diff --git a/doc/salome/gui/GEOM/images/add_dimension.png b/doc/salome/gui/GEOM/images/add_dimension.png new file mode 100644 index 000000000..a632eba82 Binary files /dev/null and b/doc/salome/gui/GEOM/images/add_dimension.png differ diff --git a/doc/salome/gui/GEOM/images/dialog.png b/doc/salome/gui/GEOM/images/dialog.png index 09459032f..c46b6b571 100755 Binary files a/doc/salome/gui/GEOM/images/dialog.png and b/doc/salome/gui/GEOM/images/dialog.png differ diff --git a/doc/salome/gui/GEOM/images/dimensions_preview.png b/doc/salome/gui/GEOM/images/dimensions_preview.png new file mode 100644 index 000000000..004a05014 Binary files /dev/null and b/doc/salome/gui/GEOM/images/dimensions_preview.png differ diff --git a/doc/salome/gui/GEOM/images/pref15.png b/doc/salome/gui/GEOM/images/pref15.png index 82189e99d..c4b2cac4d 100755 Binary files a/doc/salome/gui/GEOM/images/pref15.png and b/doc/salome/gui/GEOM/images/pref15.png differ diff --git a/doc/salome/gui/GEOM/input/add_dimension.doc b/doc/salome/gui/GEOM/input/add_dimension.doc new file mode 100644 index 000000000..691132280 --- /dev/null +++ b/doc/salome/gui/GEOM/input/add_dimension.doc @@ -0,0 +1,44 @@ +/*! + +\page add_dimension_page Add Dimension + +\image html add_dimension.png + +The dialog is opened from \ref managing_dimensions_page "Manage Dimensions" dialog when "Add" button is clicked. +This dialog allows creating measurement dimension for the selected geometrical object. +The following types of dimensions can be constructed: + + +Being constructed, the dimension is positioned by application such that the user is able to see it from the most appropriate angle of view. +The application selects one of the best matching planes allowed for the dimension. If extending the dimension by increasing length of flyouts +make sense, then the application extends the flyouts for a default value specified on the \ref geometry_preferences_page "geometry preference dialog". + +Once constructed, the geometrical properties of dimension preview (flyout, plane) become interactively editable in OCC viewer. +For the description of interactive operations please refer to corresponding section at \ref managing_dimensions_page "Manage Dimensions" page. + +The legnth dimension can be constructed in three ways: as length on edge, as length between two points and as length between two parallel lines. +In order to construct the dimension, the selected geometry should met the following conditions: + + +The diameter dimension can be constructed for the following geometry types: + + +The angle dimension can be constructed in two ways: as angle between two edges, as angle by three points. +The following conditions should be met: + + +*/ diff --git a/doc/salome/gui/GEOM/input/geometry_preferences.doc b/doc/salome/gui/GEOM/input/geometry_preferences.doc index bfce50129..6ad3270cb 100644 --- a/doc/salome/gui/GEOM/input/geometry_preferences.doc +++ b/doc/salome/gui/GEOM/input/geometry_preferences.doc @@ -49,6 +49,20 @@ predefined materials. + + -\n Or to check their integrity: +\n To check their integrity: +\n Or to measure dimensions of the shape elements: + + + \n Our TUI Scripts show how to use \ref tui_measurement_tools_page "Measurement Tools" with TUI commands. diff --git a/doc/salome/gui/GEOM/input/viewing_geom_obj.doc b/doc/salome/gui/GEOM/input/viewing_geom_obj.doc index 774dbaac2..b6b5a4f4e 100644 --- a/doc/salome/gui/GEOM/input/viewing_geom_obj.doc +++ b/doc/salome/gui/GEOM/input/viewing_geom_obj.doc @@ -59,6 +59,8 @@ geometrical object. TUI Command: sg.DisplayOnly(ID) \image html image33.png +
  • Show all dimensions - shows all of the persistent dimensions created for the selected geometrical object.
  • +
  • Hide all dimensions - hides all of the persistent dimensions created for the selected geometrical object.
  • Dump view - exports an object from the viewer in bmp, png, jpg or jpeg image format.
  • Change background - allows to redefine the background diff --git a/resources/SalomeApp.xml.in b/resources/SalomeApp.xml.in index 2fb47511b..269d3b366 100644 --- a/resources/SalomeApp.xml.in +++ b/resources/SalomeApp.xml.in @@ -69,13 +69,14 @@ - - - - - - - + + + + + + + + diff --git a/src/GEOMGUI/GEOMGUI_DimensionProperty.cxx b/src/GEOMGUI/GEOMGUI_DimensionProperty.cxx index c9ca8337f..0191e9c23 100644 --- a/src/GEOMGUI/GEOMGUI_DimensionProperty.cxx +++ b/src/GEOMGUI/GEOMGUI_DimensionProperty.cxx @@ -47,6 +47,7 @@ void GEOMGUI_DimensionProperty::Length::Init( const Handle(AIS_LengthDimension)& Flyout = theIO->GetFlyout(); TextHPos = theIO->DimensionAspect()->TextHorizontalPosition(); TextVPos = theIO->DimensionAspect()->TextVerticalPosition(); + ArrowPos = theIO->DimensionAspect()->ArrowOrientation(); } //================================================================================= @@ -68,6 +69,7 @@ void GEOMGUI_DimensionProperty::Length::Update( Handle(AIS_LengthDimension)& the Handle(Prs3d_DimensionAspect) aStyle = new Prs3d_DimensionAspect(); aStyle->SetTextHorizontalPosition( TextHPos ); aStyle->SetTextVerticalPosition( TextVPos ); + aStyle->SetArrowOrientation( ArrowPos ); theIO->SetDimensionAspect( aStyle ); } @@ -99,7 +101,8 @@ bool GEOMGUI_DimensionProperty::Length::operator == (const Length& theOther) con if ( Flyout != theOther.Flyout || TextHPos != theOther.TextHPos - || TextVPos != theOther.TextVPos ) + || TextVPos != theOther.TextVPos + || ArrowPos != theOther.ArrowPos ) { return false; } @@ -121,6 +124,7 @@ void GEOMGUI_DimensionProperty::Diameter::Init( const Handle(AIS_DiameterDimensi Flyout = theIO->GetFlyout(); TextHPos = theIO->DimensionAspect()->TextHorizontalPosition(); TextVPos = theIO->DimensionAspect()->TextVerticalPosition(); + ArrowPos = theIO->DimensionAspect()->ArrowOrientation(); } //================================================================================= @@ -154,6 +158,7 @@ void GEOMGUI_DimensionProperty::Diameter::Update( Handle(AIS_DiameterDimension)& Handle(Prs3d_DimensionAspect) aStyle = new Prs3d_DimensionAspect(); aStyle->SetTextHorizontalPosition( TextHPos ); aStyle->SetTextVerticalPosition( TextVPos ); + aStyle->SetArrowOrientation( ArrowPos ); theIO->SetDimensionAspect( aStyle ); } @@ -189,7 +194,8 @@ bool GEOMGUI_DimensionProperty::Diameter::operator == (const Diameter& theOther) if ( Flyout != theOther.Flyout || TextHPos != theOther.TextHPos - || TextVPos != theOther.TextVPos ) + || TextVPos != theOther.TextVPos + || ArrowPos != theOther.ArrowPos ) { return false; } @@ -212,6 +218,7 @@ void GEOMGUI_DimensionProperty::Angle::Init( const Handle(AIS_AngleDimension)& t Flyout = theIO->GetFlyout(); TextHPos = theIO->DimensionAspect()->TextHorizontalPosition(); TextVPos = theIO->DimensionAspect()->TextVerticalPosition(); + ArrowPos = theIO->DimensionAspect()->ArrowOrientation(); } //================================================================================= @@ -233,6 +240,7 @@ void GEOMGUI_DimensionProperty::Angle::Update( Handle(AIS_AngleDimension)& theIO Handle(Prs3d_DimensionAspect) aStyle = new Prs3d_DimensionAspect(); aStyle->SetTextHorizontalPosition( TextHPos ); aStyle->SetTextVerticalPosition( TextVPos ); + aStyle->SetArrowOrientation( ArrowPos ); theIO->SetDimensionAspect( aStyle ); } @@ -257,7 +265,8 @@ bool GEOMGUI_DimensionProperty::Angle::operator == (const Angle& theOther) const if ( Flyout != theOther.Flyout || TextHPos != theOther.TextHPos - || TextVPos != theOther.TextVPos ) + || TextVPos != theOther.TextVPos + || ArrowPos != theOther.ArrowPos ) { return false; } @@ -311,6 +320,15 @@ GEOMGUI_DimensionProperty::GEOMGUI_DimensionProperty( const GEOMGUI_DimensionPro } } +//================================================================================= +// function : Init constructor +// purpose : +//================================================================================= +GEOMGUI_DimensionProperty::GEOMGUI_DimensionProperty( SalomeApp_Study* theStudy, const std::string& theEntry ) +{ + LoadFromAttribute( theStudy, theEntry ); +} + //================================================================================= // function : Destructor // purpose : @@ -463,6 +481,8 @@ void GEOMGUI_DimensionProperty::AddRecord( const RecordPtr& theRecord ) //================================================================================= void GEOMGUI_DimensionProperty::RemoveRecord( const int theIndex ) { + myNames.remove( theIndex ); + myVisibility.remove( theIndex ); myRecords.remove( theIndex ); } @@ -472,6 +492,8 @@ void GEOMGUI_DimensionProperty::RemoveRecord( const int theIndex ) //================================================================================= void GEOMGUI_DimensionProperty::Clear() { + myNames.clear(); + myVisibility.clear(); myRecords.clear(); } @@ -480,8 +502,8 @@ void GEOMGUI_DimensionProperty::Clear() // purpose : //================================================================================= void GEOMGUI_DimensionProperty::SetRecord( const int theIndex, - const Handle(AIS_Dimension)& theIO, - const gp_Ax3& theLCS ) + const Handle(AIS_Dimension)& theIO, + const gp_Ax3& theLCS ) { int aType = TypeFromIO( theIO ); @@ -588,7 +610,7 @@ int GEOMGUI_DimensionProperty::GetType( const int theIndex ) const // purpose : //================================================================================= void GEOMGUI_DimensionProperty::LoadFromAttribute( SalomeApp_Study* theStudy, - const std::string& theEntry ) + const std::string& theEntry ) { Clear(); @@ -647,13 +669,16 @@ void GEOMGUI_DimensionProperty::LoadFromAttribute( SalomeApp_Study* theStudy, aLength->TextHPos = (Prs3d_DimensionTextHorizontalPosition)(int)aPacked[it++]; aLength->TextVPos = (Prs3d_DimensionTextVerticalPosition) (int)aPacked[it++]; - // point 1 [9,10,11] + // arrow flags [9] + aLength->ArrowPos = (Prs3d_DimensionArrowOrientation) (int)aPacked[it++]; + + // point 1 [10,11,12] Standard_Real aFirstX = aPacked[it++]; Standard_Real aFirstY = aPacked[it++]; Standard_Real aFirstZ = aPacked[it++]; aLength->FirstPoint = gp_Pnt( aFirstX, aFirstY, aFirstZ ); - // point 2 [12,13,14] + // point 2 [13,14,15] Standard_Real aSecondX = aPacked[it++]; Standard_Real aSecondY = aPacked[it++]; Standard_Real aSecondZ = aPacked[it++]; @@ -681,22 +706,25 @@ void GEOMGUI_DimensionProperty::LoadFromAttribute( SalomeApp_Study* theStudy, aDiam->TextHPos = (Prs3d_DimensionTextHorizontalPosition)(int)aPacked[it++]; aDiam->TextVPos = (Prs3d_DimensionTextVerticalPosition) (int)aPacked[it++]; - // circle location [9,10,11] + // arrow flags [9] + aDiam->ArrowPos = (Prs3d_DimensionArrowOrientation) (int)aPacked[it++]; + + // circle location [10,11,12] Standard_Real aLocX = (Standard_Real) aPacked[it++]; Standard_Real aLocY = (Standard_Real) aPacked[it++]; Standard_Real aLocZ = (Standard_Real) aPacked[it++]; - // circle normal [12,13,14] + // circle normal [13,14,15] Standard_Real aNormX = (Standard_Real) aPacked[it++]; Standard_Real aNormY = (Standard_Real) aPacked[it++]; Standard_Real aNormZ = (Standard_Real) aPacked[it++]; - // x-direction [15,16,17] + // x-direction [16,17,18] Standard_Real aXDirX = (Standard_Real) aPacked[it++]; Standard_Real aXDirY = (Standard_Real) aPacked[it++]; Standard_Real aXDirZ = (Standard_Real) aPacked[it++]; - // radius [18] + // radius [19] Standard_Real aRadius = (Standard_Real) aPacked[it++]; gp_Ax2 anAx( gp_Pnt( aLocX, aLocY, aLocZ ), @@ -720,22 +748,24 @@ void GEOMGUI_DimensionProperty::LoadFromAttribute( SalomeApp_Study* theStudy, anAngle->TextHPos = (Prs3d_DimensionTextHorizontalPosition)(int)aPacked[it++]; anAngle->TextVPos = (Prs3d_DimensionTextVerticalPosition) (int)aPacked[it++]; - // point 1 [5,6,7] + // arrow flags [5] + anAngle->ArrowPos = (Prs3d_DimensionArrowOrientation) (int)aPacked[it++]; + + // point 1 [6,7,8] Standard_Real aFirstX = (Standard_Real) aPacked[it++]; Standard_Real aFirstY = (Standard_Real) aPacked[it++]; Standard_Real aFirstZ = (Standard_Real) aPacked[it++]; - // point 2 [8,9,10] + // point 2 [9,10,11] Standard_Real aSecondX = (Standard_Real) aPacked[it++]; Standard_Real aSecondY = (Standard_Real) aPacked[it++]; Standard_Real aSecondZ = (Standard_Real) aPacked[it++]; - // center [11,12,13] + // center [12,13,14] Standard_Real aCenterX = (Standard_Real) aPacked[it++]; Standard_Real aCenterY = (Standard_Real) aPacked[it++]; Standard_Real aCenterZ = (Standard_Real) aPacked[it++]; - // points point 1 [4-6], point 2 [7-9], center [10-12] anAngle->FirstPoint = gp_Pnt( aFirstX, aFirstY, aFirstZ ); anAngle->SecondPoint = gp_Pnt( aSecondX, aSecondY, aSecondZ ); anAngle->CenterPoint = gp_Pnt( aCenterX, aCenterY, aCenterZ ); @@ -756,7 +786,7 @@ void GEOMGUI_DimensionProperty::LoadFromAttribute( SalomeApp_Study* theStudy, // purpose : //================================================================================= void GEOMGUI_DimensionProperty::SaveToAttribute( SalomeApp_Study *theStudy, - const std::string &theEntry ) + const std::string &theEntry ) { _PTR(SObject) aSObj = theStudy->studyDS()->FindObjectID( theEntry ); if ( !aSObj ) @@ -806,12 +836,15 @@ void GEOMGUI_DimensionProperty::SaveToAttribute( SalomeApp_Study *theStudy, aPacked.push_back( (double) aProps->TextHPos ); aPacked.push_back( (double) aProps->TextVPos ); - // point 1 [9,10,11] + // arrow flags [9] + aPacked.push_back( (double) aProps->ArrowPos ); + + // point 1 [10,11,12] aPacked.push_back( (double) aProps->FirstPoint.X() ); aPacked.push_back( (double) aProps->FirstPoint.Y() ); aPacked.push_back( (double) aProps->FirstPoint.Z() ); - // point 2 [12,13,14] + // point 2 [13,14,15] aPacked.push_back( (double) aProps->SecondPoint.X() ); aPacked.push_back( (double) aProps->SecondPoint.Y() ); aPacked.push_back( (double) aProps->SecondPoint.Z() ); @@ -837,22 +870,25 @@ void GEOMGUI_DimensionProperty::SaveToAttribute( SalomeApp_Study *theStudy, aPacked.push_back( (double) aProps->TextHPos ); aPacked.push_back( (double) aProps->TextVPos ); - // circle location [9,10,11] + // arrow flags [9] + aPacked.push_back( (double) aProps->ArrowPos ); + + // circle location [10,11,12] aPacked.push_back( (double) aProps->Circle.Location().X() ); aPacked.push_back( (double) aProps->Circle.Location().Y() ); aPacked.push_back( (double) aProps->Circle.Location().Z() ); - // circle normal [12,13,14] + // circle normal [13,14,15] aPacked.push_back( (double) aProps->Circle.Axis().Direction().X() ); aPacked.push_back( (double) aProps->Circle.Axis().Direction().Y() ); aPacked.push_back( (double) aProps->Circle.Axis().Direction().Z() ); - // x-direction [15,16,17] + // x-direction [16,17,18] aPacked.push_back( (double) aProps->Circle.XAxis().Direction().X() ); aPacked.push_back( (double) aProps->Circle.XAxis().Direction().Y() ); aPacked.push_back( (double) aProps->Circle.XAxis().Direction().Z() ); - // radius [18] + // radius [19] aPacked.push_back( (double) aProps->Circle.Radius() ); break; } @@ -868,17 +904,20 @@ void GEOMGUI_DimensionProperty::SaveToAttribute( SalomeApp_Study *theStudy, aPacked.push_back( (double) aProps->TextHPos ); aPacked.push_back( (double) aProps->TextVPos ); - // point 1 [5,6,7] + // arrow flags [5] + aPacked.push_back( (double) aProps->ArrowPos ); + + // point 1 [6,7,8] aPacked.push_back( (double) aProps->FirstPoint.X() ); aPacked.push_back( (double) aProps->FirstPoint.Y() ); aPacked.push_back( (double) aProps->FirstPoint.Z() ); - // point 2 [8,9,10] + // point 2 [9,10,11] aPacked.push_back( (double) aProps->SecondPoint.X() ); aPacked.push_back( (double) aProps->SecondPoint.Y() ); aPacked.push_back( (double) aProps->SecondPoint.Z() ); - // center [11,12,13] + // center [12,13,14] aPacked.push_back( (double) aProps->CenterPoint.X() ); aPacked.push_back( (double) aProps->CenterPoint.Y() ); aPacked.push_back( (double) aProps->CenterPoint.Z() ); diff --git a/src/GEOMGUI/GEOMGUI_DimensionProperty.h b/src/GEOMGUI/GEOMGUI_DimensionProperty.h index f2c5f7e58..49bbcd1b7 100644 --- a/src/GEOMGUI/GEOMGUI_DimensionProperty.h +++ b/src/GEOMGUI/GEOMGUI_DimensionProperty.h @@ -53,9 +53,9 @@ class SalomeApp_Study; * (name);(is_visible);(dimension type);(dimension property list); * * The following packing scheme is used to store dimension data: - * Length: (plane)[0-3] (flyout)[4] (text flags)[5-6] (p1)[7-9] (pnt2)[10-12] - * Diam: (plane)[0-3] (flyout)[4] (text flags)[5-6] (circle loc, xdir, ydir, rad)[7-16] - * Angle: (flyout)[0] (text flags)[1-2] (p1)[3-5] (p2)[6-8] (center)[9-11] + * Length: (plane)[0-3] (flyout)[4] (text flags)[5-6] (arrow flag)[7] (p1)[8-10] (pnt2)[11-13] + * Diam: (plane)[0-3] (flyout)[4] (text flags)[5-6] (arrow flag)[7] (circle loc, xdir, ydir, rad)[8-17] + * Angle: (flyout)[0] (text flags)[1-2] (arrow flag)[3] (p1)[4-6] (p2)[7-9] (center)[10-12] */ class Standard_EXPORT GEOMGUI_DimensionProperty { @@ -109,7 +109,8 @@ public: Plane( gp::XOY() ), Flyout( 0.0 ), TextHPos( Prs3d_DTHP_Fit ), - TextVPos( Prs3d_DTVP_Center ) + TextVPos( Prs3d_DTVP_Center ), + ArrowPos( Prs3d_DAO_Fit ) {} Length( const Length& theOther ) : @@ -119,7 +120,8 @@ public: Plane( theOther.Plane ), Flyout( theOther.Flyout ), TextHPos( theOther.TextHPos ), - TextVPos( theOther.TextVPos ) + TextVPos( theOther.TextVPos ), + ArrowPos( theOther.ArrowPos ) {} ~Length() {} @@ -150,6 +152,7 @@ public: double Flyout; Prs3d_DimensionTextHorizontalPosition TextHPos; Prs3d_DimensionTextVerticalPosition TextVPos; + Prs3d_DimensionArrowOrientation ArrowPos; }; /*! @@ -162,7 +165,8 @@ public: Plane( gp::XOY() ), Flyout( 0.0 ), TextHPos( Prs3d_DTHP_Fit ), - TextVPos( Prs3d_DTVP_Center ) + TextVPos( Prs3d_DTVP_Center ), + ArrowPos( Prs3d_DAO_Fit ) {} Diameter( const Diameter& theOther ) : @@ -171,7 +175,8 @@ public: Plane( theOther.Plane ), Flyout( theOther.Flyout ), TextHPos( theOther.TextHPos ), - TextVPos( theOther.TextVPos ) + TextVPos( theOther.TextVPos ), + ArrowPos( theOther.ArrowPos ) {} ~Diameter() {} @@ -201,6 +206,7 @@ public: double Flyout; Prs3d_DimensionTextHorizontalPosition TextHPos; Prs3d_DimensionTextVerticalPosition TextVPos; + Prs3d_DimensionArrowOrientation ArrowPos; }; /*! @@ -215,7 +221,8 @@ public: CenterPoint( gp::Origin() ), Flyout( 0.0 ), TextHPos( Prs3d_DTHP_Fit ), - TextVPos( Prs3d_DTVP_Center ) + TextVPos( Prs3d_DTVP_Center ), + ArrowPos( Prs3d_DAO_Fit ) {} Angle( const Angle& theOther ) : @@ -225,7 +232,8 @@ public: CenterPoint( theOther.CenterPoint ), Flyout( theOther.Flyout ), TextHPos( theOther.TextHPos ), - TextVPos( theOther.TextVPos ) + TextVPos( theOther.TextVPos ), + ArrowPos( theOther.ArrowPos ) {} ~Angle() {} @@ -256,6 +264,7 @@ public: double Flyout; Prs3d_DimensionTextHorizontalPosition TextHPos; Prs3d_DimensionTextVerticalPosition TextVPos; + Prs3d_DimensionArrowOrientation ArrowPos; }; typedef QSharedPointer RecordPtr; @@ -272,6 +281,11 @@ public: */ GEOMGUI_DimensionProperty( const GEOMGUI_DimensionProperty& theOther ); + /*! + * \brief Constructor. Inits property from attribute. + */ + GEOMGUI_DimensionProperty( SalomeApp_Study* theStudy, const std::string& theEntry ); + /*! * \brief Destructor. */ @@ -287,6 +301,14 @@ public: */ bool operator == (const GEOMGUI_DimensionProperty &theOther) const; + /*! + * \brief Overload comparsion. + */ + bool operator != (const GEOMGUI_DimensionProperty &theOther) const + { + return !(operator == (theOther)); + } + public: /*! diff --git a/src/GEOMGUI/GEOMGUI_Selection.cxx b/src/GEOMGUI/GEOMGUI_Selection.cxx index d1bdf3767..009c1565c 100644 --- a/src/GEOMGUI/GEOMGUI_Selection.cxx +++ b/src/GEOMGUI/GEOMGUI_Selection.cxx @@ -24,6 +24,7 @@ // Author : Alexander SOLOVYOV, Open CASCADE S.A.S. (alexander.solovyov@opencascade.com) #include "GEOMGUI_Selection.h" +#include #include "GeometryGUI.h" #include "GEOM_Displayer.h" @@ -178,6 +179,10 @@ QVariant GEOMGUI_Selection::parameter( const int idx, const QString& p ) const v = isPhysicalMaterial(idx); else if ( p == "isFolder" ) v = isFolder(idx); + else if ( p == "hasHiddenDimensions" ) + v = hasHiddenDimensions(idx); + else if ( p == "hasVisibleDimensions" ) + v = hasVisibleDimensions(idx); else v = LightApp_Selection::parameter( idx, p ); @@ -682,3 +687,59 @@ bool GEOMGUI_Selection::isFolder( const int index ) const return res; } +bool GEOMGUI_Selection::hasDimensions( const int theIndex, bool& theHidden, bool& theVisible ) const +{ + SalomeApp_Study* appStudy = dynamic_cast( study() ); + + if ( !appStudy ) + { + return false; + } + + QString anEntry = entry( theIndex ); + _PTR(Study) aStudy = appStudy->studyDS(); + if ( !aStudy || anEntry.isNull() ) + { + return false; + } + + GEOMGUI_DimensionProperty aDimensions( appStudy, anEntry.toStdString() ); + + theHidden = false; + theVisible = false; + + for ( int it = 0; it < aDimensions.GetNumber(); ++it ) + { + if ( aDimensions.IsVisible( it ) ) + theVisible = true; + else + theHidden = true; + } + + return aDimensions.GetNumber() > 0; +} + +bool GEOMGUI_Selection::hasHiddenDimensions( const int theIndex ) const +{ + bool isAnyVisible = false; + bool isAnyHidden = false; + if ( !hasDimensions( theIndex, isAnyHidden, isAnyVisible ) ) + { + return false; + } + + return isAnyHidden; +} + +bool GEOMGUI_Selection::hasVisibleDimensions( const int theIndex ) const +{ + bool isAnyVisible = false; + bool isAnyHidden = false; + if ( !hasDimensions( theIndex, isAnyHidden, isAnyVisible ) ) + { + return false; + } + + return isAnyVisible; +} + diff --git a/src/GEOMGUI/GEOMGUI_Selection.h b/src/GEOMGUI/GEOMGUI_Selection.h index b2738f75f..a9c17665e 100644 --- a/src/GEOMGUI/GEOMGUI_Selection.h +++ b/src/GEOMGUI/GEOMGUI_Selection.h @@ -78,6 +78,11 @@ private: bool isComponent( const int ) const; bool isFolder( const int ) const; + + bool hasDimensions( const int, bool&, bool& ) const; + bool hasHiddenDimensions( const int ) const; + bool hasVisibleDimensions( const int ) const; + GEOM::GEOM_Object_ptr getObject( const int ) const; GEOM::GEOM_BaseObject_ptr getBaseObject( const int ) const; diff --git a/src/GEOMGUI/GEOM_Displayer.cxx b/src/GEOMGUI/GEOM_Displayer.cxx index 2683c9603..77138e280 100644 --- a/src/GEOMGUI/GEOM_Displayer.cxx +++ b/src/GEOMGUI/GEOM_Displayer.cxx @@ -1100,6 +1100,7 @@ void GEOM_Displayer::updateDimensions( const Handle(SALOME_InteractiveObject)& t aStyle->MakeUnitsDisplayed( (Standard_Boolean) isUnitsShown ); aStyle->MakeText3d( Standard_True ); aStyle->MakeTextShaded( Standard_True ); + aStyle->SetExtensionSize( aFontHeight * 0.5 ); aStyle->TextAspect()->SetHeight( aFontHeight ); aStyle->ArrowAspect()->SetLength( anArrowLength ); aStyle->LineAspect()->SetWidth( aLineWidth ); @@ -1107,6 +1108,28 @@ void GEOM_Displayer::updateDimensions( const Handle(SALOME_InteractiveObject)& t aStyle->SetTextVerticalPosition( aPrs->DimensionAspect()->TextVerticalPosition() ); aPrs->SetDimensionAspect( aStyle ); aPrs->SetPolygonOffsets( Aspect_POM_Fill, -1.0, -1.0 ); + aPrs->Attributes()->SetDimLengthDisplayUnits( aUnitsLength.toLatin1().data() ); + aPrs->Attributes()->SetDimAngleDisplayUnits( aUnitsAngle.toLatin1().data() ); + + if ( aPrs->IsKind( STANDARD_TYPE(AIS_AngleDimension) ) ) + { + // show degree symbol for dimension instead of label "deg" + if ( aUnitsAngle == "deg" ) + { + aPrs->SetSpecialSymbol(0xB0); + aPrs->SetDisplaySpecialSymbol( isUnitsShown ? AIS_DSS_After : AIS_DSS_No ); + aStyle->MakeUnitsDisplayed(Standard_False); + } + else + { + aPrs->SetDisplaySpecialSymbol(AIS_DSS_No); + aStyle->MakeUnitsDisplayed( (Standard_Boolean) isUnitsShown ); + } + } + else + { + aStyle->MakeUnitsDisplayed( (Standard_Boolean) isUnitsShown ); + } aListOfIO.Append( aPrs ); } diff --git a/src/GEOMGUI/GEOM_msg_en.ts b/src/GEOMGUI/GEOM_msg_en.ts index e62e0794d..8aade3c3d 100644 --- a/src/GEOMGUI/GEOM_msg_en.ts +++ b/src/GEOMGUI/GEOM_msg_en.ts @@ -3276,6 +3276,10 @@ Please, select face, shell or solid and try again PREF_DIMENSIONS_ANGLE_UNITS Angle measurement units + + PREF_DIMENSIONS_DEFAULT_FLYOUT + Default flyout length + PREF_DIMENSIONS_SHOW_UNITS Show units of measurement @@ -4732,6 +4736,30 @@ Please, select face, shell or solid and try again STB_MANAGE_DIMENSIONS Manage measurement dimensions of an object + + MEN_POP_SHOW_ALL_DIMENSIONS + Show all dimensions + + + STB_POP_SHOW_ALL_DIMENSIONS + Show all hidden measures (dimension) created for the object + + + TOP_POP_SHOW_ALL_DIMENSIONS + Show all hidden measures (dimension) created for the object + + + MEN_POP_HIDE_ALL_DIMENSIONS + Hide all dimensions + + + STB_POP_HIDE_ALL_DIMENSIONS + Show all visible measures (dimension) created for the object + + + TOP_POP_HIDE_ALL_DIMENSIONS + Show all visible measures (dimension) created for the object + TOP_POP_AUTO_COLOR Auto color @@ -6166,6 +6194,16 @@ Number of sketch points too small WRN_TITLE_UNSAVED Unsaved changes + + WRN_MSG_CHANGES_LOST + The unsaved changes will be lost. +Do you wish to continue? + + + WRN_MSG_CHANGES_SAVE + The unsaved changes will be lost. +Do you wish to save them? + WRN_MSG_UNSAVED The unsaved changes will be lost. diff --git a/src/GEOMGUI/GEOM_msg_fr.ts b/src/GEOMGUI/GEOM_msg_fr.ts index dd5a103c7..ee3e881d8 100644 --- a/src/GEOMGUI/GEOM_msg_fr.ts +++ b/src/GEOMGUI/GEOM_msg_fr.ts @@ -3276,6 +3276,10 @@ Choisissez une face, une coque ou un solide et essayez de nouveau PREF_DIMENSIONS_ANGLE_UNITS Angle measurement units + + PREF_DIMENSIONS_DEFAULT_FLYOUT + Default flyout length + PREF_DIMENSIONS_SHOW_UNITS Show units of measurement @@ -4732,6 +4736,30 @@ Choisissez une face, une coque ou un solide et essayez de nouveau STB_MANAGE_DIMENSIONS Manage measurement dimensions of an object + + MEN_POP_SHOW_ALL_DIMENSIONS + Show all dimensions + + + STB_POP_SHOW_ALL_DIMENSIONS + Show all hidden measures (dimension) created for the object + + + TOP_POP_SHOW_ALL_DIMENSIONS + Show all hidden measures (dimension) created for the object + + + MEN_POP_HIDE_ALL_DIMENSIONS + Hide all dimensions + + + STB_POP_HIDE_ALL_DIMENSIONS + Show all visible measures (dimension) created for the object + + + TOP_POP_HIDE_ALL_DIMENSIONS + Show all visible measures (dimension) created for the object + TOP_POP_AUTO_COLOR Couleur automatique @@ -6166,6 +6194,16 @@ Le nombre de points n'est pas suffisant WRN_TITLE_UNSAVED Unsaved changes + + WRN_MSG_CHANGES_LOST + The unsaved changes will be lost. +Do you wish to continue? + + + WRN_MSG_CHANGES_SAVE + The unsaved changes will be lost. +Do you wish to save them? + WRN_MSG_UNSAVED The unsaved changes will be lost. diff --git a/src/GEOMGUI/GEOM_msg_ja.ts b/src/GEOMGUI/GEOM_msg_ja.ts index c3b84b8f6..7837cffaf 100644 --- a/src/GEOMGUI/GEOM_msg_ja.ts +++ b/src/GEOMGUI/GEOM_msg_ja.ts @@ -3271,6 +3271,10 @@ PREF_DIMENSIONS_ANGLE_UNITS Angle measurement units + + PREF_DIMENSIONS_DEFAULT_FLYOUT + Default flyout length + PREF_DIMENSIONS_SHOW_UNITS Show units of measurement @@ -4727,6 +4731,30 @@ STB_MANAGE_DIMENSIONS Manage measurement dimensions of an object + + MEN_POP_SHOW_ALL_DIMENSIONS + Show all dimensions + + + STB_POP_SHOW_ALL_DIMENSIONS + Show all hidden measures (dimension) created for the object + + + TOP_POP_SHOW_ALL_DIMENSIONS + Show all hidden measures (dimension) created for the object + + + MEN_POP_HIDE_ALL_DIMENSIONS + Hide all dimensions + + + STB_POP_HIDE_ALL_DIMENSIONS + Show all visible measures (dimension) created for the object + + + TOP_POP_HIDE_ALL_DIMENSIONS + Show all visible measures (dimension) created for the object + TOP_POP_AUTO_COLOR 自動色 @@ -6158,6 +6186,16 @@ WRN_TITLE_UNSAVED Unsaved changes + + WRN_MSG_CHANGES_LOST + The unsaved changes will be lost. +Do you wish to continue? + + + WRN_MSG_CHANGES_SAVE + The unsaved changes will be lost. +Do you wish to save them? + WRN_MSG_UNSAVED The unsaved changes will be lost. diff --git a/src/GEOMGUI/GeometryGUI.cxx b/src/GEOMGUI/GeometryGUI.cxx index bd3e7e5c0..f8c4a8268 100644 --- a/src/GEOMGUI/GeometryGUI.cxx +++ b/src/GEOMGUI/GeometryGUI.cxx @@ -635,6 +635,8 @@ void GeometryGUI::OnGUIEvent( int id, const QVariant& theParam ) case GEOMOp::OpPointCoordinates: // MENU MEASURE - POINT COORDINATES case GEOMOp::OpCheckSelfInters: // MENU MEASURE - CHECK SELF INTERSECTIONS case GEOMOp::OpManageDimensions: // MENU MEASURE - MANAGE DIMENSIONS + case GEOMOp::OpShowAllDimensions: // POPUP MENU - SHOW ALL DIMENSIONS + case GEOMOp::OpHideAllDimensions: // POPUP MENU - HIDE ALL DIMENSIONS libName = "MeasureGUI"; break; case GEOMOp::OpGroupCreate: // MENU GROUP - CREATE @@ -1071,6 +1073,8 @@ void GeometryGUI::initialize( CAM_Application* app ) createGeomAction( GEOMOp::OpPredefMaterCustom, "POP_PREDEF_MATER_CUSTOM" ); createGeomAction( GEOMOp::OpCreateFolder, "POP_CREATE_FOLDER" ); createGeomAction( GEOMOp::OpSortChildren, "POP_SORT_CHILD_ITEMS" ); + createGeomAction( GEOMOp::OpShowAllDimensions, "POP_SHOW_ALL_DIMENSIONS" ); + createGeomAction( GEOMOp::OpHideAllDimensions, "POP_HIDE_ALL_DIMENSIONS" ); // Create actions for increase/decrease transparency shortcuts createGeomAction( GEOMOp::OpIncrTransparency, "", "", 0, false, @@ -1588,6 +1592,14 @@ void GeometryGUI::initialize( CAM_Application* app ) mgr->insert( action(GEOMOp::OpShowOnlyChildren ), -1, -1 ); // display only children mgr->setRule(action(GEOMOp::OpShowOnlyChildren ), (canDisplay + "and ($type in {%1}) and client='ObjectBrowser' and hasChildren=true").arg( types ), QtxPopupMgr::VisibleRule ); + QString aDimensionRule = "($component={'GEOM'}) and selcount=1 and isVisible and type='Shape' and %1"; + + mgr->insert( separator(), -1, -1 ); // ----------- + mgr->insert( action( GEOMOp::OpShowAllDimensions ), -1, -1 ); // show all dimensions + mgr->setRule( action( GEOMOp::OpShowAllDimensions ), aDimensionRule.arg( "hasHiddenDimensions" ), QtxPopupMgr::VisibleRule ); + mgr->insert( action( GEOMOp::OpHideAllDimensions ), -1, -1 ); // hide all dimensions + mgr->setRule( action( GEOMOp::OpHideAllDimensions ), aDimensionRule.arg( "hasVisibleDimensions" ), QtxPopupMgr::VisibleRule ); + mgr->insert( separator(), -1, -1 ); // ----------- mgr->insert( action( GEOMOp::OpUnpublishObject ), -1, -1 ); // Unpublish object mgr->setRule( action( GEOMOp::OpUnpublishObject ), QString("client='ObjectBrowser' and $type in {'Shape' 'Group' 'Field' 'FieldStep'} and selcount>0"), QtxPopupMgr::VisibleRule ); @@ -2375,11 +2387,19 @@ void GeometryGUI::createPreferences() setPreferenceProperty( aDimLineWidthId, "min", 1 ); setPreferenceProperty( aDimLineWidthId, "max", 5 ); - addPreference( tr( "PREF_DIMENSIONS_FONT_HEIGHT" ), aDimGroupId, - LightApp_Preferences::DblSpin, "Geometry", "dimensions_font_height" ); + int aDimFontHeightId = addPreference( tr( "PREF_DIMENSIONS_FONT_HEIGHT" ), aDimGroupId, + LightApp_Preferences::DblSpin, "Geometry", "dimensions_font_height" ); - addPreference( tr( "PREF_DIMENSIONS_ARROW_LENGTH" ), aDimGroupId, - LightApp_Preferences::IntSpin, "Geometry", "dimensions_arrow_length" ); + setPreferenceProperty( aDimFontHeightId, "min", 1e-9 ); + setPreferenceProperty( aDimFontHeightId, "max", 1e+9 ); + setPreferenceProperty( aDimFontHeightId, "precision", 9 ); + + int aDimArrLengthId = addPreference( tr( "PREF_DIMENSIONS_ARROW_LENGTH" ), aDimGroupId, + LightApp_Preferences::DblSpin, "Geometry", "dimensions_arrow_length" ); + + setPreferenceProperty( aDimArrLengthId, "min", 1e-9 ); + setPreferenceProperty( aDimArrLengthId, "max", 1e+9 ); + setPreferenceProperty( aDimArrLengthId, "precision", 9 ); int aLengthUnitsId = addPreference( tr( "PREF_DIMENSIONS_LENGTH_UNITS" ), aDimGroupId, LightApp_Preferences::Selector, "Geometry", "dimensions_length_units" ); @@ -2404,6 +2424,13 @@ void GeometryGUI::createPreferences() setPreferenceProperty( aLengthUnitsId, "strings", aListOfLengthUnits ); setPreferenceProperty( anAngUnitsId, "strings", aListOfAngUnits ); + int aDimDefFlyout = addPreference( tr( "PREF_DIMENSIONS_DEFAULT_FLYOUT" ), aDimGroupId, + LightApp_Preferences::DblSpin, "Geometry", "dimensions_default_flyout" ); + + setPreferenceProperty( aDimDefFlyout, "min", 1e-9 ); + setPreferenceProperty( aDimDefFlyout, "max", 1e+9 ); + setPreferenceProperty( aDimDefFlyout, "precision", 9 ); + int isoGroup = addPreference( tr( "PREF_ISOS" ), tabId ); setPreferenceProperty( isoGroup, "columns", 2 ); int isoU = addPreference( tr( "PREF_ISOS_U" ), isoGroup, diff --git a/src/GEOMGUI/GeometryGUI_Operations.h b/src/GEOMGUI/GeometryGUI_Operations.h index d24ba7d8e..d63d3c7fd 100644 --- a/src/GEOMGUI/GeometryGUI_Operations.h +++ b/src/GEOMGUI/GeometryGUI_Operations.h @@ -190,6 +190,8 @@ namespace GEOMOp { OpCheckSelfInters = 5012, // MENU MEASURES - CHECK SELF INTERSECTIONS OpGetNonBlocks = 5013, // MENU MEASURES - GET NON BLOCKS OpManageDimensions = 5014, // MENU MEASURES - MANAGE DIMENSIONS + OpShowAllDimensions = 5015, // POPUP MENU - SHOW ALL DIMENSIONS + OpHideAllDimensions = 5016, // POPUP MENU - HIDE ALL DIMENSIONS // GroupGUI --------------------//-------------------------------- OpGroupCreate = 6000, // MENU GROUP - CREATE OpGroupEdit = 6001, // MENU GROUP - EDIT diff --git a/src/MeasureGUI/MeasureGUI.cxx b/src/MeasureGUI/MeasureGUI.cxx index e079e74bc..dea595628 100644 --- a/src/MeasureGUI/MeasureGUI.cxx +++ b/src/MeasureGUI/MeasureGUI.cxx @@ -28,8 +28,14 @@ #include #include "GeometryGUI_Operations.h" + +#include + +#include +#include #include #include +#include #include "MeasureGUI_PropertiesDlg.h" // Method PROPERTIES #include "MeasureGUI_CenterMassDlg.h" // Method CENTER MASS @@ -124,6 +130,12 @@ bool MeasureGUI::OnGUIEvent( int theCommandID, SUIT_Desktop* parent ) case GEOMOp::OpManageDimensions: dlg = new MeasureGUI_ManageDimensionsDlg( getGeometryGUI(), parent ); break; // MANAGE DIMENSIONS + case GEOMOp::OpShowAllDimensions: + ChangeDimensionsVisibility( true ); + break; // SHOW ALL DIMENSIONS + case GEOMOp::OpHideAllDimensions: + ChangeDimensionsVisibility( false ); + break; // HIDE ALL DIMENSIONS default: app->putInfo( tr( "GEOM_PRP_COMMAND" ).arg( theCommandID ) ); break; @@ -136,6 +148,56 @@ bool MeasureGUI::OnGUIEvent( int theCommandID, SUIT_Desktop* parent ) return true; } +//======================================================================= +// function : ChangeDimensionsVisibility +// purpose : +//======================================================================= +void MeasureGUI::ChangeDimensionsVisibility( const bool theIsVisible ) +{ + SalomeApp_Application* anApp = getGeometryGUI()->getApp(); + if (!anApp) + { + return; + } + + SalomeApp_Study* anActiveStudy = dynamic_cast( anApp->activeStudy() ); + if ( !anActiveStudy ) + { + return; + } + + LightApp_SelectionMgr* aSelMgr = anApp->selectionMgr(); + if ( !aSelMgr ) + { + return; + } + + SALOME_ListIO aListIO; + aSelMgr->selectedObjects( aListIO ); + if ( aListIO.Extent() != 1 ) + { + return; + } + + Handle(SALOME_InteractiveObject) anIObject = aListIO.First(); + if ( !anIObject->hasEntry() ) + { + return; + } + + SUIT_OverrideCursor(); + + GEOMGUI_DimensionProperty aDimensions( anActiveStudy, anIObject->getEntry() ); + + for ( int anIt = 0; anIt < aDimensions.GetNumber(); ++anIt ) + { + aDimensions.SetVisible( anIt, theIsVisible ); + } + + aDimensions.SaveToAttribute( anActiveStudy, anIObject->getEntry() ); + + GEOM_Displayer( anActiveStudy ).Redisplay( anIObject, true ); +} //===================================================================================== // EXPORTED METHODS diff --git a/src/MeasureGUI/MeasureGUI.h b/src/MeasureGUI/MeasureGUI.h index 4ab843810..fc909da1d 100644 --- a/src/MeasureGUI/MeasureGUI.h +++ b/src/MeasureGUI/MeasureGUI.h @@ -46,6 +46,9 @@ public: ~MeasureGUI(); bool OnGUIEvent( int, SUIT_Desktop* ); + + // Show/hide all dimension created for object + void ChangeDimensionsVisibility( const bool theIsVisible ); }; #endif // MEASUREGUI_H diff --git a/src/MeasureGUI/MeasureGUI_CreateDimensionDlg.cxx b/src/MeasureGUI/MeasureGUI_CreateDimensionDlg.cxx index 4daaf6039..5da50d8a3 100644 --- a/src/MeasureGUI/MeasureGUI_CreateDimensionDlg.cxx +++ b/src/MeasureGUI/MeasureGUI_CreateDimensionDlg.cxx @@ -34,6 +34,9 @@ #include #include +#include +#include +#include #include #include #include @@ -127,7 +130,13 @@ MeasureGUI_CreateDimensionDlg::MeasureGUI_CreateDimensionDlg( const GEOM::GeomOb myDimensionInteractor = new MeasureGUI_DimensionInteractor( theGUI, theParent ); + myDiameterArgs->setVisible( false ); + myAngleArgs ->setVisible( false ); + myLengthArgs ->setVisible( true ); + Init(); + + setHelpFileName("add_dimension_page.html"); } //================================================================================= @@ -404,6 +413,7 @@ void MeasureGUI_CreateDimensionDlg::StartLocalEditing() anAISContext->SetZLayer( myDimension, myEditingLayer ); anAISContext->Activate( myDimension, AIS_DSM_Line ); anAISContext->Activate( myDimension, AIS_DSM_Text ); + anAISContext->Redisplay( myDimension ); } //================================================================================= @@ -434,14 +444,15 @@ void MeasureGUI_CreateDimensionDlg::StopLocalEditing() //================================================================================= void MeasureGUI_CreateDimensionDlg::Init() { + myDimension = NULL; + StopLocalEditing(); erasePreview(); - myDiameterArgs->setVisible( false ); - myAngleArgs ->setVisible( false ); - myLengthArgs ->setVisible( true ); + myDiameterArgs->Reset(); myLengthArgs->Reset(); + myAngleArgs->Reset(); myRBGroup->button( TypeButtonID_Length )->click(); } @@ -461,11 +472,28 @@ Handle(AIS_Dimension) MeasureGUI_CreateDimensionDlg::CreateDimension() int aLineWidth = aResMgr->integerValue( "Geometry", "dimensions_line_width", 1 ); double aFontHeight = aResMgr->doubleValue ( "Geometry", "dimensions_font_height", 10 ); double anArrowLength = aResMgr->doubleValue ( "Geometry", "dimensions_arrow_length", 5 ); + double aDefFlyout = aResMgr->doubleValue ( "Geometry", "dimensions_default_flyout", 20 ); bool isUnitsShown = aResMgr->booleanValue( "Geometry", "dimensions_show_units", false ); QString aUnitsLength = aResMgr->stringValue ( "Geometry", "dimensions_length_units", "m" ); QString aUnitsAngle = aResMgr->stringValue ( "Geometry", "dimensions_angle_units", "deg" ); - MeasureGUI_DimensionCreateTool aTool( myGeomGUI ); + OCCViewer_ViewWindow* anActiveView = NULL; + + SalomeApp_Application* anApp = myGeomGUI->getApp(); + + if ( anApp ) + { + OCCViewer_ViewManager* aViewMgr = (OCCViewer_ViewManager*) anApp->getViewManager( OCCViewer_Viewer::Type(), false ); + if ( aViewMgr ) + { + anActiveView = (OCCViewer_ViewWindow*) aViewMgr->getActiveView(); + } + } + + MeasureGUI_DimensionCreateTool aTool; + + aTool.Settings.DefaultFlyout = aDefFlyout; + aTool.Settings.ActiveView = anActiveView ? anActiveView->getViewPort()->getView() : NULL; switch ( getConstructorId() ) { @@ -559,9 +587,33 @@ Handle(AIS_Dimension) MeasureGUI_CreateDimensionDlg::CreateDimension() aStyle->MakeUnitsDisplayed( (Standard_Boolean) isUnitsShown ); aStyle->MakeText3d( Standard_True ); aStyle->MakeTextShaded( Standard_True ); + aStyle->SetExtensionSize( aFontHeight * 0.5 ); aStyle->TextAspect()->SetHeight( aFontHeight ); aStyle->ArrowAspect()->SetLength( anArrowLength ); aStyle->LineAspect()->SetWidth( aLineWidth ); + + if ( aDimensionIO->IsKind( STANDARD_TYPE(AIS_AngleDimension) ) ) + { + // show degree symbol for dimension instead of label "deg" + if ( aUnitsAngle == "deg" ) + { + aDimensionIO->SetSpecialSymbol(0xB0); + aDimensionIO->SetDisplaySpecialSymbol( isUnitsShown ? AIS_DSS_After : AIS_DSS_No ); + aStyle->MakeUnitsDisplayed(Standard_False); + } + else + { + aDimensionIO->SetDisplaySpecialSymbol(AIS_DSS_No); + aStyle->MakeUnitsDisplayed( (Standard_Boolean) isUnitsShown ); + } + } + else + { + aStyle->MakeUnitsDisplayed( (Standard_Boolean) isUnitsShown ); + } + + aDimensionIO->Attributes()->SetDimLengthDisplayUnits( aUnitsLength.toLatin1().data() ); + aDimensionIO->Attributes()->SetDimAngleDisplayUnits( aUnitsAngle.toLatin1().data() ); aDimensionIO->SetDimensionAspect( aStyle ); aDimensionIO->SetPolygonOffsets( Aspect_POM_Fill, -1.0, -1.0 ); diff --git a/src/MeasureGUI/MeasureGUI_DimensionCreateTool.cxx b/src/MeasureGUI/MeasureGUI_DimensionCreateTool.cxx index c32d0c9ca..087e3e810 100644 --- a/src/MeasureGUI/MeasureGUI_DimensionCreateTool.cxx +++ b/src/MeasureGUI/MeasureGUI_DimensionCreateTool.cxx @@ -41,14 +41,28 @@ // OCCT includes #include #include +#include #include +#include #include +#include +#include +#include +#include +#include +#include #include #include +#include #include +#include #include #include #include +#include +#include +#include +#include #include #include #include @@ -58,36 +72,38 @@ #include #include #include +#include #include -#include #include //================================================================================= // function : Constructor // purpose : //================================================================================= -MeasureGUI_DimensionCreateTool::MeasureGUI_DimensionCreateTool( GeometryGUI* theGeomGUI ) -: myGeomGUI( theGeomGUI ) +MeasureGUI_DimensionCreateTool::MeasureGUI_DimensionCreateTool() { + Settings.DefaultFlyout = 0.0; + Settings.ActiveView = NULL; } //================================================================================= // function : LengthOnEdge // purpose : //================================================================================= -Handle(AIS_LengthDimension) MeasureGUI_DimensionCreateTool::LengthOnEdge( const GEOM::GeomObjPtr& theEdge ) +Handle(AIS_LengthDimension) MeasureGUI_DimensionCreateTool::LengthOnEdge( const GEOM::GeomObjPtr& theMeasuredObj ) const { /* ---------------------------------------------------------------- * * get the edge and parent shape * * ---------------------------------------------------------------- */ - TopoDS_Shape aShapeEdge; - TopoDS_Shape aShapeMain; - if ( !GEOMBase::GetShape( theEdge.get(), aShapeEdge ) ) + TopoDS_Shape aMeasuredShape; + TopoDS_Shape aMainShape; + if ( !GEOMBase::GetShape( theMeasuredObj.operator ->(), aMeasuredShape ) ) { return NULL; } - if ( !GEOMBase::GetShape( GetMainShape( theEdge ).get(), aShapeMain ) ) + + if ( !GEOMBase::GetShape( GetMainShape( theMeasuredObj ).get(), aMainShape ) ) { return NULL; } @@ -96,7 +112,7 @@ Handle(AIS_LengthDimension) MeasureGUI_DimensionCreateTool::LengthOnEdge( const /* check the input geometry */ /* ------------------------------------------------- */ - TopoDS_Edge anEdge = TopoDS::Edge( aShapeEdge ); + TopoDS_Edge anEdge = TopoDS::Edge( aMeasuredShape ); TopoDS_Vertex aVertex1; TopoDS_Vertex aVertex2; @@ -109,59 +125,85 @@ Handle(AIS_LengthDimension) MeasureGUI_DimensionCreateTool::LengthOnEdge( const return NULL; } - /* ------------------------------------------------- * - * compose list of possible flyout directions * - * ------------------------------------------------- */ + /* ------------------------- * + * position the dimension + * ------------------------- */ Bnd_Box aBnd; - BRepBndLib::AddClose( aShapeMain, aBnd ); + BRepBndLib::AddClose( aMainShape, aBnd ); - TColgp_SequenceOfDir aSeqOfFlyout; - ChooseLengthFlyoutsFromShape( aSeqOfFlyout, anEdge, aShapeMain ); - ChooseLengthFlyoutsFromBnd( aSeqOfFlyout, aPnt1, aPnt2, aBnd ); - if ( aSeqOfFlyout.IsEmpty() ) + // get face sides + TopTools_IndexedDataMapOfShapeListOfShape aRelationMap; + TopExp::MapShapesAndAncestors( aMainShape, TopAbs_EDGE, TopAbs_FACE, aRelationMap ); + const TopTools_ListOfShape& aRelatedFaces = aRelationMap.FindFromKey( anEdge ); + + gp_Vec aFaceN1( gp::Origin(), gp::Origin() ); + gp_Vec aFaceN2( gp::Origin(), gp::Origin() ); + gp_Vec aFaceS1( gp::Origin(), gp::Origin() ); + gp_Vec aFaceS2( gp::Origin(), gp::Origin() ); + + gp_Pnt aMiddlePnt = gp_Pnt( ( aPnt1.XYZ() + aPnt2.XYZ() ) * 0.5 ); + + TopTools_ListIteratorOfListOfShape aFaceIt( aRelatedFaces ); + + // get face side directions + if ( aFaceIt.More() ) { - return NULL; - } + TopoDS_Face aFace = TopoDS::Face( aFaceIt.Value() ); - gp_Dir aPointDir = gce_MakeDir( aPnt1, aPnt2 ); - - // make planes for dimension presentation according to flyout directions - NCollection_Sequence aSeqOfPlanes; - for ( Standard_Integer aFlyoutIt = 1; aFlyoutIt <= aSeqOfFlyout.Length(); ++aFlyoutIt ) - { - gp_Pln aPlane( aPnt1, aPointDir ^ aSeqOfFlyout.Value( aFlyoutIt ) ); - aSeqOfPlanes.Append( aPlane ); - } - - /* --------------------------------------------------------------------- * - * select best matching dimension plane for view projection * - * --------------------------------------------------------------------- */ - - OCCViewer_ViewWindow* anActiveView = NULL; - - if ( myGeomGUI != NULL ) - { - SalomeApp_Application* anApp = myGeomGUI->getApp(); - if ( !anApp ) + gp_Dir aSideDir; + if ( GetFaceSide( aFace, anEdge, aSideDir ) ) { - OCCViewer_ViewManager* aViewMgr = (OCCViewer_ViewManager*) anApp->getViewManager( OCCViewer_Viewer::Type(), false ); - if ( aViewMgr ) - { - anActiveView = (OCCViewer_ViewWindow*) aViewMgr->getActiveView(); - } + aFaceS1 = aSideDir; + } + + Handle(Geom_Surface) aSurface = BRep_Tool::Surface( aFace ); + + Standard_Real aU = 0.0, aV = 0.0; + GeomLib_Tool::Parameters( aSurface, aMiddlePnt, Precision::Confusion(), aU, aV ); + + gp_Dir aNorm; + if ( GeomLib::NormEstim( aSurface, gp_Pnt2d( aU, aV ), Precision::Confusion(), aNorm ) <= 1 ) + { + aFaceN1 = aFace.Orientation() == TopAbs_REVERSED ? -aNorm : aNorm; + } + + aFaceIt.Next(); + } + + if ( aFaceIt.More() ) + { + TopoDS_Face aFace = TopoDS::Face( aFaceIt.Value() ); + + gp_Dir aSideDir; + if ( GetFaceSide( aFace, anEdge, aSideDir ) ) + { + aFaceS2 = aSideDir; + } + + Handle(Geom_Surface) aSurface = BRep_Tool::Surface( aFace ); + + Standard_Real aU = 0.0, aV = 0.0; + GeomLib_Tool::Parameters( aSurface, aMiddlePnt, Precision::Confusion(), aU, aV ); + + gp_Dir aNorm; + if ( GeomLib::NormEstim( aSurface, gp_Pnt2d( aU, aV ), Precision::Confusion(), aNorm ) <= 1 ) + { + aFaceN2 = aFace.Orientation() == TopAbs_REVERSED ? -aNorm : aNorm; } } - gp_Pln aChoosenPlane = anActiveView - ? SelectPlaneForProjection( aSeqOfPlanes, anActiveView->getViewPort()->getView() ) - : aSeqOfPlanes.First(); + gp_Pln aPln; + PositionLength( aBnd, aFaceN1, aFaceN2, aFaceS1, aFaceS2, aPnt1, aPnt2, aPln ); - /* ------------------------------------------------------------------------------------ * - * construct interactive presentation * - * ------------------------------------------------------------------------------------ */ + /* --------------------------------------------------------- * + * construct the dimension for the best selected position + * --------------------------------------------------------- */ + + Handle(AIS_LengthDimension) aDimension = new AIS_LengthDimension( anEdge, aPln ); + + aDimension->SetFlyout( Settings.DefaultFlyout ); - Handle(AIS_LengthDimension) aDimension = new AIS_LengthDimension( anEdge, aChoosenPlane ); if ( !aDimension->IsValid() ) { return NULL; @@ -174,45 +216,155 @@ Handle(AIS_LengthDimension) MeasureGUI_DimensionCreateTool::LengthOnEdge( const // function : LengthByPoints // purpose : //================================================================================= -Handle(AIS_LengthDimension) MeasureGUI_DimensionCreateTool::LengthByPoints( const GEOM::GeomObjPtr& thePoint1, - const GEOM::GeomObjPtr& thePoint2 ) +Handle(AIS_LengthDimension) MeasureGUI_DimensionCreateTool::LengthByPoints( const GEOM::GeomObjPtr& theMeasuredObj1, + const GEOM::GeomObjPtr& theMeasuredObj2 ) const { - TopoDS_Shape aFirstSh; - if ( !GEOMBase::GetShape( thePoint1.operator ->(), aFirstSh ) ) + /* ---------------------------------------------------------------- * + * get the edge and parent shape * + * ---------------------------------------------------------------- */ + + TopoDS_Shape aMeasuredShape1; + TopoDS_Shape aMeasuredShape2; + TopoDS_Shape aMainShape; + + if ( !GEOMBase::GetShape( theMeasuredObj1.operator ->(), aMeasuredShape1 ) ) { return NULL; } - TopoDS_Shape aSecondSh; - if ( !GEOMBase::GetShape( thePoint2.operator ->(), aSecondSh ) ) + if ( !GEOMBase::GetShape( theMeasuredObj2.operator ->(), aMeasuredShape2 ) ) { return NULL; } - TopoDS_Vertex aFirstVertex = TopoDS::Vertex( aFirstSh ); - TopoDS_Vertex aSecondVertex = TopoDS::Vertex( aSecondSh ); - - gp_Pnt aPnt1 = BRep_Tool::Pnt( aFirstVertex ); - gp_Pnt aPnt2 = BRep_Tool::Pnt( aSecondVertex ); - - gp_Vec aDir( aPnt1, aPnt2 ); - gp_Dir aUnitVecs[] = { gp::DZ(), gp::DY(), gp::DX() }; - int aUnitVecIt = 0; - for ( ; aUnitVecIt < 3; ++aUnitVecIt ) + if ( !GEOMBase::GetShape( GetMainShape( theMeasuredObj1 ).get(), aMainShape ) ) { - if ( aDir.Dot( aUnitVecs[aUnitVecIt] ) <= 0.5 ) + return NULL; + } + + /* ------------------------------------------------- */ + /* check the input geometry */ + /* ------------------------------------------------- */ + + TopoDS_Vertex aVertex1 = TopoDS::Vertex( aMeasuredShape1 ); + TopoDS_Vertex aVertex2 = TopoDS::Vertex( aMeasuredShape2 ); + + gp_Pnt aPnt1 = BRep_Tool::Pnt( aVertex1 ); + gp_Pnt aPnt2 = BRep_Tool::Pnt( aVertex2 ); + if ( aPnt1.Distance( aPnt2 ) <= Precision::Confusion() ) + { + return NULL; + } + + /* ------------------------- * + * position the dimension + * ------------------------- */ + + Bnd_Box aBnd; + BRepBndLib::AddClose( aMainShape, aBnd ); + + // check whether the points share same edge + TopExp_Explorer anEdgeExp( aMainShape, TopAbs_EDGE, TopAbs_EDGE ); + for ( ; anEdgeExp.More(); anEdgeExp.Next() ) + { + TopoDS_Vertex anEdgeV1; + TopoDS_Vertex anEdgeV2; + TopExp::Vertices( TopoDS::Edge( anEdgeExp.Current() ), anEdgeV1, anEdgeV2 ); + gp_Pnt anEdgePnt1 = BRep_Tool::Pnt( anEdgeV1 ); + gp_Pnt anEdgePnt2 = BRep_Tool::Pnt( anEdgeV2 ); + + if ( aPnt1.Distance( anEdgePnt1 ) <= Precision::Confusion() ) { - break; + if ( aPnt2.Distance( anEdgePnt2 ) <= Precision::Confusion() ) + { + break; + } + } + + if ( aPnt2.Distance( anEdgePnt1 ) <= Precision::Confusion() ) + { + if ( aPnt1.Distance( anEdgePnt2 ) <= Precision::Confusion() ) + { + break; + } } } - gp_Pnt aPnt3 = aPnt2.Translated( aUnitVecs[aUnitVecIt] ); + gp_Vec aFaceN1( gp::Origin(), gp::Origin() ); + gp_Vec aFaceN2( gp::Origin(), gp::Origin() ); + gp_Vec aFaceS1( gp::Origin(), gp::Origin() ); + gp_Vec aFaceS2( gp::Origin(), gp::Origin() ); - GC_MakePlane aMkPlane( aPnt1, aPnt2, aPnt3 ); - Handle(Geom_Plane) aPlane = aMkPlane.Value(); + // have shared edge + if ( anEdgeExp.More() ) + { + TopoDS_Edge anEdge = TopoDS::Edge( anEdgeExp.Current() ); + TopTools_IndexedDataMapOfShapeListOfShape aRelationMap; + TopExp::MapShapesAndAncestors( aMainShape, TopAbs_EDGE, TopAbs_FACE, aRelationMap ); + const TopTools_ListOfShape& aRelatedFaces = aRelationMap.FindFromKey( anEdge ); - // check whether it is possible to compute valid dimension - Handle(AIS_LengthDimension) aDimension = new AIS_LengthDimension ( aFirstVertex, aSecondVertex, aPlane->Pln() ); + gp_Pnt aMiddlePnt = gp_Pnt( ( aPnt1.XYZ() + aPnt2.XYZ() ) * 0.5 ); + + TopTools_ListIteratorOfListOfShape aFaceIt( aRelatedFaces ); + + // get face side directions + if ( aFaceIt.More() ) + { + TopoDS_Face aFace = TopoDS::Face( aFaceIt.Value() ); + + gp_Dir aSideDir; + if ( GetFaceSide( aFace, anEdge, aSideDir ) ) + { + aFaceS1 = aSideDir; + } + + Handle(Geom_Surface) aSurface = BRep_Tool::Surface( aFace ); + + Standard_Real aU = 0.0, aV = 0.0; + GeomLib_Tool::Parameters( aSurface, aMiddlePnt, Precision::Confusion(), aU, aV ); + + gp_Dir aNorm; + if ( GeomLib::NormEstim( aSurface, gp_Pnt2d( aU, aV ), Precision::Confusion(), aNorm ) <= 1 ) + { + aFaceN1 = aFace.Orientation() == TopAbs_REVERSED ? -aNorm : aNorm; + } + + aFaceIt.Next(); + } + + if ( aFaceIt.More() ) + { + TopoDS_Face aFace = TopoDS::Face( aFaceIt.Value() ); + + gp_Dir aSideDir; + if ( GetFaceSide( aFace, anEdge, aSideDir ) ) + { + aFaceS2 = aSideDir; + } + + Handle(Geom_Surface) aSurface = BRep_Tool::Surface( aFace ); + + Standard_Real aU = 0.0, aV = 0.0; + GeomLib_Tool::Parameters( aSurface, aMiddlePnt, Precision::Confusion(), aU, aV ); + + gp_Dir aNorm; + if ( GeomLib::NormEstim( aSurface, gp_Pnt2d( aU, aV ), Precision::Confusion(), aNorm ) <= 1 ) + { + aFaceN2 = aFace.Orientation() == TopAbs_REVERSED ? -aNorm : aNorm; + } + } + } + + gp_Pln aPln; + PositionLength( aBnd, aFaceN1, aFaceN2, aFaceS1, aFaceS2, aPnt1, aPnt2, aPln ); + + /* --------------------------------------------------------- * + * construct the dimension for the best selected position + * --------------------------------------------------------- */ + + Handle(AIS_LengthDimension) aDimension = new AIS_LengthDimension( aPnt1, aPnt2, aPln ); + + aDimension->SetFlyout( Settings.DefaultFlyout ); if ( !aDimension->IsValid() ) { @@ -227,7 +379,7 @@ Handle(AIS_LengthDimension) MeasureGUI_DimensionCreateTool::LengthByPoints( cons // purpose : //================================================================================= Handle(AIS_LengthDimension) MeasureGUI_DimensionCreateTool::LengthByParallelEdges( const GEOM::GeomObjPtr& theEdge1, - const GEOM::GeomObjPtr& theEdge2 ) + const GEOM::GeomObjPtr& theEdge2 ) const { TopoDS_Shape aFirstSh; if ( !GEOMBase::GetShape( theEdge1.operator ->(), aFirstSh ) ) @@ -258,6 +410,8 @@ Handle(AIS_LengthDimension) MeasureGUI_DimensionCreateTool::LengthByParallelEdge // check whether it is possible to compute valid dimension Handle(AIS_LengthDimension) aDimension = new AIS_LengthDimension ( aFirstEdge, aSecondEdge, aPlane->Pln() ); + aDimension->SetFlyout( Settings.DefaultFlyout ); + if ( !aDimension->IsValid() ) { return NULL; @@ -270,23 +424,250 @@ Handle(AIS_LengthDimension) MeasureGUI_DimensionCreateTool::LengthByParallelEdge // function : Diameter // purpose : //================================================================================= -Handle(AIS_DiameterDimension) MeasureGUI_DimensionCreateTool::Diameter( const GEOM::GeomObjPtr& theShape ) +Handle(AIS_DiameterDimension) MeasureGUI_DimensionCreateTool::Diameter( const GEOM::GeomObjPtr& theMeasuredObj ) const { - TopoDS_Shape aShape; - if ( !GEOMBase::GetShape( theShape.operator ->(), aShape ) ) + /* ------------------------------------------------ * + * get the shape and its parent (if exist) * + * ------------------------------------------------ */ + + TopoDS_Shape aMeasuredShape; + TopoDS_Shape aMainShape; + if ( !GEOMBase::GetShape( theMeasuredObj.operator ->(), aMeasuredShape ) ) { return NULL; } - if ( aShape.ShapeType() != TopAbs_EDGE && - aShape.ShapeType() != TopAbs_FACE && - aShape.ShapeType() != TopAbs_WIRE ) + if ( !GEOMBase::GetShape( GetMainShape( theMeasuredObj ).get(), aMainShape ) ) { return NULL; } - // check whether it is possible to compute dimension on the passed geometry - Handle(AIS_DiameterDimension) aDimension = new AIS_DiameterDimension( aShape ); + Bnd_Box aBnd; + BRepBndLib::AddClose( aMainShape, aBnd ); + + /* ------------------------------------------------ * + * get the dimension construction arguments * + * ------------------------------------------------ */ + + Handle(Geom_Circle) aCircle; + + Standard_Real aPmin = 0, aPmax = 2 * M_PI; + + gp_Vec aFaceN( gp_Pnt(0.0, 0.0, 0.0), gp_Pnt(0.0, 0.0, 0.0) ); + + switch ( aMeasuredShape.ShapeType() ) + { + case TopAbs_FACE: + { + TopoDS_Face aMeasuredFace = TopoDS::Face(aMeasuredShape); + + BRepAdaptor_Surface aSurf( aMeasuredFace ); + + Standard_Real aVmin = aSurf.FirstVParameter(); + Standard_Real aVmax = aSurf.LastVParameter(); + + // get arguments of closed sphere + if ( aSurf.GetType() == GeomAbs_Sphere ) + { + if ( !aSurf.IsUClosed() || !aSurf.IsVClosed() ) + { + return NULL; + } + + // take circle in XOY plane from sphere + gp_Sphere aSphere = aSurf.Sphere(); + gp_Ax2 anAx2 = gp_Ax2( aSphere.Location(), gp::DZ() ); + aCircle = new Geom_Circle( anAx2, aSphere.Radius() ); + break; + } + + + // get arguments of closed torus + if ( aSurf.GetType() == GeomAbs_Torus ) + { + if ( !aSurf.IsUClosed() || !aSurf.IsVClosed() ) + { + return NULL; + } + + gp_Torus aTorus = aSurf.Torus(); + gp_Ax2 anAx2 = aTorus.Position().Ax2(); + aCircle = new Geom_Circle( anAx2, aTorus.MinorRadius() ); + break; + } + + // get arguments of closed cone + if ( aSurf.GetType() == GeomAbs_Cone ) + { + if ( !aSurf.IsUClosed() || !aSurf.IsVClosed() ) + { + return NULL; + } + + gp_Cone aCone = aSurf.Cone(); + gp_Ax2 anAx2 = aCone.Position().Ax2(); + aCircle = new Geom_Circle( anAx2, aCone.RefRadius() ); + + aFaceN = aCone.SemiAngle() > 0.0 + ? anAx2.Axis().Direction() + : -anAx2.Axis().Direction(); + break; + } + + // get arguments of closed/opened cylinder + if ( aSurf.GetType() == GeomAbs_Cylinder ) + { + Handle(Geom_Curve) aCurve = aSurf.Surface().Surface()->VIso( (aVmax + aVmin) * 0.5 ); + + if ( aCurve->IsKind( STANDARD_TYPE( Geom_Circle ) ) ) + { + aPmin = aSurf.FirstUParameter(); + aPmax = aSurf.LastUParameter(); + aCircle = Handle(Geom_Circle)::DownCast( aCurve ); + } + else if ( aCurve->IsKind( STANDARD_TYPE( Geom_TrimmedCurve ) ) ) + { + Handle(Geom_TrimmedCurve) aTrimmedCurve = Handle(Geom_TrimmedCurve)::DownCast( aCurve ); + aPmin = aTrimmedCurve->FirstParameter(); + aPmax = aTrimmedCurve->LastParameter(); + + aCircle = Handle(Geom_Circle)::DownCast( aTrimmedCurve ); + } + + break; + } + + // face containing edge? + TopExp_Explorer anExp( aMeasuredShape, TopAbs_EDGE ); + if ( !anExp.More() ) + { + return NULL; + } + + TopoDS_Shape anExpEdge = anExp.Current(); + if ( anExpEdge.IsNull() ) + { + return NULL; + } + + // only a single edge is expected + anExp.Next(); + if ( anExp.More() ) + { + return NULL; + } + + // do not break, go to edge checking + aMeasuredShape = anExpEdge; + } + + case TopAbs_EDGE: + { + TopoDS_Edge aMeasureEdge = TopoDS::Edge( aMeasuredShape ); + + BRepAdaptor_Curve aCurve(aMeasureEdge); + + if ( aCurve.GetType() != GeomAbs_Circle ) + { + return NULL; + } + + aPmin = aCurve.FirstParameter(); + aPmax = aCurve.LastParameter(); + + aCircle = new Geom_Circle( aCurve.Circle() ); + + // check if there is an parent face containing the edge + TopTools_IndexedDataMapOfShapeListOfShape aShapeMap; + TopExp::MapShapesAndAncestors( aMainShape, TopAbs_EDGE, TopAbs_FACE, aShapeMap ); + const TopTools_ListOfShape& aFaces = aShapeMap.FindFromKey( aMeasureEdge ); + + TopTools_ListIteratorOfListOfShape aFaceIt( aFaces ); + for ( ; aFaceIt.More(); aFaceIt.Next() ) + { + Handle(Geom_Surface) aSurface = BRep_Tool::Surface( TopoDS::Face( aFaceIt.Value() ) ); + + gp_Pnt aCircCenter = aCircle->Circ().Location(); + Standard_Real aCircU = 0.0, aCircV = 0.0; + GeomLib_Tool::Parameters( aSurface, aCircCenter, Precision::Confusion(), aCircU, aCircV ); + + gp_Dir aNorm; + if ( GeomLib::NormEstim( aSurface, gp_Pnt2d( aCircU, aCircV ), Precision::Confusion(), aNorm ) > 1 ) + { + break; + } + + if ( aNorm.Angle( aCircle->Circ().Axis().Direction() ) > M_PI * 0.25 ) + { + continue; + } + + aFaceN = gp_Vec( aNorm ); + } + } + break; + } + + if ( aCircle.IsNull() ) + { + return NULL; + } + + ElCLib::AdjustPeriodic( 0.0, M_PI * 2, Precision::PConfusion(), aPmin, aPmax ); + + /* ------------------------- * + * position the dimension + * ------------------------- */ + + gp_Pnt aPnt1; + gp_Pnt aPnt2; + gp_Pln aPln; + + // diameter for closed circle + if ( Abs( ( aPmax - aPmin ) - M_PI * 2 ) <= Precision::PConfusion() ) + { + PositionDiameter( aBnd, aFaceN, aCircle->Circ(), aPnt1, aPnt2, aPln ); + } + // diameter for half-closed circle + else if ( Abs( aPmax - aPmin ) > M_PI ) + { + Standard_Real anAnchor = aPmin + ( ( aPmax - aPmin ) - M_PI ) * 0.5; + + PositionDiameter( aBnd, aFaceN, aCircle->Circ(), anAnchor, aPln ); + + aPnt1 = ElCLib::Value( anAnchor, aCircle->Circ() ); + aPnt2 = ElCLib::Value( anAnchor + M_PI, aCircle->Circ() ); + } + // diameter for less than half-closed circle + else + { + Standard_Real anAnchor = aPmin + ( aPmax - aPmin ) * 0.5; + + PositionDiameter( aBnd, aFaceN, aCircle->Circ(), anAnchor, aPln ); + + aPnt1 = ElCLib::Value( anAnchor, aCircle->Circ() ); + aPnt2 = ElCLib::Value( anAnchor + M_PI, aCircle->Circ() ); + } + + /* --------------------------------------------------------- * + * construct the dimension for the best selected position + * --------------------------------------------------------- */ + + gp_Pnt aCircP = aCircle->Circ().Location(); + gp_Dir aCircN = aCircle->Circ().Axis().Direction(); + gp_Dir aCircX = gce_MakeDir( aPnt1, aPnt2 ); + Standard_Real aCircR = aCircle->Circ().Radius(); + + // construct closed circle as base for the diameter dimension + gp_Circ aRuledCirc = gce_MakeCirc( gp_Ax2( aCircP, aCircN, aCircX ), aCircR ); + + Handle(AIS_DiameterDimension) aDimension = new AIS_DiameterDimension( aRuledCirc, aPln ); + + // if flyout is extended in tangent direction to circle, the default flyout value is used + // if flyout is extended in plane of circle, the zero flyout value is choosen initially + Standard_Real aFlyout = aCircN.IsParallel( aPln.Axis().Direction(), Precision::Angular() ) ? 0.0 : Settings.DefaultFlyout; + + aDimension->SetFlyout(aFlyout); if ( !aDimension->IsValid() ) { @@ -301,7 +682,7 @@ Handle(AIS_DiameterDimension) MeasureGUI_DimensionCreateTool::Diameter( const GE // purpose : //================================================================================= Handle(AIS_AngleDimension) MeasureGUI_DimensionCreateTool::AngleByTwoEdges( const GEOM::GeomObjPtr& theEdge1, - const GEOM::GeomObjPtr& theEdge2 ) + const GEOM::GeomObjPtr& theEdge2 ) const { /* --------------------------------------------------- */ /* get construction and parent shapes */ @@ -358,6 +739,8 @@ Handle(AIS_AngleDimension) MeasureGUI_DimensionCreateTool::AngleByTwoEdges( cons aDimension = new AIS_AngleDimension( aSecondPoint, aCenterPoint, aFirstPoint ); } + aDimension->SetFlyout( Settings.DefaultFlyout ); + return aDimension; } @@ -367,7 +750,7 @@ Handle(AIS_AngleDimension) MeasureGUI_DimensionCreateTool::AngleByTwoEdges( cons //================================================================================= Handle(AIS_AngleDimension) MeasureGUI_DimensionCreateTool::AngleByThreePoints( const GEOM::GeomObjPtr& thePoint1, const GEOM::GeomObjPtr& thePoint2, - const GEOM::GeomObjPtr& thePoint3 ) + const GEOM::GeomObjPtr& thePoint3 ) const { TopoDS_Shape aFirstSh; if ( !GEOMBase::GetShape( thePoint1.operator ->(), aFirstSh ) ) @@ -407,73 +790,248 @@ Handle(AIS_AngleDimension) MeasureGUI_DimensionCreateTool::AngleByThreePoints( c } //================================================================================= -// function : ChooseLengthFlyoutsFromShape -// purpose : +// function : PositionLength +// purpose : The method provides preliminary positioning algorithm for +// for length dimensions measuring the length between two points. +// Parameters: +// theBnd [in] - the bounding box of the main shape +// theFaceN1 [in] - the normal to a first face of edge length (if any) +// theFaceN2 [in] - the normal to a second face of edge length (if any) +// theFaceS1 [in] - the side vector from a first face of edge length (if any) +// theFaceS2 [in] - the side vector from a second face of edge length (if any) +// thePnt1 [in] - the first measured point +// thePnt2 [in] - the last measured point +// The method selects flyout plane to best match the current +// view projection. If edge length is constructed, then the flyout +// can go in line with sides of faces, normal to the faces, or +// aligned to XOY, YOZ, ZOX planes. //================================================================================= -void MeasureGUI_DimensionCreateTool::ChooseLengthFlyoutsFromShape( TColgp_SequenceOfDir& theDirs, - const TopoDS_Vertex& theVertex1, - const TopoDS_Vertex& theVertex2, - const TopoDS_Shape& theShape ) +void MeasureGUI_DimensionCreateTool::PositionLength( const Bnd_Box& theBnd, + const gp_Vec& theFaceN1, + const gp_Vec& theFaceN2, + const gp_Vec& theFaceS1, + const gp_Vec& theFaceS2, + const gp_Pnt& thePnt1, + const gp_Pnt& thePnt2, + gp_Pln& thePln ) const { -} - -//================================================================================= -// function : ChooseLengthFlyoutsFromShape -// purpose : -//================================================================================= -void MeasureGUI_DimensionCreateTool::ChooseLengthFlyoutsFromShape( TColgp_SequenceOfDir& theDirs, - const TopoDS_Edge& theEdge, - const TopoDS_Shape& theShape ) -{ - TopTools_IndexedDataMapOfShapeListOfShape aRelationMap; - TopExp::MapShapesAndAncestors( theShape, TopAbs_EDGE, TopAbs_FACE, aRelationMap ); - const TopTools_ListOfShape& aRelatedFaces = aRelationMap.FindFromKey( theEdge ); - - // get face side directions - gp_Dir aSideDir; - if ( aRelatedFaces.Extent() > 0 && GetFaceSide( TopoDS::Face( aRelatedFaces.First() ), theEdge, aSideDir ) ) - { - theDirs.Append( aSideDir ); - } - if ( aRelatedFaces.Extent() > 1 && GetFaceSide( TopoDS::Face( aRelatedFaces.Last() ), theEdge, aSideDir ) ) - { - theDirs.Append( aSideDir ); - } + Standard_Boolean isFace1 = theFaceN1.Magnitude() > Precision::Confusion(); + Standard_Boolean isFace2 = theFaceN2.Magnitude() > Precision::Confusion(); + gp_Vec anAverageN( gp_Pnt(0.0, 0.0, 0.0), gp_Pnt(0.0, 0.0, 0.0) ); // get average direction in case of two non-sharp angled faces - if ( theDirs.Length() == 2 ) + if ( isFace1 && isFace2 ) { - const gp_Dir& aDir1 = theDirs.First(); - const gp_Dir& aDir2 = theDirs.Last(); - Standard_Boolean isSame = aDir1.IsParallel( aDir2, Precision::Angular() ); + Standard_Boolean isSame = theFaceN1.IsParallel( theFaceN2, Precision::Angular() ); if ( !isSame ) { - gp_Dir aReferenceDir = aDir1 ^ aDir2; + gp_Dir aReferenceDir = theFaceN1 ^ theFaceN2; // compute angle between face sides [0 - 2PI] - Standard_Real aDirAngle = aDir1.AngleWithRef( aDir2, aReferenceDir ); + Standard_Real aDirAngle = theFaceN1.AngleWithRef( theFaceN2, aReferenceDir ); if ( aDirAngle < 0 ) { aDirAngle = ( M_PI * 2.0 ) - aDirAngle; } - // non-sharp angle, use averaged direction + // non-sharp angle, use averaged directio + if ( aDirAngle > M_PI * 0.5 ) + { + anAverageN = theFaceN1 + theFaceN2; + } + if ( aDirAngle > M_PI ) { - theDirs.Clear(); - theDirs.Append( aDir1.Rotated( gp_Ax1( gp::Origin(), aReferenceDir ), aDirAngle * 0.5 ) ); + isFace1 = Standard_False; + isFace2 = Standard_False; } } } + + Standard_Boolean isAverage = anAverageN.Magnitude() > Precision::Confusion(); + + SeqOfDirs aFlyoutDirs; + if ( isFace1 ) + { + aFlyoutDirs.Append( theFaceN1 ); + aFlyoutDirs.Append( theFaceS1 ); + } + if ( isFace2 ) + { + aFlyoutDirs.Append( theFaceN2 ); + aFlyoutDirs.Append( theFaceS2 ); + } + if ( isAverage ) + { + aFlyoutDirs.Append( anAverageN ); + } + + ChooseLengthFlyoutsFromBnd( aFlyoutDirs, thePnt1, thePnt2, theBnd ); + + if ( aFlyoutDirs.IsEmpty() ) + { + return; + } + + gp_Dir aPointDir = gce_MakeDir( thePnt1, thePnt2 ); + + // make planes for dimension presentation according to flyout directions + SeqOfPlanes aSeqOfPlanes; + for ( Standard_Integer aFlyoutIt = 1; aFlyoutIt <= aFlyoutDirs.Length(); ++aFlyoutIt ) + { + gp_Pln aPlane( thePnt1, aPointDir ^ aFlyoutDirs.Value( aFlyoutIt ) ); + aSeqOfPlanes.Append( aPlane ); + } + + Handle(V3d_View) aView = Settings.ActiveView; + + thePln = !aView.IsNull() + ? SelectPlaneForProjection( aSeqOfPlanes, aView ) + : aSeqOfPlanes.First(); +} + +//================================================================================= +// function : PositionDiameter +// purpose : The method provides preliminary positioning algorithm for +// for diameter dimensions measuring the circle. +// Parameters: +// theBnd [in] - the bounding box of the shape +// theFaceN [in] - the circle face normal (can be void) +// theCirc [in] - the measured circle +// thePnt1 [out] - first dimension point +// thePnt2 [out] - second dimension point +// thePln [out] - dimension flyout plane +// The method selects points on the circle for diameter dimension and +// flyout plane to best match the current view projection (if any) +// The points are aligned to XOY, YOZ, ZOX planes. +// The flyout takes into account bounding box of main shape of face normal +// vector. The flyouts tangetial to the circle plane are directed in +// accordance with the face normal (if not-null), otherwise the flyouts +// are turned to direct to the closest border of bounding box. +//================================================================================= +void MeasureGUI_DimensionCreateTool::PositionDiameter( const Bnd_Box& theBnd, + const gp_Vec& theFaceN, + const gp_Circ& theCirc, + gp_Pnt& thePnt1, + gp_Pnt& thePnt2, + gp_Pln& thePln ) const +{ + // plane associated with custom data + struct PlaneAndSegment + { + PlaneAndSegment() {} + PlaneAndSegment(const gp_Pln& thePlane, const Segment& theSegment) : pln(thePlane), seg(theSegment) {} + operator gp_Pln () const { return pln; } + operator Segment () const { return seg; } + gp_Pln pln; + Segment seg; + }; + typedef NCollection_Sequence SeqOfPlnsAndSegments; + + // select list of measured segments aligned to projection planes + SeqOfDirs aProjectionDirs; + aProjectionDirs.Append( gp::DX() ); + aProjectionDirs.Append( gp::DY() ); + aProjectionDirs.Append( gp::DZ() ); + + SeqOfSegments aMeasureSegments = GetInPlaneSegments( theCirc, aProjectionDirs ); + + SeqOfPlnsAndSegments aSelectedPlanes; + + // select in-circle-plane direction for flyout closest to border of bounding box + for ( Standard_Integer aSegmentIt = 1; aSegmentIt <= aMeasureSegments.Length(); ++aSegmentIt ) + { + const Segment& aSegment = aMeasureSegments.Value(aSegmentIt); + + Standard_Real anAnchor = ElCLib::Parameter( theCirc, aSegment.First ); + + gp_Pln aSelectedPlane; + + PositionDiameter( theBnd, theFaceN, theCirc, anAnchor, aSelectedPlane ); + + aSelectedPlanes.Append( PlaneAndSegment( aSelectedPlane, aSegment ) ); + } + + Handle(V3d_View) aView = Settings.ActiveView; + + PlaneAndSegment aChoosenParams = !aView.IsNull() + ? SelectPlaneForProjection( aSelectedPlanes, aView ) + : aSelectedPlanes.First(); + + thePnt1 = ((Segment)aChoosenParams).First; + thePnt2 = ((Segment)aChoosenParams).Last; + thePln = ((gp_Pln)aChoosenParams); +} + +//================================================================================= +// function : PositionDiameter +// purpose : The method provides preliminary positioning algorithm for +// for diameter dimensions measuring the circle. The diameter +// dimension is bound at anchor point on the circle. +// Parameters: +// theBnd [in] the bounding box of the shape +// theFaceN [in] - the circle face normal (can be void) +// theCirc [in] - the measured circle +// theAnchorAt [in] - the anchoring parameter +// thePln [out] - dimension flyout plane +// The method selects flyout plane to best match the current +// view projection. The flyout plane can be parallel to circle, +// or tangent to it. +//================================================================================= +void MeasureGUI_DimensionCreateTool::PositionDiameter( const Bnd_Box& theBnd, + const gp_Vec& theFaceN, + const gp_Circ& theCirc, + const Standard_Real& theAnchorAt, + gp_Pln& thePln ) const +{ + gp_Dir aCircN = theCirc.Axis().Direction(); + gp_Pnt aCircP = theCirc.Location(); + + // select tangent direction for flyout closest to border of bounding box + gp_Dir aSelectedTanDir; + if ( theFaceN.Magnitude() < Precision::Confusion() ) + { + SeqOfDirs aTangentDirs; + aTangentDirs.Append( aCircN ); + aTangentDirs.Append( -aCircN ); + aSelectedTanDir = ChooseDirFromBnd( aTangentDirs, aCircP, theBnd ); + } + else + { + aSelectedTanDir = gp_Dir( theFaceN ); + } + + gp_Pnt aPnt1 = ElCLib::Value( theAnchorAt, theCirc ); + gp_Pnt aPnt2 = ElCLib::Value( theAnchorAt + M_PI, theCirc ); + + gp_Dir aSegmentDir = gce_MakeDir( aPnt1, aPnt2 ); + + SeqOfDirs aSegmentDirs; + aSegmentDirs.Append( aCircN ^ aSegmentDir ); + aSegmentDirs.Append( -aCircN ^ aSegmentDir ); + gp_Dir aSelectedSegDir = ChooseDirFromBnd( aSegmentDirs, aCircP, theBnd ); + + gp_Pln aTangentFlyout( aCircP, aSegmentDir ^ aSelectedTanDir ); + gp_Pln aCoplanarFlyout( aCircP, aSegmentDir ^ aSelectedSegDir ); + + SeqOfPlanes aSelectedPlanes; + aSelectedPlanes.Append( aTangentFlyout ); + aSelectedPlanes.Append( aCoplanarFlyout ); + + Handle(V3d_View) aView = Settings.ActiveView; + + thePln = !aView.IsNull() + ? SelectPlaneForProjection( aSelectedPlanes, aView ) + : aSelectedPlanes.First(); } //================================================================================= // function : ChooseLengthFlyoutsFromBnd // purpose : //================================================================================= -void MeasureGUI_DimensionCreateTool::ChooseLengthFlyoutsFromBnd( TColgp_SequenceOfDir& theDirs, +void MeasureGUI_DimensionCreateTool::ChooseLengthFlyoutsFromBnd( SeqOfDirs& theDirs, const gp_Pnt& thePnt1, const gp_Pnt& thePnt2, - const Bnd_Box& theBnd ) + const Bnd_Box& theBnd ) const { // compose a list of axis-aligned planes for lying-in flyouts NCollection_Sequence anAAPlanes; @@ -526,12 +1084,54 @@ void MeasureGUI_DimensionCreateTool::ChooseLengthFlyoutsFromBnd( TColgp_Sequence } } +//================================================================================= +// function : ChooseDirFromBnd +// purpose : The method chooses the best direction from the passed list of +// directions, which is closest to the bounding box border. +// Parameters: +// theCandidates [in] the list of candidate directions +// thePos [in] the position from where the directions are traced +// theBnd [in] the bounding box of main shape +//================================================================================= +gp_Dir MeasureGUI_DimensionCreateTool::ChooseDirFromBnd( const SeqOfDirs& theCandidates, + const gp_Pnt& thePos, + const Bnd_Box& theBnd ) const +{ + gp_Dir aBestDir; + + Standard_Real aBestDistance = RealLast(); + + SeqOfDirs::Iterator anIt( theCandidates ); + for ( ; anIt.More(); anIt.Next() ) + { + const gp_Dir& aDir = anIt.Value(); + + gp_Ax3 aFlyoutSpace( thePos, aDir ); + + gp_Trsf aRelativeTransform; + aRelativeTransform.SetTransformation( gp_Ax3(), aFlyoutSpace ); + Bnd_Box aRelativeBounds = theBnd.Transformed( aRelativeTransform ); + + Standard_Real aXmin, aXmax, aYmin, aYmax, aZmin, aZmax; + aRelativeBounds.Get( aXmin, aYmin, aZmin, aXmax, aYmax, aZmax ); + + if ( aYmax < aBestDistance ) + { + aBestDir = aDir; + aBestDistance = aYmax; + } + } + + return aBestDir; +} + //================================================================================= // function : SelectPlaneForProjection // purpose : Select best matching plane in current view projection //================================================================================= -gp_Pln MeasureGUI_DimensionCreateTool::SelectPlaneForProjection( const NCollection_Sequence& thePlanes, - const Handle(V3d_View)& theView ) +template +TPlane MeasureGUI_DimensionCreateTool::SelectPlaneForProjection( const NCollection_Sequence& thePlanes, + const Handle(V3d_View)& theView ) const { Quantity_Parameter U[3]; Quantity_Parameter N[3]; @@ -541,15 +1141,15 @@ gp_Pln MeasureGUI_DimensionCreateTool::SelectPlaneForProjection( const NCollecti gp_Dir aViewN( (Standard_Real)N[0], (Standard_Real)N[1], (Standard_Real)N[2] ); gp_Dir aViewU( (Standard_Real)U[0], (Standard_Real)U[1], (Standard_Real)U[2] ); - gp_Pln aBestPlane = thePlanes.First(); + TPlane aBestPlane = thePlanes.First(); Standard_Real aBestDotProduct = RealFirst(); for ( Standard_Integer aPlnIt = 1; aPlnIt <= thePlanes.Length(); ++aPlnIt ) { - const gp_Pln& aPlane = thePlanes.Value( aPlnIt ); + const TPlane& aPlane = thePlanes.Value( aPlnIt ); - Standard_Real aDotProduct = Abs( aPlane.Axis().Direction() * aViewN ); + Standard_Real aDotProduct = Abs( ((gp_Pln)aPlane).Axis().Direction() * aViewN ); // preferred plane is "view parallel" if ( aDotProduct <= aBestDotProduct ) @@ -569,7 +1169,7 @@ gp_Pln MeasureGUI_DimensionCreateTool::SelectPlaneForProjection( const NCollecti // function : GetMainShape // purpose : //================================================================================= -GEOM::GeomObjPtr MeasureGUI_DimensionCreateTool::GetMainShape( const GEOM::GeomObjPtr& theShape ) +GEOM::GeomObjPtr MeasureGUI_DimensionCreateTool::GetMainShape( const GEOM::GeomObjPtr& theShape ) const { // iterate over top-level objects to search for main shape GEOM::GeomObjPtr aMainShapeIt = theShape; @@ -584,7 +1184,7 @@ GEOM::GeomObjPtr MeasureGUI_DimensionCreateTool::GetMainShape( const GEOM::GeomO // function : GetFaceSide // purpose : //================================================================================= -bool MeasureGUI_DimensionCreateTool::GetFaceSide( const TopoDS_Face& theFace, const TopoDS_Edge& theEdge, gp_Dir& theDir ) +bool MeasureGUI_DimensionCreateTool::GetFaceSide( const TopoDS_Face& theFace, const TopoDS_Edge& theEdge, gp_Dir& theDir ) const { // get correctly oriented edge from main shape TopoDS_Edge anEdgeFromFace; @@ -648,3 +1248,44 @@ bool MeasureGUI_DimensionCreateTool::GetFaceSide( const TopoDS_Face& theFace, co theDir = gp_Dir( aTangent ) ^ aNorm; return true; } + +//================================================================================= +// function : GetInPlaneSegments +// purpose : The method finds segments crossing the passed circle, +// which lie in the passed planes. +// Parameters: +// theCirc [in] the circle to be crossed. +// thePlanes [in] the projection planes crossing the circle. +//================================================================================= +MeasureGUI_DimensionCreateTool::SeqOfSegments + MeasureGUI_DimensionCreateTool::GetInPlaneSegments( const gp_Circ& theCirc, + const SeqOfDirs& thePlanes ) const +{ + SeqOfSegments aResult; + + gp_Pnt aCircP = theCirc.Location(); + gp_Dir aCircN = theCirc.Axis().Direction(); + Standard_Real aCircR = theCirc.Radius(); + + SeqOfDirs::Iterator anIt( thePlanes ); + for ( ; anIt.More(); anIt.Next() ) + { + const gp_Dir& aDir = anIt.Value(); + + if ( aDir.IsParallel( aCircN, Precision::Angular() ) ) + { + continue; + } + + gp_Dir aIntDir = aDir ^ aCircN; + + gp_Pnt aPnt1 = gp_Pnt( aCircP.XYZ() - aIntDir.XYZ() * aCircR ); + gp_Pnt aPnt2 = gp_Pnt( aCircP.XYZ() + aIntDir.XYZ() * aCircR ); + Segment aSegment; + aSegment.First = aPnt1; + aSegment.Last = aPnt2; + aResult.Append( aSegment ); + } + + return aResult; +} diff --git a/src/MeasureGUI/MeasureGUI_DimensionCreateTool.h b/src/MeasureGUI/MeasureGUI_DimensionCreateTool.h index 978aaa915..8a396786c 100644 --- a/src/MeasureGUI/MeasureGUI_DimensionCreateTool.h +++ b/src/MeasureGUI/MeasureGUI_DimensionCreateTool.h @@ -47,60 +47,96 @@ //================================================================================= class MeasureGUI_DimensionCreateTool { + struct Segment + { + gp_Pnt First; + gp_Pnt Last; + }; + typedef NCollection_Sequence SeqOfDirs; + typedef NCollection_Sequence SeqOfPlanes; + typedef NCollection_Sequence SeqOfSegments; + public: - MeasureGUI_DimensionCreateTool( GeometryGUI* ); + MeasureGUI_DimensionCreateTool(); + + struct + { + Standard_Real DefaultFlyout; + Handle(V3d_View) ActiveView; + } Settings; /* construction methods */ public: - Handle(AIS_LengthDimension) LengthOnEdge( const GEOM::GeomObjPtr& ); + Handle(AIS_LengthDimension) LengthOnEdge( const GEOM::GeomObjPtr& ) const; Handle(AIS_LengthDimension) LengthByPoints( const GEOM::GeomObjPtr&, - const GEOM::GeomObjPtr& ); + const GEOM::GeomObjPtr& ) const; Handle(AIS_LengthDimension) LengthByParallelEdges( const GEOM::GeomObjPtr&, - const GEOM::GeomObjPtr& ); + const GEOM::GeomObjPtr& ) const; - Handle(AIS_DiameterDimension) Diameter( const GEOM::GeomObjPtr& ); + Handle(AIS_DiameterDimension) Diameter( const GEOM::GeomObjPtr& ) const; Handle(AIS_AngleDimension) AngleByTwoEdges( const GEOM::GeomObjPtr&, - const GEOM::GeomObjPtr& ); + const GEOM::GeomObjPtr& ) const; Handle(AIS_AngleDimension) AngleByThreePoints( const GEOM::GeomObjPtr&, const GEOM::GeomObjPtr&, - const GEOM::GeomObjPtr& ); + const GEOM::GeomObjPtr& ) const; + /* selecting flyout direction for length dimensions */ protected: - void ChooseLengthFlyoutsFromShape( TColgp_SequenceOfDir&, - const TopoDS_Vertex&, - const TopoDS_Vertex&, - const TopoDS_Shape& ); + void ChooseLengthFlyoutsFromBnd( SeqOfDirs&, + const gp_Pnt&, + const gp_Pnt&, + const Bnd_Box& ) const; - void ChooseLengthFlyoutsFromShape( TColgp_SequenceOfDir&, - const TopoDS_Edge&, - const TopoDS_Shape& ); - - void ChooseLengthFlyoutsFromBnd( TColgp_SequenceOfDir&, - const gp_Pnt&, - const gp_Pnt&, - const Bnd_Box& ); + gp_Dir ChooseDirFromBnd( const SeqOfDirs&, + const gp_Pnt&, + const Bnd_Box& ) const; /* selecting best flyout direction taking into account view projection */ protected: - gp_Pln SelectPlaneForProjection( const NCollection_Sequence&, - const Handle(V3d_View)& ); + template + TPlane SelectPlaneForProjection( const NCollection_Sequence&, + const Handle(V3d_View)& ) const; + +/* positioning */ +protected: + + void PositionLength( const Bnd_Box&, + const gp_Vec&, + const gp_Vec&, + const gp_Vec&, + const gp_Vec&, + const gp_Pnt&, + const gp_Pnt&, + gp_Pln& ) const; + + void PositionDiameter( const Bnd_Box&, + const gp_Vec&, + const gp_Circ&, + gp_Pnt&, + gp_Pnt&, + gp_Pln& ) const; + + void PositionDiameter( const Bnd_Box&, + const gp_Vec&, + const gp_Circ&, + const Standard_Real&, + gp_Pln& ) const; /* utility */ protected: - GEOM::GeomObjPtr GetMainShape( const GEOM::GeomObjPtr& ); + GEOM::GeomObjPtr GetMainShape( const GEOM::GeomObjPtr& ) const; bool GetFaceSide( const TopoDS_Face&, const TopoDS_Edge&, - gp_Dir& ); - -private: - GeometryGUI* myGeomGUI; + gp_Dir& ) const; + SeqOfSegments GetInPlaneSegments( const gp_Circ&, + const SeqOfDirs& ) const; }; #endif diff --git a/src/MeasureGUI/MeasureGUI_DimensionInteractor.cxx b/src/MeasureGUI/MeasureGUI_DimensionInteractor.cxx index 48b9dbda4..56b921a20 100644 --- a/src/MeasureGUI/MeasureGUI_DimensionInteractor.cxx +++ b/src/MeasureGUI/MeasureGUI_DimensionInteractor.cxx @@ -518,8 +518,9 @@ void MeasureGUI_DimensionInteractor::MoveText( const Handle(V3d_View)& theView, const gp_Dir& aPlaneN = aPlane.Axis().Direction(); - Prs3d_DimensionTextHorizontalPosition aHPos = myInteractedIO->DimensionAspect()->TextHorizontalPosition(); - Prs3d_DimensionTextVerticalPosition aVPos = myInteractedIO->DimensionAspect()->TextVerticalPosition(); + Prs3d_DimensionTextHorizontalPosition aHPos = myInteractedIO->DimensionAspect()->TextHorizontalPosition(); + Prs3d_DimensionTextVerticalPosition aVPos = myInteractedIO->DimensionAspect()->TextVerticalPosition(); + Prs3d_DimensionArrowOrientation aArrPos = myInteractedIO->DimensionAspect()->ArrowOrientation(); Standard_Real aHeight = myInteractedIO->DimensionAspect()->TextAspect()->Height() * 0.5; @@ -563,15 +564,18 @@ void MeasureGUI_DimensionInteractor::MoveText( const Handle(V3d_View)& theView, if ( aPosX < 0.0 ) { - aHPos = Prs3d_DTHP_Left; + aHPos = Prs3d_DTHP_Left; + aArrPos = Prs3d_DAO_External; } else if ( aPosX > aFirstPoint.Distance( aSecondPoint ) ) { - aHPos = Prs3d_DTHP_Right; + aHPos = Prs3d_DTHP_Right; + aArrPos = Prs3d_DAO_External; } else { - aHPos = Prs3d_DTHP_Center; + aHPos = Prs3d_DTHP_Center; + aArrPos = Prs3d_DAO_Fit; } if ( aPosY > aHeight ) @@ -636,16 +640,19 @@ void MeasureGUI_DimensionInteractor::MoveText( const Handle(V3d_View)& theView, if ( aPointAngle < -aDirAngle * 0.5 ) // outside of second dir { aHPos = Prs3d_DTHP_Left; + aArrPos = Prs3d_DAO_External; aPosY = Abs( aPointVec.Dot( aFirstDir ) ) - Abs( myInteractedIO->GetFlyout() ); } else if ( aPointAngle > aDirAngle * 0.5 ) // outside of first dir { aHPos = Prs3d_DTHP_Right; + aArrPos = Prs3d_DAO_External; aPosY = Abs( aPointVec.Dot( aSecondDir ) ) - Abs( myInteractedIO->GetFlyout() ); } else // between first and second direction { aHPos = Prs3d_DTHP_Center; + aArrPos = Prs3d_DAO_Fit; aPosY = Abs( aPointVec.Magnitude() ) - Abs( myInteractedIO->GetFlyout() ); } @@ -665,6 +672,7 @@ void MeasureGUI_DimensionInteractor::MoveText( const Handle(V3d_View)& theView, myInteractedIO->DimensionAspect()->SetTextVerticalPosition( aVPos ); myInteractedIO->DimensionAspect()->SetTextHorizontalPosition( aHPos ); + myInteractedIO->DimensionAspect()->SetArrowOrientation( aArrPos ); myInteractedIO->SetToUpdate(); myViewer->getAISContext()->Redisplay( myInteractedIO ); diff --git a/src/MeasureGUI/MeasureGUI_ManageDimensionsDlg.cxx b/src/MeasureGUI/MeasureGUI_ManageDimensionsDlg.cxx index 62b43b4e2..fb739349e 100644 --- a/src/MeasureGUI/MeasureGUI_ManageDimensionsDlg.cxx +++ b/src/MeasureGUI/MeasureGUI_ManageDimensionsDlg.cxx @@ -121,6 +121,9 @@ MeasureGUI_ManageDimensionsDlg::MeasureGUI_ManageDimensionsDlg( GeometryGUI* the connect( buttonApply(), SIGNAL( clicked() ), SLOT( ClickOnApply() ) ); connect( this, SIGNAL( finished( int ) ), SLOT( OnFinish() ) ); + + connect( myGeomGUI, SIGNAL( SignalDeactivateActiveDialog() ), this, SLOT( OnDeactivateThisDialog() ) ); + connect( myGeomGUI, SIGNAL( SignalCloseAllDialogs() ), this, SLOT( ClickOnCancel() ) ); myDimensionInteractor = new MeasureGUI_DimensionInteractor( theGUI, theParent ), @@ -130,6 +133,8 @@ MeasureGUI_ManageDimensionsDlg::MeasureGUI_ManageDimensionsDlg( GeometryGUI* the { myObjectSelector->PushButton1->click(); } + + setHelpFileName("managing_dimensions_page.html"); } //================================================================================= @@ -151,7 +156,7 @@ void MeasureGUI_ManageDimensionsDlg::StartSelection( const Selection theSelectio myCurrentSelection = theSelection; - if ( theSelection == Selection_Object && WarnUnsaved() ) + if ( theSelection == Selection_Object && AllowedToCancelChanges() ) { /* ----------------------------------------------- * * selection of object * @@ -703,7 +708,7 @@ void MeasureGUI_ManageDimensionsDlg::ClickOnOk() //================================================================================= void MeasureGUI_ManageDimensionsDlg::ClickOnCancel() { - if ( !WarnUnsaved() ) + if ( !AllowedToCancelChanges() ) { return; } @@ -781,6 +786,70 @@ void MeasureGUI_ManageDimensionsDlg::OnFinish() redisplay( myEditObject.get() ); } +//================================================================================= +// function : enterEvent() +// purpose : +//================================================================================= +void MeasureGUI_ManageDimensionsDlg::enterEvent( QEvent* ) +{ + if ( !mainFrame()->GroupConstructors->isEnabled() ) + { + OnActivateThisDialog(); + } +} + +//================================================================================= +// function : OnActivateThisDialog +// purpose : +//================================================================================= +void MeasureGUI_ManageDimensionsDlg::OnActivateThisDialog() +{ + disconnect( myGeomGUI, SIGNAL( SignalDeactivateActiveDialog() ), this, SLOT( OnDeactivateThisDialog() ) ); + GEOMBase_Skeleton::ActivateThisDialog(); + connect( myGeomGUI, SIGNAL( SignalDeactivateActiveDialog() ), this, SLOT( OnDeactivateThisDialog() ) ); + + SelectionIntoArgument( Selection_Object ); + + if ( myEditObject.isNull() ) + { + myObjectSelector->PushButton1->click(); + } +} + +//================================================================================= +// function : OnDeactivateThisDialog +// purpose : +//================================================================================= +void MeasureGUI_ManageDimensionsDlg::OnDeactivateThisDialog() +{ + if ( AllowedToSaveChanges() ) + { + ClickOnApply(); + } + + if ( !myEditObject.isNull() ) + { + SalomeApp_Study* aStudy = NULL; + SalomeApp_Application* anApp = myGeomGUI->getApp(); + if ( anApp ) + { + aStudy = dynamic_cast( anApp->activeStudy() ); + } + + if ( aStudy ) + { + aStudy->setObjectProperty( GEOM::sharedPropertiesId(), + myEditObject->GetStudyEntry(), + GEOM::propertyName( GEOM::Dimensions ), + QVariant() ); + } + + redisplay( myEditObject.get() ); + } + + GEOMBase_Skeleton::DeactivateActiveDialog(); +} + //================================================================================= // function : SetEditObject // purpose : @@ -967,26 +1036,26 @@ void MeasureGUI_ManageDimensionsDlg::PopulateList() } //================================================================================= -// function : WarnUnsaved +// function : HasUnsavedChanges // purpose : //================================================================================= -bool MeasureGUI_ManageDimensionsDlg::WarnUnsaved() +bool MeasureGUI_ManageDimensionsDlg::HasUnsavedChanges() { if ( myEditObject.isNull() ) { - return true; + return false; } SalomeApp_Application* anApp = myGeomGUI->getApp(); if ( !anApp ) { - return true; + return false; } SalomeApp_Study* aStudy = dynamic_cast( anApp->activeStudy() ); if ( !aStudy ) { - return true; + return false; } GEOMGUI_DimensionProperty aCurrentState = @@ -996,14 +1065,43 @@ bool MeasureGUI_ManageDimensionsDlg::WarnUnsaved() QVariant() ) .value(); - if ( aCurrentState == mySavedPropertyState ) + return aCurrentState != mySavedPropertyState; +} + +//================================================================================= +// function : AllowedToCancelChanges +// purpose : +//================================================================================= +bool MeasureGUI_ManageDimensionsDlg::AllowedToCancelChanges() +{ + if ( !HasUnsavedChanges() ) { return true; } int aResponse = SUIT_MessageBox::warning( this, tr( "WRN_TITLE_UNSAVED" ), - tr( "WRN_MSG_UNSAVED" ), + tr( "WRN_MSG_CHANGES_LOST" ), + QMessageBox::Ok, + QMessageBox::Cancel ); + + return aResponse == QMessageBox::Ok; +} + +//================================================================================= +// function : AllowedToSaveChanges +// purpose : +//================================================================================= +bool MeasureGUI_ManageDimensionsDlg::AllowedToSaveChanges() +{ + if ( !HasUnsavedChanges() ) + { + return false; + } + + int aResponse = SUIT_MessageBox::warning( this, + tr( "WRN_TITLE_UNSAVED" ), + tr( "WRN_MSG_CHANGES_SAVE" ), QMessageBox::Ok, QMessageBox::Cancel ); diff --git a/src/MeasureGUI/MeasureGUI_ManageDimensionsDlg.h b/src/MeasureGUI/MeasureGUI_ManageDimensionsDlg.h index 25d99b27f..91a28978f 100644 --- a/src/MeasureGUI/MeasureGUI_ManageDimensionsDlg.h +++ b/src/MeasureGUI/MeasureGUI_ManageDimensionsDlg.h @@ -79,12 +79,17 @@ protected slots: virtual void ClickOnCancel(); bool ClickOnApply(); void OnFinish(); + void OnActivateThisDialog(); + void OnDeactivateThisDialog(); /* Utils */ private: void SetEditObject( const GEOM::GeomObjPtr& ); void RestoreState(); void PopulateList(); + bool HasUnsavedChanges(); + bool AllowedToCancelChanges(); + bool AllowedToSaveChanges(); bool WarnUnsaved(); int IdFromItem( QTreeWidgetItem* theItem ); int IdFromPrs( const Handle(AIS_InteractiveObject)& theAIS ); @@ -93,6 +98,9 @@ private: void SelectInViewer( SOCC_Viewer* theViewer, const int theId ); void RedisplayObject(); +private: + void enterEvent(QEvent*); + private: enum GroupItems {