diff --git a/resources/CMakeLists.txt b/resources/CMakeLists.txt
index 7e9c9aa48..973310af6 100755
--- a/resources/CMakeLists.txt
+++ b/resources/CMakeLists.txt
@@ -107,6 +107,7 @@ SET( _res_files
line.png
line2points.png
line2faces.png
+ managedimensions.png
mindist.png
mirrorPoint.png
mirrorAxe.png
diff --git a/resources/SalomeApp.xml.in b/resources/SalomeApp.xml.in
index af5f33ef5..2fb47511b 100644
--- a/resources/SalomeApp.xml.in
+++ b/resources/SalomeApp.xml.in
@@ -68,6 +68,15 @@
+
+
+
+
+
+
+
+
+
diff --git a/resources/managedimensions.png b/resources/managedimensions.png
new file mode 100644
index 000000000..1600ecbed
Binary files /dev/null and b/resources/managedimensions.png differ
diff --git a/src/EntityGUI/EntityGUI_3DSketcherDlg.cxx b/src/EntityGUI/EntityGUI_3DSketcherDlg.cxx
index 88b730307..c486ce48c 100755
--- a/src/EntityGUI/EntityGUI_3DSketcherDlg.cxx
+++ b/src/EntityGUI/EntityGUI_3DSketcherDlg.cxx
@@ -1696,36 +1696,8 @@ Handle(AIS_AngleDimension) EntityGUI_3DSketcherDlg::createAISAngleDimension(doub
if (Abs(theAngle) < Precision::Angular() ||
aLength < Precision::Confusion())
return NULL;
-
- // Convert angles to string
- std::string Angle_str = doubleToString(theAngle);
-
- // Construction of the plane
- //gce_MakePln gce_MP2(P0, P1, P2);
- //Handle(Geom_Plane) aPlane = new Geom_Plane(gce_MP2.Value());
-
- TopoDS_Vertex V0 = BRepBuilderAPI_MakeVertex(P0);
- TopoDS_Vertex V1 = BRepBuilderAPI_MakeVertex(P1);
- TopoDS_Vertex V2 = BRepBuilderAPI_MakeVertex(P2);
-
- TopoDS_Edge anEdge1 = BRepBuilderAPI_MakeEdge(V0, V1);
- TopoDS_Edge anEdge2 = BRepBuilderAPI_MakeEdge(V0, V2);
- //Handle(AIS_AngleDimension) anIO =
- // new AIS_AngleDimension(anEdge1, anEdge2, aPlane, theAngle * M_PI / 180.,
- // TCollection_ExtendedString(Angle_str.c_str()));
- //
- //anIO->SetArrowSize((theAngle * M_PI / 180) * (aLength/20));
- //
- //SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
- //int w = resMgr->integerValue("Geometry", "measures_line_width", 1);
- //Handle(Prs3d_AngleAspect) asp = new Prs3d_AngleAspect();
- //asp->LineAspect()->SetWidth(w);
- //anIO->Attributes()->SetAngleAspect(asp);
-
- // todo : port
-
- Handle(AIS_AngleDimension) anIO = new AIS_AngleDimension( anEdge1, anEdge2 );
+ Handle(AIS_AngleDimension) anIO = new AIS_AngleDimension( P1, P0, P2 );
anIO->SetCustomValue( theAngle );
diff --git a/src/GEOMGUI/CMakeLists.txt b/src/GEOMGUI/CMakeLists.txt
index ed1bf4cf1..304d8f6f8 100755
--- a/src/GEOMGUI/CMakeLists.txt
+++ b/src/GEOMGUI/CMakeLists.txt
@@ -38,6 +38,7 @@ INCLUDE_DIRECTORIES(
${PROJECT_SOURCE_DIR}/src/Material
${PROJECT_SOURCE_DIR}/src/GEOMClient
${PROJECT_SOURCE_DIR}/src/GEOMImpl
+ ${PROJECT_SOURCE_DIR}/src/GEOMUtils
${CMAKE_CURRENT_SOURCE_DIR}
)
@@ -56,6 +57,7 @@ SET(_link_LIBRARIES
GEOMFiltersSelection
Material
GEOMImpl
+ GEOMUtils
${KERNEL_SALOMELocalTrace}
${KERNEL_SalomeDS}
${KERNEL_SalomeDSClient}
@@ -76,6 +78,7 @@ SET(GEOMGUI_HEADERS
GEOMGUI_Selection.h
GEOM_GEOMGUI.hxx
GEOMGUI_CreationInfoWdg.h
+ GEOMGUI_DimensionProperty.h
)
# header files / to be processed by moc
@@ -98,6 +101,7 @@ SET(GEOMGUI_SOURCES
GEOMGUI_OCCSelector.cxx
GEOMGUI_Selection.cxx
GEOMGUI_CreationInfoWdg.cxx
+ GEOMGUI_DimensionProperty.cxx
${_moc_SOURCES}
)
diff --git a/src/GEOMGUI/GEOMGUI_DimensionProperty.cxx b/src/GEOMGUI/GEOMGUI_DimensionProperty.cxx
new file mode 100644
index 000000000..c9ca8337f
--- /dev/null
+++ b/src/GEOMGUI/GEOMGUI_DimensionProperty.cxx
@@ -0,0 +1,918 @@
+// Copyright (C) 2007-2013 CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+// File : GEOMGUI_DimensionProperty.cxx
+// Author : Anton POLETAEV, Open CASCADE S.A.S.
+//
+
+#include "GEOMGUI_DimensionProperty.h"
+
+// OCCT includes
+#include
+#include
+
+#include
+
+//=================================================================================
+// function : Length::Init
+// purpose :
+//=================================================================================
+void GEOMGUI_DimensionProperty::Length::Init( const Handle(AIS_LengthDimension)& theIO, const gp_Ax3& theLCS )
+{
+ gp_Trsf aFromLCS;
+ aFromLCS.SetTransformation( gp_Ax3(), theLCS );
+
+ FirstPoint = theIO->FirstPoint().Transformed( aFromLCS );
+ SecondPoint = theIO->SecondPoint().Transformed( aFromLCS );
+ Plane = theIO->GetPlane().Transformed( aFromLCS );
+ Flyout = theIO->GetFlyout();
+ TextHPos = theIO->DimensionAspect()->TextHorizontalPosition();
+ TextVPos = theIO->DimensionAspect()->TextVerticalPosition();
+}
+
+//=================================================================================
+// function : Length::Update
+// purpose :
+//=================================================================================
+void GEOMGUI_DimensionProperty::Length::Update( Handle(AIS_LengthDimension)& theIO, const gp_Ax3& theLCS )
+{
+ gp_Trsf aToLCS;
+ aToLCS.SetTransformation( theLCS, gp_Ax3() );
+
+ gp_Pnt aPoint1 = FirstPoint.Transformed( aToLCS );
+ gp_Pnt aPoint2 = SecondPoint.Transformed( aToLCS );
+ gp_Pln aPlane = Plane.Transformed( aToLCS );
+
+ theIO->SetMeasuredGeometry( aPoint1, aPoint2, aPlane );
+ theIO->SetFlyout( Flyout );
+
+ Handle(Prs3d_DimensionAspect) aStyle = new Prs3d_DimensionAspect();
+ aStyle->SetTextHorizontalPosition( TextHPos );
+ aStyle->SetTextVerticalPosition( TextVPos );
+ theIO->SetDimensionAspect( aStyle );
+}
+
+//=================================================================================
+// function : Length::operator ==
+// purpose :
+//=================================================================================
+bool GEOMGUI_DimensionProperty::Length::operator == (const Length& theOther) const
+{
+ if ( FirstPoint.X() != theOther.FirstPoint.X()
+ || FirstPoint.Y() != theOther.FirstPoint.Y()
+ || FirstPoint.Z() != theOther.FirstPoint.Z()
+ || SecondPoint.X() != theOther.SecondPoint.X()
+ || SecondPoint.Y() != theOther.SecondPoint.Y()
+ || SecondPoint.Z() != theOther.SecondPoint.Z() )
+ {
+ return false;
+ }
+
+ if ( Plane.Location().X() != theOther.Plane.Location().X()
+ || Plane.Location().Y() != theOther.Plane.Location().Y()
+ || Plane.Location().Z() != theOther.Plane.Location().Z()
+ || Plane.Axis().Direction().X() != theOther.Plane.Axis().Direction().X()
+ || Plane.Axis().Direction().Y() != theOther.Plane.Axis().Direction().Y()
+ || Plane.Axis().Direction().Z() != theOther.Plane.Axis().Direction().Z() )
+ {
+ return false;
+ }
+
+ if ( Flyout != theOther.Flyout
+ || TextHPos != theOther.TextHPos
+ || TextVPos != theOther.TextVPos )
+ {
+ return false;
+ }
+
+ return true;
+}
+
+//=================================================================================
+// function : Diameter::Init
+// purpose :
+//=================================================================================
+void GEOMGUI_DimensionProperty::Diameter::Init( const Handle(AIS_DiameterDimension)& theIO, const gp_Ax3& theLCS )
+{
+ gp_Trsf aFromLCS;
+ aFromLCS.SetTransformation( gp_Ax3(), theLCS );
+
+ Circle = theIO->Circle().Transformed( aFromLCS );
+ Plane = theIO->GetPlane().Transformed( aFromLCS );
+ Flyout = theIO->GetFlyout();
+ TextHPos = theIO->DimensionAspect()->TextHorizontalPosition();
+ TextVPos = theIO->DimensionAspect()->TextVerticalPosition();
+}
+
+//=================================================================================
+// function : Diameter::Update
+// purpose :
+//=================================================================================
+void GEOMGUI_DimensionProperty::Diameter::Update( Handle(AIS_DiameterDimension)& theIO, const gp_Ax3& theLCS )
+{
+ gp_Trsf aToLCS;
+ aToLCS.SetTransformation( theLCS, gp_Ax3() );
+
+ gp_Circ aCircle = Circle.Transformed( aToLCS );
+ gp_Pln aPlane = Plane.Transformed( aToLCS );
+
+ Standard_Boolean isParallel =
+ aCircle.Axis().Direction().IsParallel( aPlane.Axis().Direction(), Precision::Angular() );
+
+ if ( isParallel )
+ {
+ theIO->UnsetCustomPlane();
+ theIO->SetMeasuredGeometry( aCircle );
+ }
+ else
+ {
+ theIO->SetCustomPlane( aPlane );
+ theIO->SetMeasuredGeometry( aCircle );
+ }
+
+ theIO->SetFlyout( Flyout );
+
+ Handle(Prs3d_DimensionAspect) aStyle = new Prs3d_DimensionAspect();
+ aStyle->SetTextHorizontalPosition( TextHPos );
+ aStyle->SetTextVerticalPosition( TextVPos );
+ theIO->SetDimensionAspect( aStyle );
+}
+
+//=================================================================================
+// function : Diameter::operator ==
+// purpose :
+//=================================================================================
+bool GEOMGUI_DimensionProperty::Diameter::operator == (const Diameter& theOther) const
+{
+ if ( Circle.Location().X() != theOther.Circle.Location().X()
+ || Circle.Location().Y() != theOther.Circle.Location().Y()
+ || Circle.Location().Z() != theOther.Circle.Location().Z()
+ || Circle.Axis().Direction().X() != theOther.Circle.Axis().Direction().X()
+ || Circle.Axis().Direction().Y() != theOther.Circle.Axis().Direction().Y()
+ || Circle.Axis().Direction().Z() != theOther.Circle.Axis().Direction().Z()
+ || Circle.XAxis().Direction().X() != theOther.Circle.XAxis().Direction().X()
+ || Circle.XAxis().Direction().Y() != theOther.Circle.XAxis().Direction().Y()
+ || Circle.XAxis().Direction().Z() != theOther.Circle.XAxis().Direction().Z()
+ || Circle.Radius() != theOther.Circle.Radius() )
+ {
+ return false;
+ }
+
+ if ( Plane.Location().X() != theOther.Plane.Location().X()
+ || Plane.Location().Y() != theOther.Plane.Location().Y()
+ || Plane.Location().Z() != theOther.Plane.Location().Z()
+ || Plane.Axis().Direction().X() != theOther.Plane.Axis().Direction().X()
+ || Plane.Axis().Direction().Y() != theOther.Plane.Axis().Direction().Y()
+ || Plane.Axis().Direction().Z() != theOther.Plane.Axis().Direction().Z() )
+ {
+ return false;
+ }
+
+ if ( Flyout != theOther.Flyout
+ || TextHPos != theOther.TextHPos
+ || TextVPos != theOther.TextVPos )
+ {
+ return false;
+ }
+
+ return true;
+}
+
+//=================================================================================
+// function : Angle::Init
+// purpose :
+//=================================================================================
+void GEOMGUI_DimensionProperty::Angle::Init( const Handle(AIS_AngleDimension)& theIO, const gp_Ax3& theLCS )
+{
+ gp_Trsf aFromLCS;
+ aFromLCS.SetTransformation( gp_Ax3(), theLCS );
+
+ FirstPoint = theIO->FirstPoint().Transformed( aFromLCS );
+ SecondPoint = theIO->SecondPoint().Transformed( aFromLCS );
+ CenterPoint = theIO->CenterPoint().Transformed( aFromLCS );
+ Flyout = theIO->GetFlyout();
+ TextHPos = theIO->DimensionAspect()->TextHorizontalPosition();
+ TextVPos = theIO->DimensionAspect()->TextVerticalPosition();
+}
+
+//=================================================================================
+// function : Angle::Update
+// purpose :
+//=================================================================================
+void GEOMGUI_DimensionProperty::Angle::Update( Handle(AIS_AngleDimension)& theIO, const gp_Ax3& theLCS )
+{
+ gp_Trsf aToLCS;
+ aToLCS.SetTransformation( theLCS, gp_Ax3() );
+
+ gp_Pnt aPoint1 = FirstPoint.Transformed( aToLCS );
+ gp_Pnt aPoint2 = CenterPoint.Transformed( aToLCS );
+ gp_Pnt aPoint3 = SecondPoint.Transformed( aToLCS );
+
+ theIO->SetMeasuredGeometry( aPoint1, aPoint2, aPoint3 );
+ theIO->SetFlyout( Flyout );
+
+ Handle(Prs3d_DimensionAspect) aStyle = new Prs3d_DimensionAspect();
+ aStyle->SetTextHorizontalPosition( TextHPos );
+ aStyle->SetTextVerticalPosition( TextVPos );
+ theIO->SetDimensionAspect( aStyle );
+}
+
+//=================================================================================
+// function : Angle::operator ==
+// purpose :
+//=================================================================================
+bool GEOMGUI_DimensionProperty::Angle::operator == (const Angle& theOther) const
+{
+ if ( FirstPoint.X() != theOther.FirstPoint.X()
+ || FirstPoint.Y() != theOther.FirstPoint.Y()
+ || FirstPoint.Z() != theOther.FirstPoint.Z()
+ || SecondPoint.X() != theOther.SecondPoint.X()
+ || SecondPoint.Y() != theOther.SecondPoint.Y()
+ || SecondPoint.Z() != theOther.SecondPoint.Z()
+ || CenterPoint.X() != theOther.CenterPoint.X()
+ || CenterPoint.Y() != theOther.CenterPoint.Y()
+ || CenterPoint.Z() != theOther.CenterPoint.Z() )
+ {
+ return false;
+ }
+
+ if ( Flyout != theOther.Flyout
+ || TextHPos != theOther.TextHPos
+ || TextVPos != theOther.TextVPos )
+ {
+ return false;
+ }
+
+ return true;
+}
+
+//=================================================================================
+// function : Constructor
+// purpose :
+//=================================================================================
+GEOMGUI_DimensionProperty::GEOMGUI_DimensionProperty()
+{
+}
+
+//=================================================================================
+// function : Copy constructor
+// purpose :
+//=================================================================================
+GEOMGUI_DimensionProperty::GEOMGUI_DimensionProperty( const GEOMGUI_DimensionProperty& theOther )
+{
+ const VectorOfVisibility& aOtherVis = theOther.myVisibility;
+ const VectorOfNames& aOtherNames = theOther.myNames;
+ const VectorOfRecords& aOtherRecords = theOther.myRecords;
+
+ VectorOfVisibility::const_iterator aVisIt = aOtherVis.constBegin();
+ VectorOfNames::const_iterator aNamesIt = aOtherNames.constBegin();
+ VectorOfRecords::const_iterator aRecordIt = aOtherRecords.constBegin();
+ for ( ; aRecordIt != aOtherRecords.constEnd(); ++aVisIt, ++aNamesIt, ++aRecordIt )
+ {
+ RecordPtr aNewRecord;
+ const RecordPtr& aRecord = *aRecordIt;
+ switch( aRecord->Type() )
+ {
+ case DimensionType_Length :
+ aNewRecord = RecordPtr( new Length( *aRecord->AsLength() ) );
+ break;
+
+ case DimensionType_Diameter :
+ aNewRecord = RecordPtr( new Diameter( *aRecord->AsDiameter() ) );
+ break;
+
+ case DimensionType_Angle :
+ aNewRecord = RecordPtr( new Angle( *aRecord->AsAngle() ) );
+ break;
+ }
+
+ myVisibility.append( *aVisIt );
+ myNames.append( *aNamesIt );
+ myRecords.append( aNewRecord );
+ }
+}
+
+//=================================================================================
+// function : Destructor
+// purpose :
+//=================================================================================
+GEOMGUI_DimensionProperty::~GEOMGUI_DimensionProperty()
+{
+}
+
+//=================================================================================
+// function : operator QVariant()
+// purpose :
+//=================================================================================
+GEOMGUI_DimensionProperty::operator QVariant()
+{
+ QVariant aQVariant;
+ aQVariant.setValue( *this );
+ return aQVariant;
+}
+
+//=================================================================================
+// function : operator ==
+// purpose :
+//=================================================================================
+bool GEOMGUI_DimensionProperty::operator == (const GEOMGUI_DimensionProperty& theOther) const
+{
+ if ( myVisibility.size() != theOther.myVisibility.size()
+ || myNames.size() != theOther.myNames.size()
+ || myRecords.size() != theOther.myRecords.size() )
+ {
+ return false;
+ }
+
+ for ( int it = 0; it < myRecords.size(); ++it )
+ {
+ if ( myVisibility[it] != theOther.myVisibility[it] )
+ {
+ return false;
+ }
+
+ if ( myNames[it] != theOther.myNames[it] )
+ {
+ return false;
+ }
+
+ const RecordPtr& aRecord = myRecords[it];
+ const RecordPtr& aOtherRecord = theOther.myRecords[it];
+ if ( aRecord->Type() != aOtherRecord->Type() )
+ {
+ return false;
+ }
+
+ switch ( aRecord->Type() )
+ {
+ case DimensionType_Length:
+ if ( (*aRecord->AsLength()) != (*aOtherRecord->AsLength()) )
+ {
+ return false;
+ }
+ break;
+
+ case DimensionType_Diameter:
+ if ( (*aRecord->AsDiameter()) != (*aOtherRecord->AsDiameter()) )
+ {
+ return false;
+ }
+ break;
+
+ case DimensionType_Angle:
+ if ( (*aRecord->AsAngle()) != (*aOtherRecord->AsAngle()) )
+ {
+ return false;
+ }
+ break;
+ }
+ }
+
+ return true;
+}
+
+//=================================================================================
+// function : GetNumber
+// purpose :
+//=================================================================================
+int GEOMGUI_DimensionProperty::GetNumber() const
+{
+ return myRecords.size();
+}
+
+//=================================================================================
+// function : AddRecord
+// purpose :
+//=================================================================================
+void GEOMGUI_DimensionProperty::AddRecord( const Handle(AIS_Dimension)& theIO, const gp_Ax3& theLCS )
+{
+ RecordPtr aNewRecord;
+
+ int aType = TypeFromIO( theIO );
+
+ switch ( aType )
+ {
+ case DimensionType_Length :
+ {
+ Handle(AIS_LengthDimension) aLength =
+ Handle(AIS_LengthDimension)::DownCast( theIO );
+
+ aNewRecord = RecordPtr( new Length() );
+ aNewRecord->AsLength()->Init( aLength, theLCS );
+ break;
+ }
+
+ case DimensionType_Diameter :
+ {
+ Handle(AIS_DiameterDimension) aDiam =
+ Handle(AIS_DiameterDimension)::DownCast( theIO );
+
+ aNewRecord = RecordPtr( new Diameter() );
+ aNewRecord->AsDiameter()->Init( aDiam, theLCS );
+ break;
+ }
+
+ case DimensionType_Angle :
+ {
+ Handle(AIS_AngleDimension) anAngle =
+ Handle(AIS_AngleDimension)::DownCast( theIO );
+
+ aNewRecord = RecordPtr( new Angle() );
+ aNewRecord->AsAngle()->Init( anAngle, theLCS );
+ }
+ }
+
+ myVisibility.append( true );
+ myNames.append( QString() );
+ myRecords.append( aNewRecord );
+}
+
+//=================================================================================
+// function : AddRecord
+// purpose :
+//=================================================================================
+void GEOMGUI_DimensionProperty::AddRecord( const RecordPtr& theRecord )
+{
+ myVisibility.append( true );
+ myNames.append( QString() );
+ myRecords.append( theRecord );
+}
+
+//=================================================================================
+// function : RemoveRecord
+// purpose :
+//=================================================================================
+void GEOMGUI_DimensionProperty::RemoveRecord( const int theIndex )
+{
+ myRecords.remove( theIndex );
+}
+
+//=================================================================================
+// function : Clear
+// purpose :
+//=================================================================================
+void GEOMGUI_DimensionProperty::Clear()
+{
+ myRecords.clear();
+}
+
+//=================================================================================
+// function : SetRecord
+// purpose :
+//=================================================================================
+void GEOMGUI_DimensionProperty::SetRecord( const int theIndex,
+ const Handle(AIS_Dimension)& theIO,
+ const gp_Ax3& theLCS )
+{
+ int aType = TypeFromIO( theIO );
+
+ RecordPtr& aChangeRecord = myRecords[theIndex];
+
+ switch ( aType )
+ {
+ case DimensionType_Length :
+ {
+ Handle(AIS_LengthDimension) aLength =
+ Handle(AIS_LengthDimension)::DownCast( theIO );
+
+ aChangeRecord = RecordPtr( new Length() );
+ aChangeRecord->AsLength()->Init( aLength, theLCS );
+ break;
+ }
+
+ case DimensionType_Diameter :
+ {
+ Handle(AIS_DiameterDimension) aDiam =
+ Handle(AIS_DiameterDimension)::DownCast( theIO );
+
+ aChangeRecord = RecordPtr( new Diameter() );
+ aChangeRecord->AsDiameter()->Init( aDiam, theLCS );
+ break;
+ }
+
+ case DimensionType_Angle :
+ {
+ Handle(AIS_AngleDimension) anAngle =
+ Handle(AIS_AngleDimension)::DownCast( theIO );
+
+ aChangeRecord = RecordPtr( new Angle() );
+ aChangeRecord->AsAngle()->Init( anAngle, theLCS );
+ }
+ }
+}
+
+//=================================================================================
+// function : SetRecord
+// purpose :
+//=================================================================================
+void GEOMGUI_DimensionProperty::SetRecord( const int theIndex, const RecordPtr& theRecord )
+{
+ myRecords[theIndex] = theRecord;
+}
+
+//=================================================================================
+// function : GetRecord
+// purpose :
+//=================================================================================
+const GEOMGUI_DimensionProperty::RecordPtr& GEOMGUI_DimensionProperty::GetRecord( const int theIndex ) const
+{
+ return myRecords[theIndex];
+}
+
+//=================================================================================
+// function : IsVisible
+// purpose :
+//=================================================================================
+bool GEOMGUI_DimensionProperty::IsVisible( const int theIndex ) const
+{
+ return myVisibility[theIndex];
+}
+
+//=================================================================================
+// function : SetVisible
+// purpose :
+//=================================================================================
+void GEOMGUI_DimensionProperty::SetVisible( const int theIndex, const bool theIsVisible )
+{
+ myVisibility[theIndex] = theIsVisible;
+}
+
+//=================================================================================
+// function : GetName
+// purpose :
+//=================================================================================
+QString GEOMGUI_DimensionProperty::GetName( const int theIndex ) const
+{
+ return myNames[theIndex];
+}
+
+//=================================================================================
+// function : SetName
+// purpose :
+//=================================================================================
+void GEOMGUI_DimensionProperty::SetName( const int theIndex, const QString &theName )
+{
+ myNames[theIndex] = theName;
+}
+
+//=================================================================================
+// function : GetType
+// purpose :
+//=================================================================================
+int GEOMGUI_DimensionProperty::GetType( const int theIndex ) const
+{
+ return myRecords[theIndex]->Type();
+}
+
+//=================================================================================
+// function : LoadFromAttribute
+// purpose :
+//=================================================================================
+void GEOMGUI_DimensionProperty::LoadFromAttribute( SalomeApp_Study* theStudy,
+ const std::string& theEntry )
+{
+ Clear();
+
+ _PTR(SObject) aSObj = theStudy->studyDS()->FindObjectID( theEntry );
+ if ( !aSObj )
+ {
+ return;
+ }
+
+ _PTR(StudyBuilder) aBuilder = theStudy->studyDS()->NewBuilder();
+
+ _PTR(GenericAttribute) aSeekAtt;
+ _PTR(AttributeTableOfReal) aRecordsAtt;
+
+ if ( !aSObj->FindAttribute( aSeekAtt, "AttributeTableOfReal" ) )
+ {
+ return;
+ }
+
+ aRecordsAtt = aSeekAtt;
+
+ for ( int aRecordIt = 1; aRecordIt <= aRecordsAtt->GetNbColumns(); ++aRecordIt )
+ {
+ std::vector aPacked = aRecordsAtt->GetColumn( aRecordIt );
+
+ RecordPtr aRecord;
+
+ QString aName( aRecordsAtt->GetColumnTitle( aRecordIt ).c_str() );
+
+ // unpack records
+ int it = 0;
+
+ // visibility [0]
+ bool isVisible = (bool) aPacked[it++];
+
+ // type [1]
+ int aType = (int) aPacked[it++];
+
+ switch (aType)
+ {
+ case DimensionType_Length :
+ {
+ Length* aLength = new Length;
+
+ // custom plane [2,3,4,5]
+ Standard_Real A = (Standard_Real) aPacked[it++];
+ Standard_Real B = (Standard_Real) aPacked[it++];
+ Standard_Real C = (Standard_Real) aPacked[it++];
+ Standard_Real D = (Standard_Real) aPacked[it++];
+ aLength->Plane = gp_Pln( A, B, C, D );
+
+ // flyout size [6]
+ aLength->Flyout = (Standard_Real) aPacked[it++];
+
+ // text flags [7,8]
+ aLength->TextHPos = (Prs3d_DimensionTextHorizontalPosition)(int)aPacked[it++];
+ aLength->TextVPos = (Prs3d_DimensionTextVerticalPosition) (int)aPacked[it++];
+
+ // point 1 [9,10,11]
+ 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]
+ Standard_Real aSecondX = aPacked[it++];
+ Standard_Real aSecondY = aPacked[it++];
+ Standard_Real aSecondZ = aPacked[it++];
+ aLength->SecondPoint = gp_Pnt( aSecondX, aSecondY, aSecondZ );
+
+ aRecord = RecordPtr( aLength );
+ break;
+ }
+
+ case DimensionType_Diameter :
+ {
+ Diameter* aDiam = new Diameter;
+
+ // custom plane [2,3,4,5]
+ Standard_Real A = (Standard_Real) aPacked[it++];
+ Standard_Real B = (Standard_Real) aPacked[it++];
+ Standard_Real C = (Standard_Real) aPacked[it++];
+ Standard_Real D = (Standard_Real) aPacked[it++];
+ aDiam->Plane = gp_Pln( A, B, C, D );
+
+ // flyout size [6]
+ aDiam->Flyout = (Standard_Real) aPacked[it++];
+
+ // text flags [7,8]
+ aDiam->TextHPos = (Prs3d_DimensionTextHorizontalPosition)(int)aPacked[it++];
+ aDiam->TextVPos = (Prs3d_DimensionTextVerticalPosition) (int)aPacked[it++];
+
+ // circle location [9,10,11]
+ 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]
+ 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]
+ Standard_Real aXDirX = (Standard_Real) aPacked[it++];
+ Standard_Real aXDirY = (Standard_Real) aPacked[it++];
+ Standard_Real aXDirZ = (Standard_Real) aPacked[it++];
+
+ // radius [18]
+ Standard_Real aRadius = (Standard_Real) aPacked[it++];
+
+ gp_Ax2 anAx( gp_Pnt( aLocX, aLocY, aLocZ ),
+ gp_Dir( aNormX, aNormY, aNormZ ),
+ gp_Dir( aXDirX, aXDirY, aXDirZ ) );
+
+ aDiam->Circle = gp_Circ( anAx, aRadius );
+
+ aRecord = RecordPtr( aDiam );
+ break;
+ }
+
+ case DimensionType_Angle :
+ {
+ Angle* anAngle = new Angle;
+
+ // flyout [2]
+ anAngle->Flyout = (Standard_Real) aPacked[it++];
+
+ // text flags [3,4]
+ anAngle->TextHPos = (Prs3d_DimensionTextHorizontalPosition)(int)aPacked[it++];
+ anAngle->TextVPos = (Prs3d_DimensionTextVerticalPosition) (int)aPacked[it++];
+
+ // point 1 [5,6,7]
+ 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]
+ 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]
+ 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 );
+
+ aRecord = RecordPtr( anAngle );
+ break;
+ }
+ }
+
+ myVisibility.append( isVisible );
+ myNames.append( aName );
+ myRecords.append( aRecord );
+ }
+}
+
+//=================================================================================
+// function : SaveToAttribute
+// purpose :
+//=================================================================================
+void GEOMGUI_DimensionProperty::SaveToAttribute( SalomeApp_Study *theStudy,
+ const std::string &theEntry )
+{
+ _PTR(SObject) aSObj = theStudy->studyDS()->FindObjectID( theEntry );
+ if ( !aSObj )
+ {
+ return;
+ }
+
+ _PTR(StudyBuilder) aBuilder = theStudy->studyDS()->NewBuilder();
+
+ _PTR(AttributeTableOfReal) aRecordsAtt;
+
+ aRecordsAtt = aBuilder->FindOrCreateAttribute( aSObj, "AttributeTableOfReal" );
+ aRecordsAtt->SetNbColumns( 0 );
+
+ for ( int it = 0; it < myRecords.size(); ++it )
+ {
+ bool aVisibility = myVisibility[it];
+ QString& aName = myNames[it];
+ RecordPtr& aRecord = myRecords[it];
+
+ std::vector aPacked;
+
+ // visibility [0]
+ aPacked.push_back( (double) aVisibility );
+
+ // type [1]
+ aPacked.push_back( (double) aRecord->Type() );
+
+ switch ( aRecord->Type() )
+ {
+ case DimensionType_Length:
+ {
+ Length* aProps = aRecord->AsLength();
+
+ // custom plane [2,3,4,5]
+ Standard_Real A, B, C, D;
+ aProps->Plane.Coefficients( A, B, C, D );
+ aPacked.push_back( (double) A );
+ aPacked.push_back( (double) B );
+ aPacked.push_back( (double) C );
+ aPacked.push_back( (double) D );
+
+ // flyout size [6]
+ aPacked.push_back( (double) aProps->Flyout );
+
+ // text flags [7,8]
+ aPacked.push_back( (double) aProps->TextHPos );
+ aPacked.push_back( (double) aProps->TextVPos );
+
+ // point 1 [9,10,11]
+ 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]
+ aPacked.push_back( (double) aProps->SecondPoint.X() );
+ aPacked.push_back( (double) aProps->SecondPoint.Y() );
+ aPacked.push_back( (double) aProps->SecondPoint.Z() );
+ break;
+ }
+
+ case DimensionType_Diameter:
+ {
+ Diameter* aProps = aRecord->AsDiameter();
+
+ // custom plane [2,3,4,5]
+ Standard_Real A, B, C, D;
+ aProps->Plane.Coefficients( A, B, C, D );
+ aPacked.push_back( (double) A );
+ aPacked.push_back( (double) B );
+ aPacked.push_back( (double) C );
+ aPacked.push_back( (double) D );
+
+ // flyout size [6]
+ aPacked.push_back( (double) aProps->Flyout );
+
+ // text flags [7,8]
+ aPacked.push_back( (double) aProps->TextHPos );
+ aPacked.push_back( (double) aProps->TextVPos );
+
+ // circle location [9,10,11]
+ 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]
+ 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]
+ 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]
+ aPacked.push_back( (double) aProps->Circle.Radius() );
+ break;
+ }
+
+ case DimensionType_Angle:
+ {
+ Angle* aProps = aRecord->AsAngle();
+
+ // flyout [2]
+ aPacked.push_back( (double) aProps->Flyout );
+
+ // text flags [3,4]
+ aPacked.push_back( (double) aProps->TextHPos );
+ aPacked.push_back( (double) aProps->TextVPos );
+
+ // point 1 [5,6,7]
+ 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]
+ 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]
+ aPacked.push_back( (double) aProps->CenterPoint.X() );
+ aPacked.push_back( (double) aProps->CenterPoint.Y() );
+ aPacked.push_back( (double) aProps->CenterPoint.Z() );
+ break;
+ }
+ }
+
+ aRecordsAtt->AddColumn( aPacked );
+ aRecordsAtt->SetColumnTitle( it + 1, aName.toStdString() );
+ }
+}
+
+//=================================================================================
+// function : TypeFromIO
+// purpose :
+//=================================================================================
+int GEOMGUI_DimensionProperty::TypeFromIO( const Handle(AIS_Dimension)& theIO ) const
+{
+ if ( theIO->IsKind( STANDARD_TYPE( AIS_LengthDimension ) ) )
+ {
+ return DimensionType_Length;
+ }
+
+ if ( theIO->IsKind( STANDARD_TYPE( AIS_DiameterDimension ) ) )
+ {
+ return DimensionType_Diameter;
+ }
+
+ if ( theIO->IsKind( STANDARD_TYPE( AIS_AngleDimension ) ) )
+ {
+ return DimensionType_Angle;
+ }
+
+ Standard_ProgramError::Raise( "unsupported dimension type" );
+
+ return 0;
+}
diff --git a/src/GEOMGUI/GEOMGUI_DimensionProperty.h b/src/GEOMGUI/GEOMGUI_DimensionProperty.h
new file mode 100644
index 000000000..f2c5f7e58
--- /dev/null
+++ b/src/GEOMGUI/GEOMGUI_DimensionProperty.h
@@ -0,0 +1,419 @@
+// Copyright (C) 2007-2013 CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+// File : GEOMGUI_DimensionProperty.h
+// Author : Anton POLETAEV, Open CASCADE S.A.S.
+//
+
+#ifndef GEOMGUI_DIMENSIONPROPERTY_H
+#define GEOMGUI_DIMENSIONPROPERTY_H
+
+// OCCT includes
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+class SalomeApp_Study;
+
+/*!
+ * \brief Utility class to unpack/pack dimension presentations as object property of study.
+ *
+ * Dimension presentations are store in relative coordinate system (LCS).
+ * To ensure that dimension is bound to the equal shape irrespectively of its location
+ * transformation.
+ *
+ * The record is a list of qvariant, containing packed dimension properties and its attributes:
+ * (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]
+ */
+class Standard_EXPORT GEOMGUI_DimensionProperty
+{
+public:
+
+ /*!
+ * \brief Type of packed presentation.
+ */
+ enum DimensionType
+ {
+ DimensionType_Length,
+ DimensionType_Diameter,
+ DimensionType_Angle
+ };
+
+ /*!
+ * \brief Base class for pointer-optimized records storing.
+ */
+ struct Length;
+ struct Diameter;
+ struct Angle;
+ struct Record
+ {
+ public:
+ Record( const DimensionType theType )
+ : myType( theType )
+ {}
+
+ DimensionType Type() const
+ {
+ return myType;
+ }
+
+ Length* AsLength() { return static_cast( this ); }
+ Diameter* AsDiameter() { return static_cast( this ); }
+ Angle* AsAngle() { return static_cast( this ); }
+
+ private:
+ DimensionType myType;
+ };
+
+ /*!
+ * \brief Declaration of properties for length dimensions.
+ */
+ struct Standard_EXPORT Length : public Record
+ {
+ Length() :
+ Record( DimensionType_Length ),
+ FirstPoint( gp::Origin() ),
+ SecondPoint( gp::Origin() ),
+ Plane( gp::XOY() ),
+ Flyout( 0.0 ),
+ TextHPos( Prs3d_DTHP_Fit ),
+ TextVPos( Prs3d_DTVP_Center )
+ {}
+
+ Length( const Length& theOther ) :
+ Record( DimensionType_Length ),
+ FirstPoint( theOther.FirstPoint ),
+ SecondPoint( theOther.SecondPoint ),
+ Plane( theOther.Plane ),
+ Flyout( theOther.Flyout ),
+ TextHPos( theOther.TextHPos ),
+ TextVPos( theOther.TextVPos )
+ {}
+
+ ~Length() {}
+
+ /*!
+ * \brief Inits property fields from the passed length object.
+ * \param theIO [in] the interactive presentation.
+ * \param theLCS [in] the local coordiante system of parent object.
+ */
+ void Init( const Handle(AIS_LengthDimension)& theIO, const gp_Ax3& theLCS );
+
+ /*!
+ * \brief Updates length object properties from the fields.
+ * \param theIO [in/out] the interactive presentation.
+ * \param theLCS [in] the local coordiante system of parent object.
+ */
+ void Update( Handle(AIS_LengthDimension)& theIO, const gp_Ax3& theLCS );
+
+ /*!
+ * \brief Overload comparsion.
+ */
+ bool operator == (const Length &theOther) const;
+ bool operator != (const Length &theOther) const { return !(operator == (theOther)); }
+
+ gp_Pnt FirstPoint;
+ gp_Pnt SecondPoint;
+ gp_Pln Plane;
+ double Flyout;
+ Prs3d_DimensionTextHorizontalPosition TextHPos;
+ Prs3d_DimensionTextVerticalPosition TextVPos;
+ };
+
+ /*!
+ * \brief Declaration of properties for diameter dimensions.
+ */
+ struct Standard_EXPORT Diameter : public Record
+ {
+ Diameter() :
+ Record( DimensionType_Diameter ),
+ Plane( gp::XOY() ),
+ Flyout( 0.0 ),
+ TextHPos( Prs3d_DTHP_Fit ),
+ TextVPos( Prs3d_DTVP_Center )
+ {}
+
+ Diameter( const Diameter& theOther ) :
+ Record( DimensionType_Diameter ),
+ Circle( theOther.Circle ),
+ Plane( theOther.Plane ),
+ Flyout( theOther.Flyout ),
+ TextHPos( theOther.TextHPos ),
+ TextVPos( theOther.TextVPos )
+ {}
+
+ ~Diameter() {}
+
+ /*!
+ * \brief Inits property fields from the passed length object.
+ * \param theIO [in] the interactive presentation.
+ * \param theLCS [in] the local coordiante system of parent object.
+ */
+ void Init( const Handle(AIS_DiameterDimension)& theIO, const gp_Ax3& theLCS );
+
+ /*!
+ * \brief Updates length object properties from the fields.
+ * \param theIO [in/out] the interactive presentation.
+ * \param theLCS [in] the local coordiante system of parent object.
+ */
+ void Update( Handle(AIS_DiameterDimension)& theIO, const gp_Ax3& theLCS );
+
+ /*!
+ * \brief Overload comparsion.
+ */
+ bool operator == (const Diameter &theOther) const;
+ bool operator != (const Diameter &theOther) const { return !(operator == (theOther)); }
+
+ gp_Circ Circle;
+ gp_Pln Plane;
+ double Flyout;
+ Prs3d_DimensionTextHorizontalPosition TextHPos;
+ Prs3d_DimensionTextVerticalPosition TextVPos;
+ };
+
+ /*!
+ * \brief Declaration of properties for angle dimensions.
+ */
+ struct Standard_EXPORT Angle : public Record
+ {
+ Angle() :
+ Record( DimensionType_Angle ),
+ FirstPoint( gp::Origin() ),
+ SecondPoint( gp::Origin() ),
+ CenterPoint( gp::Origin() ),
+ Flyout( 0.0 ),
+ TextHPos( Prs3d_DTHP_Fit ),
+ TextVPos( Prs3d_DTVP_Center )
+ {}
+
+ Angle( const Angle& theOther ) :
+ Record( DimensionType_Angle ),
+ FirstPoint( theOther.FirstPoint ),
+ SecondPoint( theOther.SecondPoint ),
+ CenterPoint( theOther.CenterPoint ),
+ Flyout( theOther.Flyout ),
+ TextHPos( theOther.TextHPos ),
+ TextVPos( theOther.TextVPos )
+ {}
+
+ ~Angle() {}
+
+ /*!
+ * \brief Inits property fields from the passed length object.
+ * \param theIO [in] the interactive presentation.
+ * \param theLCS [in] the local coordiante system of parent object.
+ */
+ void Init( const Handle(AIS_AngleDimension)& theIO, const gp_Ax3& theLCS );
+
+ /*!
+ * \brief Updates length object properties from the fields.
+ * \param theIO [in/out] the interactive presentation.
+ * \param theLCS [in] the local coordiante system of parent object.
+ */
+ void Update( Handle(AIS_AngleDimension)& theIO, const gp_Ax3& theLCS );
+
+ /*!
+ * \brief Overload comparsion.
+ */
+ bool operator == (const Angle &theOther) const;
+ bool operator != (const Angle &theOther) const { return !(operator == (theOther)); }
+
+ gp_Pnt FirstPoint;
+ gp_Pnt SecondPoint;
+ gp_Pnt CenterPoint;
+ double Flyout;
+ Prs3d_DimensionTextHorizontalPosition TextHPos;
+ Prs3d_DimensionTextVerticalPosition TextVPos;
+ };
+
+ typedef QSharedPointer RecordPtr;
+
+public:
+
+ /*!
+ * \brief Constructor. Inits empty property.
+ */
+ GEOMGUI_DimensionProperty();
+
+ /*!
+ * \brief Copy constructor.
+ */
+ GEOMGUI_DimensionProperty( const GEOMGUI_DimensionProperty& theOther );
+
+ /*!
+ * \brief Destructor.
+ */
+ ~GEOMGUI_DimensionProperty();
+
+ /*!
+ * \brief Overload QVariant cast operator.
+ */
+ operator QVariant();
+
+ /*!
+ * \brief Overload comparsion.
+ */
+ bool operator == (const GEOMGUI_DimensionProperty &theOther) const;
+
+public:
+
+ /*!
+ * \brief Returns number of dimension records.
+ */
+ int GetNumber() const;
+
+ /*!
+ * \brief Adds new record for the passed interactive object. Convenience method.
+ * \param theIO [in] the interactive dimension to append as new record.
+ * \param theLCS [in] the local coordinate system of parent object.
+ */
+ void AddRecord( const Handle(AIS_Dimension)& theIO, const gp_Ax3& theLCS );
+
+ /*!
+ * \brief Adds new dimension record.
+ * \param theRecord [in] the record to add.
+ */
+ void AddRecord( const RecordPtr& theRecord );
+
+ /*!
+ * \brief Update dimension record data.
+ * \param theIndex [in] the index of the record.
+ * \param theIO [in] the interactive dimension to update properties.
+ * \param theLCS [in] the local coordinate system of parent object.
+ */
+ void SetRecord( const int theIndex,
+ const Handle(AIS_Dimension)& theIO,
+ const gp_Ax3& theLCS );
+
+ /*!
+ * \brief Update dimension record data.
+ * \param theIndex [in] the index of the dimension record.
+ * \param theRecord [in] the record to replace with.
+ */
+ void SetRecord( const int theIndex, const RecordPtr& theRecord );
+
+ /*!
+ * \brief Access record by index.
+ * \param theIndex [in] the index of the dimension record.
+ */
+ const RecordPtr& GetRecord( const int theIndex ) const;
+
+ /*!
+ * \brief Removes record by its index.
+ * \param theIndex [in] the index of dimension record.
+ */
+ void RemoveRecord( const int theIndex );
+
+ /*!
+ * \brief Clears property data.
+ */
+ void Clear();
+
+public:
+
+ /*!
+ * \brief Returns visibility state of dimension record by its index.
+ *
+ * \param theIndex [in] the index of the dimension record.
+ */
+ bool IsVisible( const int theIndex ) const;
+
+ /*!
+ * \brief Changes visibility state of the dimension record.
+ *
+ * \param theIndex [in] the index of the dimension record.
+ * \param theIsVisible [in] the new visibility state.
+ */
+ void SetVisible( const int theIndex, const bool theIsVisible );
+
+ /*!
+ * \brief Returns name of dimension record by its index.
+ *
+ * \param theIndex [in] the index of the dimension record.
+ */
+ QString GetName( const int theIndex ) const;
+
+ /*!
+ * \brief Changes name of dimension record.
+ *
+ * \param theIndex [in] the index of the dimension record.
+ * \param theName [in] the new name.
+ */
+ void SetName( const int theIndex, const QString& theName );
+
+ /*!
+ * \brief Returns dimension type.
+ */
+ int GetType( const int theIndex ) const;
+
+public:
+
+ /*!
+ * \brief Loads properties data from attribute "AttributeTableOfReal".
+ * \param theStudy [in] the study.
+ * \param theEntry [in] the entry of GEOM object to operate with.
+ */
+ void LoadFromAttribute( SalomeApp_Study* theStudy, const std::string& theEntry );
+
+ /*!
+ * \brief Saves properties data to attribute "AttributeTableOfReal".
+ * \param theStudy [in] the study.
+ * \param theEntry [in] the entry of GEOM object to operate with.
+ */
+ void SaveToAttribute( SalomeApp_Study* theStudy, const std::string& theEntry );
+
+private:
+
+ /*!
+ * \brief Determines dimension type code.
+ */
+ int TypeFromIO( const Handle(AIS_Dimension)& theIO ) const;
+
+private:
+
+ typedef QVector VectorOfVisibility;
+ typedef QVector VectorOfNames;
+ typedef QVector VectorOfRecords;
+
+private:
+
+ VectorOfVisibility myVisibility;
+ VectorOfNames myNames;
+ VectorOfRecords myRecords;
+};
+
+Q_DECLARE_METATYPE(GEOMGUI_DimensionProperty);
+
+#endif
diff --git a/src/GEOMGUI/GEOM_Displayer.cxx b/src/GEOMGUI/GEOM_Displayer.cxx
index 566e42c19..f4d8cbb98 100644
--- a/src/GEOMGUI/GEOM_Displayer.cxx
+++ b/src/GEOMGUI/GEOM_Displayer.cxx
@@ -25,7 +25,7 @@
// Author : Vadim SANDLER, Open CASCADE S.A.S. (vadim.sandler@opencascade.com)
#include "GEOM_Displayer.h"
-
+#include "GEOMGUI_DimensionProperty.h"
#include "GeometryGUI.h"
#include
@@ -39,12 +39,15 @@
#include
#include
+#include
#include
#include
#include
#include
#include
+#include
+
#include
#include
@@ -77,7 +80,12 @@
// OCCT Includes
#include
+#include
+#include
+#include
+#include
#include
+#include
#include
#include
#include
@@ -520,8 +528,7 @@ void GEOM_Displayer::Redisplay( const Handle(SALOME_InteractiveObject)& theIO,
{
if ( view->isVisible( theIO ) || ( checkActiveViewer && view == GetActiveView() ) )
{
- Erase( theIO, true, false, view );
- Display( theIO, updateViewer, view );
+ Redisplay( theIO, updateViewer, view );
}
}
}
@@ -530,6 +537,27 @@ void GEOM_Displayer::Redisplay( const Handle(SALOME_InteractiveObject)& theIO,
}
}
+//=================================================================
+/*!
+ * GEOM_Displayer::Redisplay
+ * Redisplay (erase and then display again) interactive object
+ * in the specified view
+ */
+//=================================================================
+void GEOM_Displayer::Redisplay( const Handle(SALOME_InteractiveObject)& theIO,
+ const bool theUpdateViewer,
+ SALOME_View* theViewFrame )
+{
+ SALOME_View* vf = theViewFrame ? theViewFrame : GetActiveView();
+ if ( !vf )
+ {
+ return;
+ }
+
+ Erase( theIO, true, false, theViewFrame );
+ Display( theIO, theUpdateViewer, theViewFrame );
+}
+
//=================================================================
/*!
* GEOM_Displayer::Display
@@ -953,6 +981,144 @@ void GEOM_Displayer::updateActorProperties( GEOM_Actor* actor, bool create )
}
}
+//=================================================================
+/*!
+ * GEOM_Displayer::updateDimensions
+ * Creates or renews dimension presentation for the IO.
+ */
+//=================================================================
+void GEOM_Displayer::updateDimensions( const Handle(SALOME_InteractiveObject)& theIO,
+ SALOME_OCCPrs* thePrs,
+ const gp_Ax3& theShapeLCS )
+{
+ SalomeApp_Study* aStudy = getStudy();
+ if ( !aStudy )
+ {
+ return;
+ }
+
+ if ( theIO.IsNull() )
+ {
+ return;
+ }
+
+ SOCC_Prs* anOccPrs = dynamic_cast( thePrs );
+
+ AIS_ListOfInteractive aListOfIO;
+
+ anOccPrs->GetObjects( aListOfIO );
+
+ AIS_ListIteratorOfListOfInteractive aIterateIO( aListOfIO );
+
+ // remove outdated presentations of dimensions
+ for ( ; aIterateIO.More(); aIterateIO.Next() )
+ {
+ const Handle(AIS_InteractiveObject)& anIO = aIterateIO.Value();
+ if ( !anIO->IsKind( STANDARD_TYPE( AIS_Dimension ) ) )
+ {
+ continue;
+ }
+
+ aListOfIO.Remove( aIterateIO );
+ }
+
+ // prepare dimension styling
+ SUIT_ResourceMgr* aResMgr = SUIT_Session::session()->resourceMgr();
+
+ QColor aQColor = aResMgr->colorValue ( "Geometry", "dimensions_color", QColor( 0, 255, 0 ) );
+ 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 );
+ 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" );
+
+ // restore dimension presentation from saved attribute or property data
+ AIS_ListOfInteractive aRestoredDimensions;
+
+ QVariant aProperty = aStudy->getObjectProperty( GEOM::sharedPropertiesId(),
+ theIO->getEntry(),
+ GEOM::propertyName( GEOM::Dimensions ),
+ QVariant() );
+
+ GEOMGUI_DimensionProperty aRecords;
+
+ if ( aProperty.isValid() && aProperty.canConvert() )
+ {
+ aRecords = aProperty.value();
+ }
+ else
+ {
+ aRecords.LoadFromAttribute( getStudy(), theIO->getEntry() );
+ }
+
+ // create up-to-date dimension presentations
+ for ( int aPrsIt = 0; aPrsIt < aRecords.GetNumber(); ++aPrsIt )
+ {
+ if ( !aRecords.IsVisible( aPrsIt ) )
+ {
+ continue;
+ }
+
+ // init dimension by type
+ Handle(AIS_Dimension) aPrs;
+ switch( aRecords.GetType( aPrsIt ) )
+ {
+ case GEOMGUI_DimensionProperty::DimensionType_Length :
+ {
+ Handle(GEOM_AISLength) aLength = new GEOM_AISLength( aPrsIt );
+ aRecords.GetRecord( aPrsIt )->AsLength()->Update( aLength, theShapeLCS );
+ aPrs = aLength;
+ break;
+ }
+
+ case GEOMGUI_DimensionProperty::DimensionType_Diameter :
+ {
+ Handle(GEOM_AISDiameter) aDiam = new GEOM_AISDiameter( aPrsIt );
+ aRecords.GetRecord( aPrsIt )->AsDiameter()->Update( aDiam, theShapeLCS );
+ aPrs = aDiam;
+ break;
+ }
+
+ case GEOMGUI_DimensionProperty::DimensionType_Angle :
+ {
+ Handle(GEOM_AISAngle) anAng = new GEOM_AISAngle( aPrsIt );
+ aRecords.GetRecord( aPrsIt )->AsAngle()->Update( anAng, theShapeLCS );
+ aPrs = anAng;
+ break;
+ }
+ }
+
+ aPrs->SetOwner( theIO );
+
+ Quantity_Color aColor( aQColor.redF(), aQColor.greenF(), aQColor.blueF(), Quantity_TOC_RGB );
+
+ Handle(Prs3d_DimensionAspect) aStyle = new Prs3d_DimensionAspect();
+
+ aStyle->SetCommonColor( aColor );
+ aStyle->MakeUnitsDisplayed( (Standard_Boolean) isUnitsShown );
+ aStyle->MakeText3d( Standard_True );
+ aStyle->MakeTextShaded( Standard_True );
+ aStyle->TextAspect()->SetHeight( aFontHeight );
+ aStyle->ArrowAspect()->SetLength( anArrowLength );
+ aStyle->LineAspect()->SetWidth( aLineWidth );
+ aStyle->SetTextHorizontalPosition( aPrs->DimensionAspect()->TextHorizontalPosition() );
+ aStyle->SetTextVerticalPosition( aPrs->DimensionAspect()->TextVerticalPosition() );
+ aPrs->SetDimensionAspect( aStyle );
+ aPrs->SetPolygonOffsets( Aspect_POM_Fill, -1.0, -1.0 );
+
+ aListOfIO.Append( aPrs );
+ }
+
+ // update presentation
+ anOccPrs->Clear();
+
+ for ( aIterateIO.Initialize( aListOfIO ); aIterateIO.More(); aIterateIO.Next() )
+ {
+ anOccPrs->AddObject( aIterateIO.Value() );
+ }
+}
+
//=================================================================
/*!
* GEOM_Displayer::Erase
@@ -989,6 +1155,28 @@ void GEOM_Displayer::Redisplay( const SALOME_ListIO& theIOList,
UpdateViewer();
}
+//=================================================================
+/*!
+ * GEOM_Displayer::Redisplay
+ * Calls Redisplay() method for each object in the given list
+ */
+//=================================================================
+void GEOM_Displayer::Redisplay( const SALOME_ListIO& theIOList,
+ const bool theUpdateViewer,
+ SALOME_View* theViewFrame )
+{
+ SALOME_ListIteratorOfListIO anIter( theIOList );
+ for ( ; anIter.More(); anIter.Next() )
+ {
+ Redisplay( anIter.Value(), false, theViewFrame );
+ }
+
+ if ( theUpdateViewer )
+ {
+ UpdateViewer();
+ }
+}
+
//=================================================================
/*!
* GEOM_Displayer::Update
@@ -1119,6 +1307,8 @@ void GEOM_Displayer::Update( SALOME_OCCPrs* prs )
AISShape->SetToUpdate();
}
}
+
+ updateDimensions( myIO, occPrs, GEOMUtils::GetPosition( myShape ) );
}
}
diff --git a/src/GEOMGUI/GEOM_Displayer.h b/src/GEOMGUI/GEOM_Displayer.h
index 6d3f03216..4e8df530b 100644
--- a/src/GEOMGUI/GEOM_Displayer.h
+++ b/src/GEOMGUI/GEOM_Displayer.h
@@ -66,6 +66,7 @@ class SalomeApp_Study;
class SalomeApp_Application;
class SUIT_SelectionFilter;
class Handle_GEOM_AISShape;
+class gp_Ax3;
//class SALOME_Selection;
class GEOMGUI_EXPORT GEOM_Displayer : public LightApp_Displayer
@@ -93,6 +94,10 @@ public:
const bool updateViewer = true,
const bool checkActiveViewer = true );
+ void Redisplay ( const Handle(SALOME_InteractiveObject)& theIO,
+ const bool theUpdateViewer,
+ SALOME_View* theViewFrame );
+
void Erase ( const Handle(SALOME_InteractiveObject)& theIO,
const bool forced = false,
const bool updateViewer = true,
@@ -118,6 +123,10 @@ public:
const bool updateViewer = true,
const bool checkActiveViewer = true );
+ void Redisplay ( const SALOME_ListIO& theIOList,
+ const bool theUpdateViewer,
+ SALOME_View* theViewFrame );
+
/* build presentation accordint to the current viewer type*/
SALOME_Prs* BuildPrs ( GEOM::GEOM_Object_ptr );
SALOME_Prs* BuildPrs ( const TopoDS_Shape& );
@@ -226,6 +235,7 @@ protected:
QColor colorFromResources( const QString&, const QColor& );
void updateShapeProperties( const Handle(GEOM_AISShape)&, bool );
void updateActorProperties( GEOM_Actor*, bool );
+ void updateDimensions( const Handle(SALOME_InteractiveObject)&, SALOME_OCCPrs*, const gp_Ax3& );
PropMap getObjectProperties( SalomeApp_Study*, const QString&, SALOME_View* = 0 );
PropMap getDefaultPropertyMap();
diff --git a/src/GEOMGUI/GEOM_images.ts b/src/GEOMGUI/GEOM_images.ts
index 1e27166a6..467cc55de 100644
--- a/src/GEOMGUI/GEOM_images.ts
+++ b/src/GEOMGUI/GEOM_images.ts
@@ -1135,6 +1135,10 @@
angle.png
+
+
+ managedimensions.png
+
point2.png
diff --git a/src/GEOMGUI/GEOM_msg_en.ts b/src/GEOMGUI/GEOM_msg_en.ts
index add4553bd..e62e0794d 100644
--- a/src/GEOMGUI/GEOM_msg_en.ts
+++ b/src/GEOMGUI/GEOM_msg_en.ts
@@ -3248,6 +3248,38 @@ Please, select face, shell or solid and try again
Automatic bring to front
+
+
+ Dimensions (Measurements)
+
+
+
+ Color
+
+
+
+ Line width
+
+
+
+ Font height
+
+
+
+ Length of arrows
+
+
+
+ Length measurement units
+
+
+
+ Angle measurement units
+
+
+
+ Show units of measurement
+
Number of isolines
@@ -4688,6 +4720,18 @@ Please, select face, shell or solid and try again
Compute angle between two lines or linear edges
+
+
+ Manage dimensions
+
+
+
+ Manage dimensions
+
+
+
+ Manage measurement dimensions of an object
+
Auto color
@@ -6076,6 +6120,154 @@ Number of sketch points too small
Z
+
+ MeasureGUI_ManageDimensionsDlg
+
+
+ Manage dimensions
+
+
+
+ Object
+
+
+
+ Dimensions
+
+
+
+ Add
+
+
+
+ Remove
+
+
+
+ Show all
+
+
+
+ Hide all
+
+
+
+ Distance
+
+
+
+ Diameter
+
+
+
+ Angle
+
+
+
+ Unsaved changes
+
+
+
+ The unsaved changes will be lost.
+Do you want to continue?
+
+
+
+ MeasureGUI_CreateDimensionDlg
+
+
+ Add dimension
+
+
+
+ Dimensions
+
+
+
+ Length
+
+
+
+ Diameter
+
+
+
+ Angle
+
+
+
+ Arguments
+
+
+
+ Edge length
+
+
+
+ Two points
+
+
+
+ Parallel edges
+
+
+
+ Two edges
+
+
+
+ Three points
+
+
+
+ Edge
+
+
+
+ Edge 1
+
+
+
+ Edge 2
+
+
+
+ Point 1
+
+
+
+ Point 2
+
+
+
+ Point 3
+
+
+
+ Object
+
+
+
+ Length
+
+
+
+ Diameter
+
+
+
+ Angle
+
+
+
+ Can not create dimension
+
+
+
+ The dimension can not be created for the specified arguments.
+Please specify suitable arguments.
+
+
OperationGUI_ChamferDlg
diff --git a/src/GEOMGUI/GEOM_msg_fr.ts b/src/GEOMGUI/GEOM_msg_fr.ts
index 5d3f8d802..dd5a103c7 100644
--- a/src/GEOMGUI/GEOM_msg_fr.ts
+++ b/src/GEOMGUI/GEOM_msg_fr.ts
@@ -3248,6 +3248,38 @@ Choisissez une face, une coque ou un solide et essayez de nouveau
Afficher au premier plan automatiquement
+
+
+ Dimensions (Measurements)
+
+
+
+ Color
+
+
+
+ Line width
+
+
+
+ Font height
+
+
+
+ Length of arrows
+
+
+
+ Length measurement units
+
+
+
+ Angle measurement units
+
+
+
+ Show units of measurement
+
Nombre d'isolignes
@@ -4688,6 +4720,18 @@ Choisissez une face, une coque ou un solide et essayez de nouveau
Calculer l'angle entre deux lignes ou arêtes linéaires
+
+
+ Manage dimensions
+
+
+
+ Manage dimensions
+
+
+
+ Manage measurement dimensions of an object
+
Couleur automatique
@@ -6076,6 +6120,154 @@ Le nombre de points n'est pas suffisant
Z
+
+ MeasureGUI_ManageDimensionsDlg
+
+
+ Manage dimensions
+
+
+
+ Object
+
+
+
+ Dimensions
+
+
+
+ Add
+
+
+
+ Remove
+
+
+
+ Show all
+
+
+
+ Hide all
+
+
+
+ Distance
+
+
+
+ Diameter
+
+
+
+ Angle
+
+
+
+ Unsaved changes
+
+
+
+ The unsaved changes will be lost.
+Do you want to continue?
+
+
+
+ MeasureGUI_CreateDimensionDlg
+
+
+ Add dimension
+
+
+
+ Dimensions
+
+
+
+ Length
+
+
+
+ Diameter
+
+
+
+ Angle
+
+
+
+ Arguments
+
+
+
+ Edge length
+
+
+
+ Two points
+
+
+
+ Parallel edges
+
+
+
+ Two edges
+
+
+
+ Three points
+
+
+
+ Edge
+
+
+
+ Edge 1
+
+
+
+ Edge 2
+
+
+
+ Point 1
+
+
+
+ Point 2
+
+
+
+ Point 3
+
+
+
+ Object
+
+
+
+ Length
+
+
+
+ Diameter
+
+
+
+ Angle
+
+
+
+ Can not create dimension
+
+
+
+ The dimension can not be created for the specified arguments.
+Please specify suitable arguments.
+
+
OperationGUI_ChamferDlg
diff --git a/src/GEOMGUI/GEOM_msg_ja.ts b/src/GEOMGUI/GEOM_msg_ja.ts
index 8a673fc1b..c3b84b8f6 100644
--- a/src/GEOMGUI/GEOM_msg_ja.ts
+++ b/src/GEOMGUI/GEOM_msg_ja.ts
@@ -3243,6 +3243,38 @@
フォア グラウンドで自動的に表示されます。
+
+
+ Dimensions (Measurements)
+
+
+
+ Color
+
+
+
+ Line width
+
+
+
+ Font height
+
+
+
+ Length of arrows
+
+
+
+ Length measurement units
+
+
+
+ Angle measurement units
+
+
+
+ Show units of measurement
+
輪郭の数
@@ -4683,6 +4715,18 @@
2つのラインまたはエッジ間の角度を計算
+
+
+ Manage dimensions
+
+
+
+ Manage dimensions
+
+
+
+ Manage measurement dimensions of an object
+
自動色
@@ -6068,6 +6112,154 @@
Z
+
+ MeasureGUI_ManageDimensionsDlg
+
+
+ Manage dimensions
+
+
+
+ Object
+
+
+
+ Dimensions
+
+
+
+ Add
+
+
+
+ Remove
+
+
+
+ Show all
+
+
+
+ Hide all
+
+
+
+ Distance
+
+
+
+ Diameter
+
+
+
+ Angle
+
+
+
+ Unsaved changes
+
+
+
+ The unsaved changes will be lost.
+Do you want to continue?
+
+
+
+ MeasureGUI_CreateDimensionDlg
+
+
+ Add dimension
+
+
+
+ Dimensions
+
+
+
+ Length
+
+
+
+ Diameter
+
+
+
+ Angle
+
+
+
+ Arguments
+
+
+
+ Edge length
+
+
+
+ Two points
+
+
+
+ Parallel edges
+
+
+
+ Two edges
+
+
+
+ Three points
+
+
+
+ Edge
+
+
+
+ Edge 1
+
+
+
+ Edge 2
+
+
+
+ Point 1
+
+
+
+ Point 2
+
+
+
+ Point 3
+
+
+
+ Object
+
+
+
+ Length
+
+
+
+ Diameter
+
+
+
+ Angle
+
+
+
+ Can not create dimension
+
+
+
+ The dimension can not be created for the specified arguments.
+Please specify suitable arguments.
+
+
OperationGUI_ChamferDlg
diff --git a/src/GEOMGUI/GeometryGUI.cxx b/src/GEOMGUI/GeometryGUI.cxx
index b334172ed..bd3e7e5c0 100644
--- a/src/GEOMGUI/GeometryGUI.cxx
+++ b/src/GEOMGUI/GeometryGUI.cxx
@@ -634,6 +634,7 @@ void GeometryGUI::OnGUIEvent( int id, const QVariant& theParam )
case GEOMOp::OpGetNonBlocks: // MENU MEASURE - Get NON BLOCKS
case GEOMOp::OpPointCoordinates: // MENU MEASURE - POINT COORDINATES
case GEOMOp::OpCheckSelfInters: // MENU MEASURE - CHECK SELF INTERSECTIONS
+ case GEOMOp::OpManageDimensions: // MENU MEASURE - MANAGE DIMENSIONS
libName = "MeasureGUI";
break;
case GEOMOp::OpGroupCreate: // MENU GROUP - CREATE
@@ -1009,6 +1010,7 @@ void GeometryGUI::initialize( CAM_Application* app )
createGeomAction( GEOMOp::OpBoundingBox, "BND_BOX" );
createGeomAction( GEOMOp::OpMinDistance, "MIN_DIST" );
createGeomAction( GEOMOp::OpAngle, "MEASURE_ANGLE" );
+ createGeomAction( GEOMOp::OpManageDimensions, "MANAGE_DIMENSIONS" );
createGeomAction( GEOMOp::OpTolerance, "TOLERANCE" );
createGeomAction( GEOMOp::OpWhatIs, "WHAT_IS" );
@@ -1268,9 +1270,10 @@ void GeometryGUI::initialize( CAM_Application* app )
createMenu( separator(), measurId, -1 );
int dimId = createMenu( tr( "MEN_DIMENSIONS" ), measurId, -1 );
- createMenu( GEOMOp::OpBoundingBox, dimId, -1 );
- createMenu( GEOMOp::OpMinDistance, dimId, -1 );
- createMenu( GEOMOp::OpAngle, dimId, -1 );
+ createMenu( GEOMOp::OpBoundingBox, dimId, -1 );
+ createMenu( GEOMOp::OpMinDistance, dimId, -1 );
+ createMenu( GEOMOp::OpAngle, dimId, -1 );
+ createMenu( GEOMOp::OpManageDimensions, dimId, -1 );
createMenu( separator(), measurId, -1 );
createMenu( GEOMOp::OpTolerance, measurId, -1 );
@@ -2360,6 +2363,47 @@ void GeometryGUI::createPreferences()
addPreference( tr( "PREF_AUTO_BRING_TO_FRONT" ), genGroup,
LightApp_Preferences::Bool, "Geometry", "auto_bring_to_front" );
+ int aDimGroupId = addPreference( tr( "PREF_DIMENSIONS" ), tabId );
+ setPreferenceProperty( aDimGroupId, "columns", 2 );
+
+ addPreference( tr( "PREF_DIMENSIONS_COLOR" ), aDimGroupId,
+ LightApp_Preferences::Color, "Geometry", "dimensions_color" );
+
+ int aDimLineWidthId = addPreference( tr( "PREF_DIMENSIONS_LINE_WIDTH" ), aDimGroupId,
+ LightApp_Preferences::IntSpin, "Geometry", "dimensions_line_width" );
+
+ setPreferenceProperty( aDimLineWidthId, "min", 1 );
+ setPreferenceProperty( aDimLineWidthId, "max", 5 );
+
+ 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" );
+
+ int aLengthUnitsId = addPreference( tr( "PREF_DIMENSIONS_LENGTH_UNITS" ), aDimGroupId,
+ LightApp_Preferences::Selector, "Geometry", "dimensions_length_units" );
+
+ int anAngUnitsId = addPreference( tr( "PREF_DIMENSIONS_ANGLE_UNITS" ), aDimGroupId,
+ LightApp_Preferences::Selector, "Geometry", "dimensions_angle_units" );
+
+ addPreference( tr( "PREF_DIMENSIONS_SHOW_UNITS" ), aDimGroupId,
+ LightApp_Preferences::Bool, "Geometry", "dimensions_show_units" );
+
+ QStringList aListOfLengthUnits;
+ aListOfLengthUnits << "m";
+ aListOfLengthUnits << "cm";
+ aListOfLengthUnits << "mm";
+ aListOfLengthUnits << "in.";
+ aListOfLengthUnits << "ft.";
+
+ QStringList aListOfAngUnits;
+ aListOfAngUnits << "rad";
+ aListOfAngUnits << "deg";
+
+ setPreferenceProperty( aLengthUnitsId, "strings", aListOfLengthUnits );
+ setPreferenceProperty( anAngUnitsId, "strings", aListOfAngUnits );
+
int isoGroup = addPreference( tr( "PREF_ISOS" ), tabId );
setPreferenceProperty( isoGroup, "columns", 2 );
int isoU = addPreference( tr( "PREF_ISOS_U" ), isoGroup,
@@ -2569,6 +2613,46 @@ void GeometryGUI::preferencesChanged( const QString& section, const QString& par
aDisplayer.UpdateColorScale( anIsRedisplayFieldSteps, true );
}
}
+ else if ( param == QString("dimensions_color") ||
+ param == QString("dimensions_line_width") ||
+ param == QString("dimensions_font_height") ||
+ param == QString("dimensions_arrow_length") ||
+ param == QString("dimensions_show_units") ||
+ param == QString("dimensions_length_units") ||
+ param == QString("dimensions_angle_units") )
+ {
+ SalomeApp_Application* anApp = getApp();
+ if ( !anApp )
+ {
+ return;
+ }
+
+ SalomeApp_Study* aStudy = dynamic_cast( anApp->activeStudy() );
+ if ( !aStudy )
+ {
+ return;
+ }
+
+ GEOM_Displayer aDisplayer( aStudy );
+
+ ViewManagerList aVMs;
+ anApp->viewManagers( OCCViewer_Viewer::Type(), aVMs );
+ ViewManagerList::Iterator anIt = aVMs.begin();
+ for ( ; anIt != aVMs.end(); ++anIt )
+ {
+ SOCC_Viewer* aViewer = dynamic_cast( (*anIt)->getViewModel() );
+ if ( !aViewer )
+ {
+ continue;
+ }
+
+ SALOME_ListIO aVisible;
+ aViewer->GetVisible( aVisible );
+ aDisplayer.Redisplay( aVisible, false, aViewer );
+ }
+
+ aDisplayer.UpdateViewer();
+ }
}
}
diff --git a/src/GEOMGUI/GeometryGUI_Operations.h b/src/GEOMGUI/GeometryGUI_Operations.h
index 304220b0b..d24ba7d8e 100644
--- a/src/GEOMGUI/GeometryGUI_Operations.h
+++ b/src/GEOMGUI/GeometryGUI_Operations.h
@@ -189,6 +189,7 @@ namespace GEOMOp {
OpPointCoordinates = 5011, // MENU MEASURES - POINT COORDINATES
OpCheckSelfInters = 5012, // MENU MEASURES - CHECK SELF INTERSECTIONS
OpGetNonBlocks = 5013, // MENU MEASURES - GET NON BLOCKS
+ OpManageDimensions = 5014, // MENU MEASURES - MANAGE DIMENSIONS
// GroupGUI --------------------//--------------------------------
OpGroupCreate = 6000, // MENU GROUP - CREATE
OpGroupEdit = 6001, // MENU GROUP - EDIT
diff --git a/src/MeasureGUI/CMakeLists.txt b/src/MeasureGUI/CMakeLists.txt
index 809520ee8..2c6a39430 100755
--- a/src/MeasureGUI/CMakeLists.txt
+++ b/src/MeasureGUI/CMakeLists.txt
@@ -41,6 +41,7 @@ INCLUDE_DIRECTORIES(
${PROJECT_SOURCE_DIR}/src/DlgRef
${PROJECT_BINARY_DIR}/src/DlgRef
${PROJECT_SOURCE_DIR}/src/GEOMAlgo
+ ${PROJECT_SOURCE_DIR}/src/GEOMUtils
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_BINARY_DIR}
)
@@ -55,6 +56,7 @@ ADD_DEFINITIONS(
# libraries to link to
SET(_link_LIBRARIES
GEOMBase
+ GEOMUtils
)
# --- resources ---
@@ -67,7 +69,11 @@ SET(_uic_files
MeasureGUI_1Sel1TextView_QTD.ui
MeasureGUI_1Sel3LineEdit_QTD.ui
MeasureGUI_1Sel6LineEdit_QTD.ui
+ MeasureGUI_1Sel_Frame_QTD.ui
+ MeasureGUI_1TreeWidget_4Button_QTD.ui
MeasureGUI_2Sel1LineEdit_QTD.ui
+ MeasureGUI_2Sel_Frame_QTD.ui
+ MeasureGUI_3Sel_Frame_QTD.ui
MeasureGUI_SkeletonBox_QTD.ui
)
@@ -91,6 +97,11 @@ SET(MeasureGUI_HEADERS
MeasureGUI_GetNonBlocksDlg.h
MeasureGUI_CheckSelfIntersectionsDlg.h
MeasureGUI_PointDlg.h
+ MeasureGUI_ManageDimensionsDlg.h
+ MeasureGUI_CreateDimensionDlg.h
+ MeasureGUI_DimensionCreateTool.h
+ MeasureGUI_DimensionInteractor.h
+ MeasureGUI_DimensionFilter.h
)
# header files / to be processed by moc
@@ -111,6 +122,9 @@ SET(_moc_HEADERS
MeasureGUI_GetNonBlocksDlg.h
MeasureGUI_CheckSelfIntersectionsDlg.h
MeasureGUI_PointDlg.h
+ MeasureGUI_ManageDimensionsDlg.h
+ MeasureGUI_CreateDimensionDlg.h
+ MeasureGUI_DimensionInteractor.h
)
# header files / uic wrappings
@@ -139,6 +153,11 @@ SET(MeasureGUI_SOURCES
MeasureGUI_GetNonBlocksDlg.cxx
MeasureGUI_CheckSelfIntersectionsDlg.cxx
MeasureGUI_PointDlg.cxx
+ MeasureGUI_ManageDimensionsDlg.cxx
+ MeasureGUI_CreateDimensionDlg.cxx
+ MeasureGUI_DimensionCreateTool.cxx
+ MeasureGUI_DimensionInteractor.cxx
+ MeasureGUI_DimensionFilter.cxx
${_moc_SOURCES}
${_uic_files}
)
diff --git a/src/MeasureGUI/MeasureGUI.cxx b/src/MeasureGUI/MeasureGUI.cxx
index 435a92a9f..e079e74bc 100644
--- a/src/MeasureGUI/MeasureGUI.cxx
+++ b/src/MeasureGUI/MeasureGUI.cxx
@@ -31,20 +31,21 @@
#include
#include
-#include "MeasureGUI_PropertiesDlg.h" // Method PROPERTIES
-#include "MeasureGUI_CenterMassDlg.h" // Method CENTER MASS
-#include "MeasureGUI_NormaleDlg.h" // Method NORMALE
-#include "MeasureGUI_InertiaDlg.h" // Method INERTIA
-#include "MeasureGUI_BndBoxDlg.h" // Method BNDBOX
-#include "MeasureGUI_DistanceDlg.h" // Method DISTANCE
-#include "MeasureGUI_AngleDlg.h" // Method ANGLE
-#include "MeasureGUI_MaxToleranceDlg.h" // Method MAXTOLERANCE
-#include "MeasureGUI_WhatisDlg.h" // Method WHATIS
-#include "MeasureGUI_CheckShapeDlg.h" // Method CHECKSHAPE
-#include "MeasureGUI_CheckCompoundOfBlocksDlg.h" // Method CHECKCOMPOUND
-#include "MeasureGUI_GetNonBlocksDlg.h" // Method GET NON BLOCKS
+#include "MeasureGUI_PropertiesDlg.h" // Method PROPERTIES
+#include "MeasureGUI_CenterMassDlg.h" // Method CENTER MASS
+#include "MeasureGUI_NormaleDlg.h" // Method NORMALE
+#include "MeasureGUI_InertiaDlg.h" // Method INERTIA
+#include "MeasureGUI_BndBoxDlg.h" // Method BNDBOX
+#include "MeasureGUI_DistanceDlg.h" // Method DISTANCE
+#include "MeasureGUI_AngleDlg.h" // Method ANGLE
+#include "MeasureGUI_MaxToleranceDlg.h" // Method MAXTOLERANCE
+#include "MeasureGUI_WhatisDlg.h" // Method WHATIS
+#include "MeasureGUI_CheckShapeDlg.h" // Method CHECKSHAPE
+#include "MeasureGUI_CheckCompoundOfBlocksDlg.h" // Method CHECKCOMPOUND
+#include "MeasureGUI_GetNonBlocksDlg.h" // Method GET NON BLOCKS
#include "MeasureGUI_CheckSelfIntersectionsDlg.h" // Method CHECK SELF INTERSCTIONS
-#include "MeasureGUI_PointDlg.h" // Method POINTCOORDINATES
+#include "MeasureGUI_PointDlg.h" // Method POINTCOORDINATES
+#include "MeasureGUI_ManageDimensionsDlg.h" // Method MANAGEDIMENSIONS
#include
@@ -120,6 +121,9 @@ bool MeasureGUI::OnGUIEvent( int theCommandID, SUIT_Desktop* parent )
case GEOMOp::OpPointCoordinates:
dlg = new MeasureGUI_PointDlg( getGeometryGUI(), parent );
break; // POINT COORDINATES
+ case GEOMOp::OpManageDimensions:
+ dlg = new MeasureGUI_ManageDimensionsDlg( getGeometryGUI(), parent );
+ break; // MANAGE DIMENSIONS
default:
app->putInfo( tr( "GEOM_PRP_COMMAND" ).arg( theCommandID ) );
break;
diff --git a/src/MeasureGUI/MeasureGUI_1Sel_Frame_QTD.ui b/src/MeasureGUI/MeasureGUI_1Sel_Frame_QTD.ui
new file mode 100644
index 000000000..3d46ee146
--- /dev/null
+++ b/src/MeasureGUI/MeasureGUI_1Sel_Frame_QTD.ui
@@ -0,0 +1,83 @@
+
+
+ MeasureGUI_1Sel_Frame_QTD
+
+
+
+ 0
+ 0
+ 155
+ 45
+
+
+
+
+
+
+
+ 0
+
+
+ 0
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 9
+
+
+ 6
+
+
-
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ TL1
+
+
+ false
+
+
+
+
+
+
+
+
+
+ qPixmapFromMimeSource
+
+ PushButton1
+ LineEdit1
+
+
+
+
diff --git a/src/MeasureGUI/MeasureGUI_1TreeWidget_4Button_QTD.ui b/src/MeasureGUI/MeasureGUI_1TreeWidget_4Button_QTD.ui
new file mode 100644
index 000000000..5aa2cbb23
--- /dev/null
+++ b/src/MeasureGUI/MeasureGUI_1TreeWidget_4Button_QTD.ui
@@ -0,0 +1,105 @@
+
+
+ MeasureGUI_1TreeWidget_4Button_QTD
+
+
+
+ 0
+ 0
+ 341
+ 450
+
+
+
+
+ 0
+ 0
+
+
+
+
+
+
+
+ 0
+
+
+ 6
+
+ -
+
+
+
+ 9
+
+
+ 6
+
+
-
+
+
-
+
+
+
+
+
+
+
+
+ -
+
+
-
+
+
+
+
+
+
+ -
+
+
+
+
+
+
+ -
+
+
+
+
+
+
+ -
+
+
+
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ qPixmapFromMimeSource
+
+
+
diff --git a/src/MeasureGUI/MeasureGUI_2Sel_Frame_QTD.ui b/src/MeasureGUI/MeasureGUI_2Sel_Frame_QTD.ui
new file mode 100644
index 000000000..76cd89d1f
--- /dev/null
+++ b/src/MeasureGUI/MeasureGUI_2Sel_Frame_QTD.ui
@@ -0,0 +1,117 @@
+
+
+ MeasureGUI_2Sel_Frame_QTD
+
+
+
+ 0
+ 0
+ 156
+ 74
+
+
+
+
+ 0
+ 0
+
+
+
+
+
+
+
+ 0
+
+
+ 6
+
+ -
+
+
+
+ 9
+
+
+ 6
+
+
-
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ TL1
+
+
+ false
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ TL2
+
+
+ false
+
+
+
+ -
+
+
+
+
+
+
+
+
+ qPixmapFromMimeSource
+
+ PushButton1
+ LineEdit1
+ PushButton2
+ LineEdit2
+
+
+
+
diff --git a/src/MeasureGUI/MeasureGUI_3Sel_Frame_QTD.ui b/src/MeasureGUI/MeasureGUI_3Sel_Frame_QTD.ui
new file mode 100644
index 000000000..3d2787b7c
--- /dev/null
+++ b/src/MeasureGUI/MeasureGUI_3Sel_Frame_QTD.ui
@@ -0,0 +1,151 @@
+
+
+ MeasureGUI_3Sel_Frame_QTD
+
+
+
+ 0
+ 0
+ 156
+ 103
+
+
+
+
+ 0
+ 0
+
+
+
+
+
+
+
+ 0
+
+
+ 6
+
+ -
+
+
+
+ 9
+
+
+ 6
+
+
-
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ TL1
+
+
+ false
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ TL2
+
+
+ false
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ TL3
+
+
+ false
+
+
+
+ -
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+
+
+
+ -
+
+
+
+
+
+
+
+
+ qPixmapFromMimeSource
+
+ PushButton1
+ LineEdit1
+ PushButton2
+ LineEdit2
+ PushButton3
+ LineEdit3
+
+
+
+
diff --git a/src/MeasureGUI/MeasureGUI_AngleDlg.cxx b/src/MeasureGUI/MeasureGUI_AngleDlg.cxx
index 8dfeeea01..df482d067 100644
--- a/src/MeasureGUI/MeasureGUI_AngleDlg.cxx
+++ b/src/MeasureGUI/MeasureGUI_AngleDlg.cxx
@@ -320,33 +320,6 @@ SALOME_Prs* MeasureGUI_AngleDlg::buildPrs()
TopoDS_Edge anEdge1 = TopoDS::Edge(S1);
TopoDS_Edge anEdge2 = TopoDS::Edge(S2);
- // Build a plane for angle dimension presentation {P11, P12, P3}
- TopoDS_Vertex V11, V12, V21, V22;
- TopExp::Vertices(anEdge1, V11, V12);
- TopExp::Vertices(anEdge2, V21, V22);
-
- gp_Pnt aP11 = BRep_Tool::Pnt(TopExp::FirstVertex(anEdge1));
- gp_Pnt aP12 = BRep_Tool::Pnt(TopExp::LastVertex (anEdge1));
-
- gp_Pnt aP21 = BRep_Tool::Pnt(TopExp::FirstVertex(anEdge2));
- gp_Pnt aP22 = BRep_Tool::Pnt(TopExp::LastVertex (anEdge2));
-
- // *P3
- // \
- // \
- // *P22
- // /
- // /
- // P11 / P12
- // *-----/----------*
- // \ /
- // \ /
- // *P21
- gp_Pnt aP3 (aP22.XYZ() + aP11.XYZ() - aP21.XYZ());
-
- gce_MakePln gce_MP(aP11, aP12, aP3);
- Handle(Geom_Plane) aPlane = new Geom_Plane(gce_MP.Value());
-
Handle(AIS_AngleDimension) anIO = new AIS_AngleDimension( anEdge1, anEdge2 );
Handle(Prs3d_DimensionAspect) aDimensionStyle = new Prs3d_DimensionAspect;
@@ -356,6 +329,7 @@ SALOME_Prs* MeasureGUI_AngleDlg::buildPrs()
Standard_Boolean isInfinite1,isInfinite2;
Handle(Geom_Curve) extCurv;
Standard_Integer extShape;
+ Handle(Geom_Plane) aPlane;
if (AIS::ComputeGeometry(anEdge1,
anEdge2,
extShape,
diff --git a/src/MeasureGUI/MeasureGUI_CreateDimensionDlg.cxx b/src/MeasureGUI/MeasureGUI_CreateDimensionDlg.cxx
new file mode 100644
index 000000000..4daaf6039
--- /dev/null
+++ b/src/MeasureGUI/MeasureGUI_CreateDimensionDlg.cxx
@@ -0,0 +1,950 @@
+// Copyright (C) 2007-2013 CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+// GEOM GEOMGUI : GUI for Geometry component
+// File : MeasureGUI_CreateDimensionDlg.cxx
+// Author : Anton POLETAEV, Open CASCADE S.A.S.
+
+#include "MeasureGUI_CreateDimensionDlg.h"
+#include "MeasureGUI_DimensionCreateTool.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+//=================================================================================
+// function : Constructor
+// purpose :
+//=================================================================================
+MeasureGUI_CreateDimensionDlg::MeasureGUI_CreateDimensionDlg( const GEOM::GeomObjPtr& theObj,
+ GeometryGUI* theGUI,
+ QWidget* theParent )
+: GEOMBase_Skeleton( theGUI, theParent ),
+ myParentObj( theObj ),
+ myEditingViewer( NULL )
+{
+ setWindowTitle( tr( "CREATE_DIMENSION_TITLE" ) );
+
+ // init "dimension type" radio buttons
+ QAbstractButton* aTypeButtonLength = mainFrame()->RadioButton1;
+ QAbstractButton* aTypeButtonDiameter = mainFrame()->RadioButton2;
+ QAbstractButton* aTypeButtonAngle = mainFrame()->RadioButton3;
+
+ mainFrame()->GroupConstructors->setTitle( tr( "DIMENSIONS" ) );
+ aTypeButtonDiameter->setText( tr( "DIAMETER" ) );
+ aTypeButtonLength->setText( tr( "LENGTH" ) );
+ aTypeButtonAngle->setText( tr( "ANGLE" ) );
+
+ // construct "arguments" pane
+ QGroupBox* aGroupArgs = new QGroupBox( tr( "ARGUMENTS" ), centralWidget() );
+ QVBoxLayout* aGroupArgsLayout = new QVBoxLayout( aGroupArgs );
+
+ myLengthArgs = new LengthPane ( centralWidget() );
+ myDiameterArgs = new DiameterPane( centralWidget() );
+ myAngleArgs = new AnglePane ( centralWidget() );
+
+ // connect selector pane signals
+ connect( myLengthArgs, SIGNAL( StartSelection( const QList& ) ),
+ SLOT( OnStartSelection( const QList& ) ) );
+ connect( myDiameterArgs, SIGNAL( StartSelection( const QList& ) ),
+ SLOT( OnStartSelection( const QList& ) ) );
+ connect( myAngleArgs, SIGNAL( StartSelection( const QList& ) ),
+ SLOT( OnStartSelection( const QList& ) ) );
+
+ connect( myLengthArgs, SIGNAL( StopSelection() ), SLOT( OnStopSelection() ) );
+ connect( myDiameterArgs, SIGNAL( StopSelection() ), SLOT( OnStopSelection() ) );
+ connect( myAngleArgs, SIGNAL( StopSelection() ), SLOT( OnStopSelection( ) ) );
+
+ connect( myLengthArgs, SIGNAL( SelectionDone() ), SLOT( OnSelectionDone() ) );
+ connect( myDiameterArgs, SIGNAL( SelectionDone() ), SLOT( OnSelectionDone() ) );
+ connect( myAngleArgs, SIGNAL( SelectionDone() ), SLOT( OnSelectionDone() ) );
+
+ aGroupArgsLayout->addWidget( myLengthArgs );
+ aGroupArgsLayout->addWidget( myDiameterArgs );
+ aGroupArgsLayout->addWidget( myAngleArgs );
+
+ // construct main layout
+ QVBoxLayout* aCustomWidLayout = new QVBoxLayout( centralWidget() );
+ aCustomWidLayout->setMargin( 0 );
+ aCustomWidLayout->setSpacing( 6 );
+ aCustomWidLayout->addWidget( aGroupArgs );
+
+ // add visibility rules for structural widgets
+ connect( aTypeButtonLength, SIGNAL( toggled(bool) ), myLengthArgs, SLOT( setVisible(bool) ) );
+ connect( aTypeButtonDiameter, SIGNAL( toggled(bool) ), myDiameterArgs, SLOT( setVisible(bool) ) );
+ connect( aTypeButtonAngle, SIGNAL( toggled(bool) ), myAngleArgs, SLOT( setVisible(bool) ) );
+
+ // signals and slots connections
+ connect( buttonOk(), SIGNAL( clicked() ), this, SLOT( ClickOnOk() ) );
+ connect( buttonApply(), SIGNAL( clicked() ), this, SLOT( ClickOnApply() ) );
+
+ // map functional signals
+ myRBGroup->setId( aTypeButtonLength, TypeButtonID_Length );
+ myRBGroup->setId( aTypeButtonDiameter, TypeButtonID_Diameter );
+ myRBGroup->setId( aTypeButtonAngle, TypeButtonID_Angle );
+
+ connect( this, SIGNAL( constructorsClicked( int ) ), SLOT( ConstructTypeChanged( int ) ) );
+ connect( myLengthArgs, SIGNAL( TabChanged() ), SLOT( OnArgumentTabChanged() ) );
+ connect( myDiameterArgs, SIGNAL( TabChanged() ), SLOT( OnArgumentTabChanged() ) );
+ connect( myAngleArgs, SIGNAL( TabChanged() ), SLOT( OnArgumentTabChanged() ) );
+
+ myDimensionInteractor = new MeasureGUI_DimensionInteractor( theGUI, theParent );
+
+ Init();
+}
+
+//=================================================================================
+// function : Destructor
+// purpose :
+//=================================================================================
+MeasureGUI_CreateDimensionDlg::~MeasureGUI_CreateDimensionDlg()
+{
+}
+
+//=================================================================================
+// function : ActiveArgs
+// purpose :
+//=================================================================================
+MeasureGUI_CreateDimensionDlg::BaseSelectorPane* MeasureGUI_CreateDimensionDlg::ActiveArgs()
+{
+ switch ( getConstructorId() )
+ {
+ case TypeButtonID_Length : return myLengthArgs;
+ case TypeButtonID_Diameter : return myDiameterArgs;
+ case TypeButtonID_Angle : return myAngleArgs;
+ default:
+ return NULL;
+ }
+}
+
+//=================================================================================
+// function : GenerateName
+// purpose :
+//=================================================================================
+QString MeasureGUI_CreateDimensionDlg::GenerateName( const QString& thePrefix )
+{
+ QRegExp anExtractIds( "^" + thePrefix + "_([0-9]+)$" );
+
+ QSet anOccupiedIds;
+
+ GEOMGUI_DimensionProperty aProp =
+ getStudy()->getObjectProperty( GEOM::sharedPropertiesId(),
+ myParentObj->GetStudyEntry(),
+ GEOM::propertyName( GEOM::Dimensions ),
+ QVariant() )
+ .value();
+
+ // get names and convert to QStrings to perform index matching
+ for( int anIt = 0; anIt < aProp.GetNumber(); ++anIt )
+ {
+ if ( anExtractIds.indexIn( aProp.GetName( anIt ) ) == -1 )
+ {
+ continue;
+ }
+
+ anOccupiedIds.insert( anExtractIds.cap( 1 ).toInt() );
+ }
+
+ int aSearchId = 1;
+ while ( true )
+ {
+ if ( !anOccupiedIds.contains( aSearchId ) )
+ {
+ break;
+ }
+
+ aSearchId++;
+ }
+
+ return QString( thePrefix + "_%1" ).arg( aSearchId );
+}
+
+//=================================================================================
+// function : ConstructTypeChanged
+// purpose :
+//=================================================================================
+void MeasureGUI_CreateDimensionDlg::ConstructTypeChanged( int theType )
+{
+ ActiveArgs()->Reset();
+
+ updateGeometry();
+
+ QString aName;
+ switch ( theType )
+ {
+ case TypeButtonID_Length : aName = GenerateName( tr("NAME_LENGTH") ); break;
+ case TypeButtonID_Diameter : aName = GenerateName( tr("NAME_DIAMETER") ); break;
+ case TypeButtonID_Angle : aName = GenerateName( tr("NAME_ANGLE") ); break;
+ }
+
+ myMainFrame->ResultName->setText( aName );
+
+ StopLocalEditing();
+ erasePreview();
+
+ updateGeometry();
+ resize( minimumSizeHint() );
+}
+
+//=================================================================================
+// function : OnArgumentTabChanged
+// purpose :
+//=================================================================================
+void MeasureGUI_CreateDimensionDlg::OnArgumentTabChanged()
+{
+ StopLocalEditing();
+ erasePreview();
+}
+
+//=================================================================================
+// function : OnStartSelection
+// purpose :
+//=================================================================================
+void MeasureGUI_CreateDimensionDlg::OnStartSelection( const QList& theModes )
+{
+ OnStopSelection();
+
+ StopLocalEditing();
+
+ QList::const_iterator aModeIt = theModes.constBegin();
+ for ( ; aModeIt != theModes.constEnd(); ++aModeIt )
+ {
+ localSelection( myParentObj.get(), *aModeIt );
+ }
+
+ mySelectionModes = theModes;
+
+ connect( myGeomGUI->getApp()->selectionMgr(),
+ SIGNAL( currentSelectionChanged() ),
+ SLOT( SelectionIntoArgument() ) );
+}
+
+//=================================================================================
+// function : OnStopSelection
+// purpose :
+//=================================================================================
+void MeasureGUI_CreateDimensionDlg::OnStopSelection()
+{
+ globalSelection();
+
+ disconnect( myGeomGUI->getApp()->selectionMgr(),
+ SIGNAL( currentSelectionChanged() ),
+ this,
+ SLOT( SelectionIntoArgument() ) );
+}
+
+//=================================================================================
+// function : SelectionIntoArgument
+// purpose : Handle model selection by active selector pane
+//=================================================================================
+void MeasureGUI_CreateDimensionDlg::SelectionIntoArgument()
+{
+ LightApp_SelectionMgr* aSelectionMgr = myGeomGUI->getApp()->selectionMgr();
+ SALOME_ListIO aSelection;
+ aSelectionMgr->selectedObjects( aSelection );
+
+ if ( aSelection.Extent() != 1 )
+ {
+ ActiveArgs()->SelectionIntoArguments( GEOM::GeomObjPtr() );
+ return;
+ }
+
+ StopLocalEditing();
+
+ erasePreview();
+
+ ActiveArgs()->SelectionIntoArguments( getSelected( mySelectionModes ) );
+}
+
+//=================================================================================
+// function : OnSelectionDone
+// purpose :
+//=================================================================================
+void MeasureGUI_CreateDimensionDlg::OnSelectionDone()
+{
+ // create new dimension presentation
+ myDimension = CreateDimension();
+
+ if ( myDimension.IsNull() )
+ {
+ // can not create preview, repeat selection
+ SUIT_MessageBox::warning( this,
+ tr( "WARNING_TITLE_CANNOT_CREATE_DIMENSION" ),
+ tr( "WARNING_MSG_INVALID_ARGUMENTS" ) );
+
+ ActiveArgs()->Reset();
+
+ return;
+ }
+
+ // show preview of dimension object
+ SUIT_ViewWindow* aViewWindow = SUIT_Session::session()->activeApplication()->desktop()->activeWindow();
+
+ SOCC_Prs* aSalomePrs = dynamic_cast( ( (SOCC_Viewer*)( aViewWindow->getViewManager()->getViewModel() ) )->CreatePrs( 0 ) );
+
+ aSalomePrs->AddObject( myDimension );
+
+ displayPreview( aSalomePrs );
+
+ StartLocalEditing();
+}
+
+//=================================================================================
+// function : ClickOnOk
+// purpose :
+//=================================================================================
+void MeasureGUI_CreateDimensionDlg::ClickOnOk()
+{
+ setIsApplyAndClose( true );
+ if ( ClickOnApply() )
+ {
+ ClickOnCancel();
+ }
+}
+
+//=================================================================================
+// function : ClickOnApply
+// purpose :
+//=================================================================================
+bool MeasureGUI_CreateDimensionDlg::ClickOnApply()
+{
+ StopLocalEditing();
+
+ if ( !AddDimensionToOwner() )
+ {
+ return false;
+ }
+
+ redisplay( myParentObj.get() );
+
+ if ( !isApplyAndClose() )
+ {
+ Init();
+ }
+
+ return true;
+}
+
+//=================================================================================
+// function : StartLocalEditing
+// purpose :
+//=================================================================================
+void MeasureGUI_CreateDimensionDlg::StartLocalEditing()
+{
+ StopLocalEditing();
+
+ myDimensionInteractor->Enable();
+
+ if ( myDimension.IsNull() )
+ {
+ return;
+ }
+
+ SalomeApp_Application* anApp = myGeomGUI->getApp();
+
+ SUIT_ViewManager* aViewMgr = anApp->activeViewManager();
+
+ if ( aViewMgr->getType() != OCCViewer_Viewer::Type() )
+ {
+ return;
+ }
+
+ SOCC_Viewer* anOCCViewer = dynamic_cast( aViewMgr->getViewModel() );
+
+ myEditingViewer = anOCCViewer;
+ if ( !myEditingViewer )
+ {
+ return;
+ }
+
+ Handle(AIS_InteractiveContext) anAISContext = myEditingViewer->getAISContext();
+ Handle(V3d_Viewer) aViewer3d = myEditingViewer->getViewer3d();
+
+ aViewer3d->AddZLayer( myEditingLayer );
+
+ anAISContext->OpenLocalContext( Standard_False, Standard_False );
+ anAISContext->Load( myDimension, AIS_DSM_All );
+ anAISContext->SetZLayer( myDimension, myEditingLayer );
+ anAISContext->Activate( myDimension, AIS_DSM_Line );
+ anAISContext->Activate( myDimension, AIS_DSM_Text );
+}
+
+//=================================================================================
+// function : StopLocalEditing
+// purpose :
+//=================================================================================
+void MeasureGUI_CreateDimensionDlg::StopLocalEditing()
+{
+ myDimensionInteractor->Disable();
+
+ if ( !myEditingViewer )
+ {
+ return;
+ }
+
+ Handle(AIS_InteractiveContext) anAISContext = myEditingViewer->getAISContext();
+ Handle(V3d_Viewer) aViewer3d = myEditingViewer->getViewer3d();
+
+ aViewer3d->RemoveZLayer( myEditingLayer );
+ anAISContext->CloseLocalContext();
+
+ myEditingViewer = NULL;
+}
+
+//=================================================================================
+// function : Init
+// purpose :
+//=================================================================================
+void MeasureGUI_CreateDimensionDlg::Init()
+{
+ StopLocalEditing();
+
+ erasePreview();
+
+ myDiameterArgs->setVisible( false );
+ myAngleArgs ->setVisible( false );
+ myLengthArgs ->setVisible( true );
+ myLengthArgs->Reset();
+
+ myRBGroup->button( TypeButtonID_Length )->click();
+}
+
+//=================================================================================
+// function : CreateDimensionPrs
+// purpose :
+//=================================================================================
+Handle(AIS_Dimension) MeasureGUI_CreateDimensionDlg::CreateDimension()
+{
+ Handle(AIS_Dimension) aDimensionIO;
+
+ // prepare dimension styling
+ SUIT_ResourceMgr* aResMgr = SUIT_Session::session()->resourceMgr();
+
+ QColor aQColor = aResMgr->colorValue ( "Geometry", "dimensions_color", QColor( 0, 255, 0 ) );
+ 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 );
+ 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 );
+
+ switch ( getConstructorId() )
+ {
+ // create length dimension
+ case TypeButtonID_Length :
+ {
+ LengthPane* aLengthPane = qobject_cast( ActiveArgs() );
+
+ switch (aLengthPane->ActiveTab())
+ {
+ case LengthPane::TabID_SingleEdge:
+ {
+ const GEOM::GeomObjPtr& anEdge = aLengthPane->GetSingleEdge();
+
+ aDimensionIO = aTool.LengthOnEdge( anEdge );
+ break;
+ }
+
+ case LengthPane::TabID_TwoPoints:
+ {
+ const GEOM::GeomObjPtr& aPoint1 = aLengthPane->GetPoint1();
+ const GEOM::GeomObjPtr& aPoint2 = aLengthPane->GetPoint2();
+
+ aDimensionIO = aTool.LengthByPoints( aPoint1, aPoint2 );
+ break;
+ }
+
+ case LengthPane::TabID_ParallelEdges:
+ {
+ const GEOM::GeomObjPtr& anEdge1 = aLengthPane->GetEdge1();
+ const GEOM::GeomObjPtr& anEdge2 = aLengthPane->GetEdge2();
+
+ aDimensionIO = aTool.LengthByParallelEdges( anEdge1, anEdge2 );
+ break;
+ }
+ }
+ }
+ break;
+
+ // create diameter dimension
+ case TypeButtonID_Diameter :
+ {
+ DiameterPane* aDiameterPane = qobject_cast( ActiveArgs() );
+
+ const GEOM::GeomObjPtr& aShape = aDiameterPane->GetShape();
+
+ aDimensionIO = aTool.Diameter( aShape );
+ break;
+ }
+
+ // create angle dimension
+ case TypeButtonID_Angle :
+ {
+ AnglePane* anAnglePane = qobject_cast( ActiveArgs() );
+
+ switch (ActiveArgs()->ActiveTab())
+ {
+ case AnglePane::TabID_TwoEdges:
+ {
+ const GEOM::GeomObjPtr& anEdge1 = anAnglePane->GetEdge1();
+ const GEOM::GeomObjPtr& anEdge2 = anAnglePane->GetEdge2();
+
+ aDimensionIO = aTool.AngleByTwoEdges( anEdge1, anEdge2 );
+ break;
+ }
+
+ case AnglePane::TabID_ThreePoints:
+ {
+ const GEOM::GeomObjPtr& aPoint1 = anAnglePane->GetPoint1();
+ const GEOM::GeomObjPtr& aPoint2 = anAnglePane->GetPoint2();
+ const GEOM::GeomObjPtr& aPoint3 = anAnglePane->GetPoint3();
+
+ aDimensionIO = aTool.AngleByThreePoints( aPoint1, aPoint2, aPoint3 );
+ break;
+ }
+ }
+ break;
+ }
+ }
+
+ if ( aDimensionIO.IsNull() )
+ {
+ return NULL;
+ }
+
+ Quantity_Color aColor( aQColor.redF(), aQColor.greenF(), aQColor.blueF(), Quantity_TOC_RGB );
+
+ Handle(Prs3d_DimensionAspect) aStyle = new Prs3d_DimensionAspect();
+
+ aStyle->SetCommonColor( aColor );
+ aStyle->MakeUnitsDisplayed( (Standard_Boolean) isUnitsShown );
+ aStyle->MakeText3d( Standard_True );
+ aStyle->MakeTextShaded( Standard_True );
+ aStyle->TextAspect()->SetHeight( aFontHeight );
+ aStyle->ArrowAspect()->SetLength( anArrowLength );
+ aStyle->LineAspect()->SetWidth( aLineWidth );
+ aDimensionIO->SetDimensionAspect( aStyle );
+ aDimensionIO->SetPolygonOffsets( Aspect_POM_Fill, -1.0, -1.0 );
+
+ return aDimensionIO;
+}
+
+//=================================================================================
+// class : AddDimensionToOwner
+// purpose :
+//=================================================================================
+bool MeasureGUI_CreateDimensionDlg::AddDimensionToOwner()
+{
+ if ( myDimension.IsNull() )
+ {
+ return false;
+ }
+
+ gp_Ax3 aLCS;
+ TopoDS_Shape anParentSh;
+ if ( GEOMBase::GetShape( myParentObj.get(), anParentSh ) )
+ {
+ aLCS = GEOMUtils::GetPosition( anParentSh );
+ }
+
+ QString aName = getNewObjectName();
+
+ SalomeApp_Study* aStudy = getStudy();
+
+ GEOMGUI_DimensionProperty aProp =
+ aStudy->getObjectProperty( GEOM::sharedPropertiesId(),
+ myParentObj->GetStudyEntry(),
+ GEOM::propertyName( GEOM::Dimensions ),
+ QVariant() )
+ .value();
+
+ // append new dimension record to data
+ aProp.AddRecord( myDimension, aLCS );
+ aProp.SetName( aProp.GetNumber() - 1, aName );
+ aProp.SetVisible( aProp.GetNumber() - 1, true );
+
+ // store modified property data
+ aStudy->setObjectProperty( GEOM::sharedPropertiesId(),
+ myParentObj->GetStudyEntry(),
+ GEOM::propertyName( GEOM::Dimensions ),
+ aProp );
+
+ return true;
+}
+
+/* ------------------------------------------------------------------------------*
+ * *
+ * Argument shape selector layout *
+ * *
+ * ------------------------------------------------------------------------------*/
+
+//=================================================================================
+// class : MeasureGUI_CreateDimensionDlg::LengthPane
+// purpose : Constructor
+//=================================================================================
+MeasureGUI_CreateDimensionDlg::LengthPane::LengthPane( QWidget* theParent )
+: BaseSelectorPane( theParent )
+{
+ myTabs = new QTabWidget( this );
+ mySingleEdgeSelectors = new MeasureGUI_1Sel_Frame( this );
+ myTwoPointsSelectors = new MeasureGUI_2Sel_Frame( this );
+ myParallelEdgesSelectors = new MeasureGUI_2Sel_Frame( this );
+
+ myTabs->addTab( mySingleEdgeSelectors, MeasureGUI_CreateDimensionDlg::tr( "EDGE_LENGTH" ) );
+ myTabs->addTab( myTwoPointsSelectors, MeasureGUI_CreateDimensionDlg::tr( "TWO_POINTS" ) );
+ myTabs->addTab( myParallelEdgesSelectors, MeasureGUI_CreateDimensionDlg::tr( "PARALLEL_EDGES" ) );
+
+ mySingleEdgeSelectors->PushButton1->setIcon( mySelectorIcon );
+ mySingleEdgeSelectors->TextLabel1->setText( MeasureGUI_CreateDimensionDlg::tr( "EDGE" ) );
+ mySingleEdgeSelectors->LineEdit1->setReadOnly( true );
+
+ myTwoPointsSelectors->PushButton1->setIcon( mySelectorIcon );
+ myTwoPointsSelectors->PushButton2->setIcon( mySelectorIcon );
+ myTwoPointsSelectors->TextLabel1->setText( MeasureGUI_CreateDimensionDlg::tr( "POINT_1" ) );
+ myTwoPointsSelectors->TextLabel2->setText( MeasureGUI_CreateDimensionDlg::tr( "POINT_2" ) );
+ myTwoPointsSelectors->LineEdit1->setReadOnly( true );
+ myTwoPointsSelectors->LineEdit2->setReadOnly( true );
+
+ myParallelEdgesSelectors->PushButton1->setIcon( mySelectorIcon );
+ myParallelEdgesSelectors->PushButton2->setIcon( mySelectorIcon );
+ myParallelEdgesSelectors->TextLabel1 ->setText( MeasureGUI_CreateDimensionDlg::tr( "EDGE_1" ) );
+ myParallelEdgesSelectors->TextLabel2 ->setText( MeasureGUI_CreateDimensionDlg::tr( "EDGE_2" ) );
+ myParallelEdgesSelectors->LineEdit1->setReadOnly( true );
+ myParallelEdgesSelectors->LineEdit2->setReadOnly( true );
+
+ QVBoxLayout* aLayout = new QVBoxLayout( this );
+
+ aLayout->setMargin( 0 );
+ aLayout->addWidget( myTabs );
+
+ SelectionModes anEdgeModes;
+ SelectionModes aPointModes;
+ anEdgeModes << TopAbs_EDGE;
+ aPointModes << TopAbs_VERTEX;
+
+ SetTabWidget( myTabs );
+ RegisterSelector( mySingleEdgeSelectors->LineEdit1, mySingleEdgeSelectors->PushButton1, anEdgeModes, TabID_SingleEdge );
+ RegisterSelector( myTwoPointsSelectors->LineEdit1, myTwoPointsSelectors->PushButton1, aPointModes, TabID_TwoPoints );
+ RegisterSelector( myTwoPointsSelectors->LineEdit2, myTwoPointsSelectors->PushButton2, aPointModes, TabID_TwoPoints );
+ RegisterSelector( myParallelEdgesSelectors->LineEdit1, myParallelEdgesSelectors->PushButton1, anEdgeModes, TabID_ParallelEdges );
+ RegisterSelector( myParallelEdgesSelectors->LineEdit2, myParallelEdgesSelectors->PushButton2, anEdgeModes, TabID_ParallelEdges );
+}
+
+//=================================================================================
+// class : MeasureGUI_CreateDimensionDlg::DiameterPane
+// purpose : Constructor
+//=================================================================================
+MeasureGUI_CreateDimensionDlg::DiameterPane::DiameterPane( QWidget* theParent )
+: BaseSelectorPane( theParent )
+{
+ myShapeSelector = new MeasureGUI_1Sel_Frame( this );
+ myShapeSelector->PushButton1->setIcon( mySelectorIcon );
+ myShapeSelector->TextLabel1 ->setText( MeasureGUI_CreateDimensionDlg::tr( "OBJECT" ) );
+
+ QVBoxLayout* aLayout = new QVBoxLayout( this );
+
+ aLayout->setMargin( 0 );
+ aLayout->addWidget( myShapeSelector );
+
+ SelectionModes aDiamModes;
+ aDiamModes << TopAbs_SHAPE
+ << TopAbs_FACE
+ << TopAbs_EDGE;
+
+ RegisterSelector( myShapeSelector->LineEdit1, myShapeSelector->PushButton1, aDiamModes );
+}
+
+//=================================================================================
+// class : MeasureGUI_CreateDimensionDlg::AnglePane
+// purpose : Constructor
+//=================================================================================
+MeasureGUI_CreateDimensionDlg::AnglePane::AnglePane( QWidget* theParent )
+: BaseSelectorPane( theParent )
+{
+ myTabs = new QTabWidget( this );
+ myTwoEdgesSelectors = new MeasureGUI_2Sel_Frame( this );
+ myThreePointsSelectors = new MeasureGUI_3Sel_Frame( this );
+
+ myTabs->addTab( myTwoEdgesSelectors, MeasureGUI_CreateDimensionDlg::tr( "TWO_EDGES" ) );
+ myTabs->addTab( myThreePointsSelectors, MeasureGUI_CreateDimensionDlg::tr( "THREE_POINTS" ) );
+
+ myTwoEdgesSelectors->PushButton1->setIcon( mySelectorIcon );
+ myTwoEdgesSelectors->PushButton2->setIcon( mySelectorIcon );
+ myTwoEdgesSelectors->TextLabel1 ->setText( MeasureGUI_CreateDimensionDlg::tr( "EDGE_1" ) );
+ myTwoEdgesSelectors->TextLabel2 ->setText( MeasureGUI_CreateDimensionDlg::tr( "EDGE_2" ) );
+
+ myThreePointsSelectors->PushButton1->setIcon( mySelectorIcon );
+ myThreePointsSelectors->PushButton2->setIcon( mySelectorIcon );
+ myThreePointsSelectors->PushButton3->setIcon( mySelectorIcon );
+ myThreePointsSelectors->TextLabel1 ->setText( MeasureGUI_CreateDimensionDlg::tr( "POINT_1" ) );
+ myThreePointsSelectors->TextLabel2 ->setText( MeasureGUI_CreateDimensionDlg::tr( "POINT_2" ) );
+ myThreePointsSelectors->TextLabel3 ->setText( MeasureGUI_CreateDimensionDlg::tr( "POINT_3" ) );
+
+ QVBoxLayout* aLayout = new QVBoxLayout( this );
+
+ aLayout->setMargin( 0 );
+ aLayout->addWidget( myTabs );
+
+ SelectionModes anEdgeModes;
+ SelectionModes aPointModes;
+ anEdgeModes << TopAbs_EDGE;
+ aPointModes << TopAbs_VERTEX;
+
+ SetTabWidget( myTabs );
+ RegisterSelector( myTwoEdgesSelectors->LineEdit1, myTwoEdgesSelectors->PushButton1, anEdgeModes, TabID_TwoEdges );
+ RegisterSelector( myTwoEdgesSelectors->LineEdit2, myTwoEdgesSelectors->PushButton2, anEdgeModes, TabID_TwoEdges );
+ RegisterSelector( myThreePointsSelectors->LineEdit1, myThreePointsSelectors->PushButton1, aPointModes, TabID_ThreePoints );
+ RegisterSelector( myThreePointsSelectors->LineEdit2, myThreePointsSelectors->PushButton2, aPointModes, TabID_ThreePoints );
+ RegisterSelector( myThreePointsSelectors->LineEdit3, myThreePointsSelectors->PushButton3, aPointModes, TabID_ThreePoints );
+}
+
+/* ------------------------------------------------------------------------------*
+ * *
+ * Argument shape selection logics *
+ * *
+ * ------------------------------------------------------------------------------*/
+
+//=================================================================================
+// class : MeasureGUI_CreateDimensionDlg::BaseSelectorPane
+// purpose : Constructor
+//=================================================================================
+MeasureGUI_CreateDimensionDlg::BaseSelectorPane::BaseSelectorPane( QWidget* theParent )
+: QWidget( theParent ),
+ myTabs( NULL )
+{
+ SUIT_ResourceMgr* aResMgr = SUIT_Session::session()->resourceMgr();
+ mySelectorIcon = aResMgr->loadPixmap( "GEOM", tr( "ICON_SELECT" ) );
+}
+
+//=================================================================================
+// function : BaseSelectorPane::Reset
+// purpose : Reset selector line edits and controls
+//=================================================================================
+void MeasureGUI_CreateDimensionDlg::BaseSelectorPane::Reset( bool theOpenDefaultTab )
+{
+ if ( theOpenDefaultTab && myTabs )
+ {
+ myTabs->setCurrentIndex( 0 );
+ }
+
+ QMap< int, QList >::iterator aTabsIt = mySelectors.begin();
+ for ( ; aTabsIt != mySelectors.end(); ++aTabsIt )
+ {
+ QList& aSelectors = *aTabsIt;
+ QList::iterator aSelectorIt = aSelectors.begin();
+ for ( ; aSelectorIt != aSelectors.end(); ++aSelectorIt )
+ {
+ QLineEdit* aSelector = *aSelectorIt;
+ aSelector->clear();
+ mySelectedShapes[aSelector] = GEOM::GeomObjPtr();
+ }
+ }
+
+ QLineEdit* aFirstSelector = mySelectors[ ActiveTab() ].first();
+
+ mySelectionButtons[aFirstSelector]->click();
+}
+
+//=================================================================================
+// function : BaseSelectorPane::ActiveTab
+// purpose : Returns active tab
+//=================================================================================
+int MeasureGUI_CreateDimensionDlg::BaseSelectorPane::ActiveTab() const
+{
+ return myTabs != NULL ? myTabs->currentIndex() : 0;
+}
+
+//=================================================================================
+// function : BaseSelectorPane::SelectionIntoArgument
+// purpose : Populates current selector
+//=================================================================================
+void MeasureGUI_CreateDimensionDlg::BaseSelectorPane::SelectionIntoArguments( const GEOM::GeomObjPtr& theSelected )
+{
+ if ( theSelected.isNull() )
+ {
+ myCurrentSelector->clear();
+ mySelectedShapes[myCurrentSelector] = GEOM::GeomObjPtr();
+ return;
+ }
+
+ QString aName = GEOMBase::GetName( theSelected.get() );
+
+ myCurrentSelector->setText( aName );
+
+ mySelectedShapes[myCurrentSelector] = theSelected;
+
+ // find next empty selector (iterate to the last)
+ QList& aCurrentSelectors = mySelectors[ ActiveTab() ];
+ int aCurrentPos = aCurrentSelectors.indexOf( myCurrentSelector );
+ int aSelectorIt = aCurrentPos + 1;
+ for ( ; aSelectorIt != aCurrentSelectors.size(); ++aSelectorIt )
+ {
+ QLineEdit* aNextSelector = aCurrentSelectors[aSelectorIt];
+ if ( mySelectedShapes[aNextSelector].isNull() )
+ {
+ mySelectionButtons[aNextSelector]->click();
+ return;
+ }
+ }
+
+ // find next empty selector (itearte from the first)
+ aSelectorIt = 0;
+ for ( ; aSelectorIt != aCurrentPos; ++aSelectorIt )
+ {
+ QLineEdit* aNextSelector = aCurrentSelectors[aSelectorIt];
+ if ( mySelectedShapes[aNextSelector].isNull() )
+ {
+ mySelectionButtons[aNextSelector]->click();
+ return;
+ }
+ }
+
+ // stop selector switching
+ myCurrentSelector->setEnabled( false );
+ mySelectionButtons[myCurrentSelector]->setDown( false );
+
+ // every selector is populated - construct presentation
+ emit StopSelection();
+ emit SelectionDone();
+}
+
+//=================================================================================
+// function : BaseSelectorPane::GetSelection
+// purpose :
+//=================================================================================
+GEOM::GeomObjPtr MeasureGUI_CreateDimensionDlg::BaseSelectorPane::GetSelection( QLineEdit* theSelector ) const
+{
+ return mySelectedShapes[theSelector];
+}
+
+//=================================================================================
+// function : BaseSelectorPane::OnSelectorClicked
+// purpose : Handle activation of selector controls pair {edit, button}
+//=================================================================================
+void MeasureGUI_CreateDimensionDlg::BaseSelectorPane::OnSelectorClicked()
+{
+ // clicked "selector" button
+ QAbstractButton* aSender = qobject_cast( sender() );
+ if ( !aSender )
+ {
+ return;
+ }
+
+ // get "selector" controls on the active tab
+ QList& aCurrentSelectors = mySelectors[ ActiveTab() ];
+
+ // iterate over controls on the tab and process them
+ for ( int aSelectorIt = 0; aSelectorIt < aCurrentSelectors.size(); ++aSelectorIt )
+ {
+ QLineEdit* aSelector = aCurrentSelectors[aSelectorIt];
+ QPushButton* aButton = mySelectionButtons[aSelector];
+
+ bool isClickedOnes = (aButton == aSender);
+
+ aSelector->setEnabled( isClickedOnes );
+
+ if ( isClickedOnes )
+ {
+ myCurrentSelector = aSelector;
+ myCurrentSelector->setFocus();
+ }
+
+ aButton->setDown( isClickedOnes );
+ }
+
+ emit StartSelection( mySelectionModes[myCurrentSelector] );
+}
+
+//=================================================================================
+// function : BaseSelectorPane::OnTabChanged
+// purpose :
+//=================================================================================
+void MeasureGUI_CreateDimensionDlg::BaseSelectorPane::OnTabChanged()
+{
+ QList& aSelectors = mySelectors[ ActiveTab() ];
+ QList::iterator aSelectorIt = aSelectors.begin();
+ for ( ; aSelectorIt != aSelectors.end(); ++aSelectorIt )
+ {
+ QLineEdit* aSelector = *aSelectorIt;
+
+ aSelector->clear();
+
+ mySelectedShapes[aSelector] = GEOM::GeomObjPtr();
+ }
+
+ QLineEdit* aFirstSelector = mySelectors[ ActiveTab() ].first();
+
+ mySelectionButtons[aFirstSelector]->click();
+
+ emit TabChanged();
+}
+
+//=================================================================================
+// function : BaseSelectorPane::SetTabWidget
+// purpose :
+//=================================================================================
+void MeasureGUI_CreateDimensionDlg::BaseSelectorPane::SetTabWidget( QTabWidget* theTabs )
+{
+ myTabs = theTabs;
+ connect( myTabs, SIGNAL( currentChanged( int ) ), this, SLOT( OnTabChanged() ) );
+}
+
+//=================================================================================
+// function : BaseSelectorPane::RegisterSelector
+// purpose :
+//=================================================================================
+void MeasureGUI_CreateDimensionDlg::BaseSelectorPane::RegisterSelector( QLineEdit* theSelectorEdit,
+ QPushButton* theSelectorButton,
+ const SelectionModes& theSelectorModes,
+ const int theTab )
+{
+ if ( !mySelectors.contains( theTab ) )
+ {
+ mySelectors.insert( theTab, QList() );
+ }
+ mySelectors[theTab].append( theSelectorEdit );
+
+ mySelectionButtons[theSelectorEdit] = theSelectorButton;
+ mySelectionModes [theSelectorEdit] = theSelectorModes;
+
+ connect( theSelectorButton, SIGNAL( clicked() ), this, SLOT( OnSelectorClicked() ) );
+}
diff --git a/src/MeasureGUI/MeasureGUI_CreateDimensionDlg.h b/src/MeasureGUI/MeasureGUI_CreateDimensionDlg.h
new file mode 100644
index 000000000..28293277a
--- /dev/null
+++ b/src/MeasureGUI/MeasureGUI_CreateDimensionDlg.h
@@ -0,0 +1,258 @@
+// Copyright (C) 2007-2013 CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+// GEOM GEOMGUI : GUI for Geometry component
+// File : MeasureGUI_CreateDimensionDlg.h
+// Author : Anton POLETAEV, Open CASCADE S.A.S.
+//
+#ifndef MEASUREGUI_CREATEDIMENSIONDLG_H
+#define MEASUREGUI_CREATEDIMENSIONDLG_H
+
+#include "MeasureGUI_Widgets.h"
+#include "MeasureGUI_DimensionInteractor.h"
+
+// GEOM includes
+#include
+#include
+
+// SUIT includes
+#include
+
+// OCCT includes
+#include
+#include
+
+class MeasureGUI_1Sel_Frame;
+class MeasureGUI_2Sel_Frame;
+class MeasureGUI_3Sel_Frame;
+class QAbstractButton;
+class QTabWidget;
+class Bnd_Box;
+class SOCC_Prs;
+
+//=================================================================================
+// class : MeasureGUI_CreateDimensionDlg
+// purpose : Dialog invoked from MeasureGUI_ManageDimensionDlg for
+// creating dimension presentations for the passed onwer object.
+// Does not use operation logics.
+//=================================================================================
+class MeasureGUI_CreateDimensionDlg : public GEOMBase_Skeleton
+{
+ Q_OBJECT
+
+ class BaseSelectorPane;
+ class LengthPane;
+ class DiameterPane;
+ class AnglePane;
+
+public:
+ // Enumerate dimension type radio buttons
+ enum TypeButtonID
+ {
+ TypeButtonID_Length = 0,
+ TypeButtonID_Diameter = 1,
+ TypeButtonID_Angle = 2
+ };
+
+public:
+ MeasureGUI_CreateDimensionDlg( const GEOM::GeomObjPtr&, GeometryGUI*, QWidget* );
+ ~MeasureGUI_CreateDimensionDlg();
+
+public:
+ Handle(AIS_Dimension) GetCreatedDimension() { return myDimension; }
+
+public:
+ void Init();
+
+/* User event logics */
+protected slots:
+ void ConstructTypeChanged( int theType );
+ void OnArgumentTabChanged();
+ void OnStartSelection( const QList& theModes );
+ void OnStopSelection();
+ void SelectionIntoArgument();
+ void OnSelectionDone();
+ void ClickOnOk();
+ bool ClickOnApply();
+
+/* Commands */
+protected:
+ void StartLocalEditing();
+ void StopLocalEditing();
+
+/* Construction of preview and interaction */
+protected:
+ Handle(AIS_Dimension) CreateDimension();
+ GEOM::GeomObjPtr GetTopLevel( const GEOM::GeomObjPtr& theObject );
+ bool AddDimensionToOwner();
+
+private:
+ BaseSelectorPane* ActiveArgs();
+
+private:
+ QString GenerateName( const QString& thePrefix );
+
+private:
+ GEOM::GeomObjPtr myParentObj;
+ LengthPane* myLengthArgs;
+ DiameterPane* myDiameterArgs;
+ AnglePane* myAngleArgs;
+ QList mySelectionModes;
+ MeasureGUI_DimensionInteractor* myDimensionInteractor;
+ Handle(AIS_Dimension) myDimension;
+ SOCC_Viewer* myEditingViewer;
+ int myEditingLayer;
+};
+
+//=================================================================================
+// class : MeasureGUI_CreateDimensionDlg::BaseSelectorPane
+// purpose : Base selector pane handles events of switching the selector controls
+// and changing argument tabs
+//=================================================================================
+class MeasureGUI_CreateDimensionDlg::BaseSelectorPane : public QWidget
+{
+ Q_OBJECT
+
+public:
+ typedef QList SelectionModes;
+
+public:
+ BaseSelectorPane( QWidget* theParent );
+
+signals:
+ void StartSelection( const QList& theModes );
+ void StopSelection();
+ void SelectionDone();
+ void TabChanged();
+
+public:
+ void Reset( bool theOpenDefaultTab = false );
+ int ActiveTab() const;
+ void SelectionIntoArguments( const GEOM::GeomObjPtr& theSelected );
+ GEOM::GeomObjPtr GetSelection( QLineEdit* theSelector ) const;
+
+public slots:
+ void OnSelectorClicked();
+ void OnTabChanged();
+
+protected:
+ void SetTabWidget( QTabWidget* theTabs );
+
+ /* Register geometry selector controls at base level to provide
+ automatic handling of button clicks, selector switching and
+ sending start selection events to dialog.
+ - theSelectorEdit : line edit control with selected geometry name.
+ - theSelectorButton: selector activation button.
+ - theSelectorModes : shape selection modes allowed for the selection.
+ - theTab : the tab index on which the controls are located. */
+ void RegisterSelector( QLineEdit* theSelectorEdit,
+ QPushButton* theSelectorButton,
+ const SelectionModes& theSelectorModes,
+ const int theTab = 0 );
+
+protected:
+ QTabWidget* myTabs;
+ QMap< int, QList > mySelectors;
+ QMap mySelectionButtons;
+ QMap mySelectionModes;
+ QMap mySelectedShapes;
+ QPixmap mySelectorIcon;
+ QLineEdit* myCurrentSelector;
+};
+
+//=================================================================================
+// class : MeasureGUI_CreateDimensionDlg::LengthPane
+// purpose : Layout for length arguments pane
+//=================================================================================
+class MeasureGUI_CreateDimensionDlg::LengthPane : public BaseSelectorPane
+{
+ Q_OBJECT
+
+public:
+ enum TabID
+ {
+ TabID_SingleEdge,
+ TabID_TwoPoints,
+ TabID_ParallelEdges
+ };
+
+public:
+ LengthPane( QWidget* theParent );
+ GEOM::GeomObjPtr GetSingleEdge() const { return GetSelection( mySingleEdgeSelectors->LineEdit1 ); }
+ GEOM::GeomObjPtr GetPoint1() const { return GetSelection( myTwoPointsSelectors->LineEdit1 ); }
+ GEOM::GeomObjPtr GetPoint2() const { return GetSelection( myTwoPointsSelectors->LineEdit2 ); }
+ GEOM::GeomObjPtr GetEdge1() const { return GetSelection( myParallelEdgesSelectors->LineEdit1 ); }
+ GEOM::GeomObjPtr GetEdge2() const { return GetSelection( myParallelEdgesSelectors->LineEdit2 ); }
+
+private:
+ QTabWidget* myTabs;
+ MeasureGUI_1Sel_Frame* mySingleEdgeSelectors;
+ MeasureGUI_2Sel_Frame* myTwoPointsSelectors;
+ MeasureGUI_2Sel_Frame* myParallelEdgesSelectors;
+};
+
+//=================================================================================
+// class : MeasureGUI_CreateDimensionDlg::DiameterPane
+// purpose : Layout for diameter arguments pane
+//=================================================================================
+class MeasureGUI_CreateDimensionDlg::DiameterPane : public BaseSelectorPane
+{
+ Q_OBJECT
+
+public:
+ DiameterPane( QWidget* theParent );
+ GEOM::GeomObjPtr GetShape() const { return GetSelection( myShapeSelector->LineEdit1 ); }
+
+private:
+ MeasureGUI_1Sel_Frame* myShapeSelector;
+};
+
+//=================================================================================
+// class : MeasureGUI_CreateDimensionDlg::AnglePane
+// purpose : Layout for angle arguments pane
+//=================================================================================
+class MeasureGUI_CreateDimensionDlg::AnglePane : public BaseSelectorPane
+{
+ Q_OBJECT
+
+public:
+ enum TabID
+ {
+ TabID_TwoEdges,
+ TabID_ThreePoints
+ };
+
+public:
+ AnglePane( QWidget* theParent );
+ GEOM::GeomObjPtr GetEdge1() const { return GetSelection( myTwoEdgesSelectors->LineEdit1 ); }
+ GEOM::GeomObjPtr GetEdge2() const { return GetSelection( myTwoEdgesSelectors->LineEdit2 ); }
+ GEOM::GeomObjPtr GetPoint1() const { return GetSelection( myThreePointsSelectors->LineEdit1 ); }
+ GEOM::GeomObjPtr GetPoint2() const { return GetSelection( myThreePointsSelectors->LineEdit2 ); }
+ GEOM::GeomObjPtr GetPoint3() const { return GetSelection( myThreePointsSelectors->LineEdit3 ); }
+
+private:
+ QTabWidget* myTabs;
+ MeasureGUI_2Sel_Frame* myTwoEdgesSelectors;
+ MeasureGUI_3Sel_Frame* myThreePointsSelectors;
+};
+
+#endif
diff --git a/src/MeasureGUI/MeasureGUI_DimensionCreateTool.cxx b/src/MeasureGUI/MeasureGUI_DimensionCreateTool.cxx
new file mode 100644
index 000000000..c32d0c9ca
--- /dev/null
+++ b/src/MeasureGUI/MeasureGUI_DimensionCreateTool.cxx
@@ -0,0 +1,650 @@
+// Copyright (C) 2007-2013 CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+// GEOM GEOMGUI : GUI for Geometry component
+// File : MeasureGUI_DimensionCreateTool.cxx
+// Author : Anton POLETAEV, Open CASCADE S.A.S.
+
+#include "MeasureGUI_DimensionCreateTool.h"
+
+// GEOM includes
+#include
+
+// GUI includes
+#include
+
+// SUIT includes
+#include
+#include
+#include
+#include
+
+// OCCT includes
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+//=================================================================================
+// function : Constructor
+// purpose :
+//=================================================================================
+MeasureGUI_DimensionCreateTool::MeasureGUI_DimensionCreateTool( GeometryGUI* theGeomGUI )
+: myGeomGUI( theGeomGUI )
+{
+}
+
+//=================================================================================
+// function : LengthOnEdge
+// purpose :
+//=================================================================================
+Handle(AIS_LengthDimension) MeasureGUI_DimensionCreateTool::LengthOnEdge( const GEOM::GeomObjPtr& theEdge )
+{
+ /* ---------------------------------------------------------------- *
+ * get the edge and parent shape *
+ * ---------------------------------------------------------------- */
+
+ TopoDS_Shape aShapeEdge;
+ TopoDS_Shape aShapeMain;
+ if ( !GEOMBase::GetShape( theEdge.get(), aShapeEdge ) )
+ {
+ return NULL;
+ }
+ if ( !GEOMBase::GetShape( GetMainShape( theEdge ).get(), aShapeMain ) )
+ {
+ return NULL;
+ }
+
+ /* ------------------------------------------------- */
+ /* check the input geometry */
+ /* ------------------------------------------------- */
+
+ TopoDS_Edge anEdge = TopoDS::Edge( aShapeEdge );
+
+ TopoDS_Vertex aVertex1;
+ TopoDS_Vertex aVertex2;
+ TopExp::Vertices( anEdge, aVertex1, aVertex2 );
+
+ gp_Pnt aPnt1 = BRep_Tool::Pnt( aVertex1 );
+ gp_Pnt aPnt2 = BRep_Tool::Pnt( aVertex2 );
+ if ( aPnt1.Distance( aPnt2 ) <= Precision::Confusion() )
+ {
+ return NULL;
+ }
+
+ /* ------------------------------------------------- *
+ * compose list of possible flyout directions *
+ * ------------------------------------------------- */
+
+ Bnd_Box aBnd;
+ BRepBndLib::AddClose( aShapeMain, aBnd );
+
+ TColgp_SequenceOfDir aSeqOfFlyout;
+ ChooseLengthFlyoutsFromShape( aSeqOfFlyout, anEdge, aShapeMain );
+ ChooseLengthFlyoutsFromBnd( aSeqOfFlyout, aPnt1, aPnt2, aBnd );
+ if ( aSeqOfFlyout.IsEmpty() )
+ {
+ return NULL;
+ }
+
+ 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 )
+ {
+ OCCViewer_ViewManager* aViewMgr = (OCCViewer_ViewManager*) anApp->getViewManager( OCCViewer_Viewer::Type(), false );
+ if ( aViewMgr )
+ {
+ anActiveView = (OCCViewer_ViewWindow*) aViewMgr->getActiveView();
+ }
+ }
+ }
+
+ gp_Pln aChoosenPlane = anActiveView
+ ? SelectPlaneForProjection( aSeqOfPlanes, anActiveView->getViewPort()->getView() )
+ : aSeqOfPlanes.First();
+
+ /* ------------------------------------------------------------------------------------ *
+ * construct interactive presentation *
+ * ------------------------------------------------------------------------------------ */
+
+ Handle(AIS_LengthDimension) aDimension = new AIS_LengthDimension( anEdge, aChoosenPlane );
+ if ( !aDimension->IsValid() )
+ {
+ return NULL;
+ }
+
+ return aDimension;
+}
+
+//=================================================================================
+// function : LengthByPoints
+// purpose :
+//=================================================================================
+Handle(AIS_LengthDimension) MeasureGUI_DimensionCreateTool::LengthByPoints( const GEOM::GeomObjPtr& thePoint1,
+ const GEOM::GeomObjPtr& thePoint2 )
+{
+ TopoDS_Shape aFirstSh;
+ if ( !GEOMBase::GetShape( thePoint1.operator ->(), aFirstSh ) )
+ {
+ return NULL;
+ }
+
+ TopoDS_Shape aSecondSh;
+ if ( !GEOMBase::GetShape( thePoint2.operator ->(), aSecondSh ) )
+ {
+ 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 ( aDir.Dot( aUnitVecs[aUnitVecIt] ) <= 0.5 )
+ {
+ break;
+ }
+ }
+
+ gp_Pnt aPnt3 = aPnt2.Translated( aUnitVecs[aUnitVecIt] );
+
+ GC_MakePlane aMkPlane( aPnt1, aPnt2, aPnt3 );
+ Handle(Geom_Plane) aPlane = aMkPlane.Value();
+
+ // check whether it is possible to compute valid dimension
+ Handle(AIS_LengthDimension) aDimension = new AIS_LengthDimension ( aFirstVertex, aSecondVertex, aPlane->Pln() );
+
+ if ( !aDimension->IsValid() )
+ {
+ return NULL;
+ }
+
+ return aDimension;
+}
+
+//=================================================================================
+// function : LengthByParallelEdges
+// purpose :
+//=================================================================================
+Handle(AIS_LengthDimension) MeasureGUI_DimensionCreateTool::LengthByParallelEdges( const GEOM::GeomObjPtr& theEdge1,
+ const GEOM::GeomObjPtr& theEdge2 )
+{
+ TopoDS_Shape aFirstSh;
+ if ( !GEOMBase::GetShape( theEdge1.operator ->(), aFirstSh ) )
+ {
+ return NULL;
+ }
+
+ TopoDS_Shape aSecondSh;
+ if ( !GEOMBase::GetShape( theEdge2.operator ->(), aSecondSh ) )
+ {
+ return NULL;
+ }
+
+ TopoDS_Edge aFirstEdge = TopoDS::Edge( aFirstSh );
+ TopoDS_Edge aSecondEdge = TopoDS::Edge( aSecondSh );
+
+ // Build plane through three points
+ BRepAdaptor_Curve aCurve1( aFirstEdge );
+ BRepAdaptor_Curve aCurve2( aSecondEdge );
+
+ gp_Pnt aPnt1 = aCurve1.Value( 0.1 );
+ gp_Pnt aPnt2 = aCurve1.Value( 0.9 );
+ gp_Pnt aPnt3 = aCurve2.Value( 0.5 );
+
+ GC_MakePlane aMkPlane( aPnt1, aPnt2, aPnt3 );
+ Handle(Geom_Plane) aPlane = aMkPlane.Value();
+
+ // check whether it is possible to compute valid dimension
+ Handle(AIS_LengthDimension) aDimension = new AIS_LengthDimension ( aFirstEdge, aSecondEdge, aPlane->Pln() );
+
+ if ( !aDimension->IsValid() )
+ {
+ return NULL;
+ }
+
+ return aDimension;
+}
+
+//=================================================================================
+// function : Diameter
+// purpose :
+//=================================================================================
+Handle(AIS_DiameterDimension) MeasureGUI_DimensionCreateTool::Diameter( const GEOM::GeomObjPtr& theShape )
+{
+ TopoDS_Shape aShape;
+ if ( !GEOMBase::GetShape( theShape.operator ->(), aShape ) )
+ {
+ return NULL;
+ }
+
+ if ( aShape.ShapeType() != TopAbs_EDGE &&
+ aShape.ShapeType() != TopAbs_FACE &&
+ aShape.ShapeType() != TopAbs_WIRE )
+ {
+ return NULL;
+ }
+
+ // check whether it is possible to compute dimension on the passed geometry
+ Handle(AIS_DiameterDimension) aDimension = new AIS_DiameterDimension( aShape );
+
+ if ( !aDimension->IsValid() )
+ {
+ return NULL;
+ }
+
+ return aDimension;
+}
+
+//=================================================================================
+// function : AngleByTwoEdges
+// purpose :
+//=================================================================================
+Handle(AIS_AngleDimension) MeasureGUI_DimensionCreateTool::AngleByTwoEdges( const GEOM::GeomObjPtr& theEdge1,
+ const GEOM::GeomObjPtr& theEdge2 )
+{
+ /* --------------------------------------------------- */
+ /* get construction and parent shapes */
+ /* --------------------------------------------------- */
+
+ TopoDS_Shape aShapeEdge1;
+ TopoDS_Shape aShapeMain1;
+ if ( !GEOMBase::GetShape( theEdge1.get(), aShapeEdge1 ) )
+ {
+ return NULL;
+ }
+ if ( !GEOMBase::GetShape( GetMainShape( theEdge1 ).get(), aShapeMain1 ) )
+ {
+ return NULL;
+ }
+
+ TopoDS_Shape aShapeEdge2;
+ TopoDS_Shape aShapeMain2;
+ if ( !GEOMBase::GetShape( theEdge2.get(), aShapeEdge2 ) )
+ {
+ return NULL;
+ }
+ if ( !GEOMBase::GetShape( GetMainShape( theEdge2 ).get(), aShapeMain2 ) )
+ {
+ return NULL;
+ }
+
+ /* ---------------------------------------------------- */
+ /* check construction edges */
+ /* ---------------------------------------------------- */
+
+ TopoDS_Edge aFirstEdge = TopoDS::Edge( aShapeEdge1 );
+ TopoDS_Edge aSecondEdge = TopoDS::Edge( aShapeEdge2 );
+
+ // check whether it is possible to compute dimension on the passed edges
+ Handle(AIS_AngleDimension) aDimension = new AIS_AngleDimension( aFirstEdge, aSecondEdge );
+
+ if ( !aDimension->IsValid() )
+ {
+ return NULL;
+ }
+
+ const gp_Pnt& aFirstPoint = aDimension->FirstPoint();
+ const gp_Pnt& aSecondPoint = aDimension->SecondPoint();
+ const gp_Pnt& aCenterPoint = aDimension->CenterPoint();
+
+ gp_Vec aVec1( aCenterPoint, aFirstPoint );
+ gp_Vec aVec2( aCenterPoint, aSecondPoint );
+
+ Standard_Real anAngle = aVec2.AngleWithRef( aVec1, aDimension->GetPlane().Axis().Direction() );
+
+ if ( anAngle < 0.0 )
+ {
+ aDimension = new AIS_AngleDimension( aSecondPoint, aCenterPoint, aFirstPoint );
+ }
+
+ return aDimension;
+}
+
+//=================================================================================
+// function : AngleByThreePoints
+// purpose :
+//=================================================================================
+Handle(AIS_AngleDimension) MeasureGUI_DimensionCreateTool::AngleByThreePoints( const GEOM::GeomObjPtr& thePoint1,
+ const GEOM::GeomObjPtr& thePoint2,
+ const GEOM::GeomObjPtr& thePoint3 )
+{
+ TopoDS_Shape aFirstSh;
+ if ( !GEOMBase::GetShape( thePoint1.operator ->(), aFirstSh ) )
+ {
+ return NULL;
+ }
+
+ TopoDS_Shape aSecondSh;
+ if ( !GEOMBase::GetShape( thePoint2.operator ->(), aSecondSh ) )
+ {
+ return NULL;
+ }
+
+ TopoDS_Shape aThirdSh;
+ if ( !GEOMBase::GetShape( thePoint3.operator ->(), aThirdSh ) )
+ {
+ return NULL;
+ }
+
+ TopoDS_Vertex aFirstVertex = TopoDS::Vertex( aFirstSh );
+ TopoDS_Vertex aSecondVertex = TopoDS::Vertex( aSecondSh );
+ TopoDS_Vertex aThirdVertex = TopoDS::Vertex( aThirdSh );
+
+ gp_Pnt aPnt1 = BRep_Tool::Pnt( aFirstVertex );
+ gp_Pnt aPnt2 = BRep_Tool::Pnt( aSecondVertex );
+ gp_Pnt aPnt3 = BRep_Tool::Pnt( aThirdVertex );
+
+ // check whether it is possible to compute dimension on the passed points
+ Handle(AIS_AngleDimension) aDimension = new AIS_AngleDimension( aPnt1, aPnt2, aPnt3 );
+
+ if ( !aDimension->IsValid() )
+ {
+ return NULL;
+ }
+
+ return aDimension;
+}
+
+//=================================================================================
+// function : ChooseLengthFlyoutsFromShape
+// purpose :
+//=================================================================================
+void MeasureGUI_DimensionCreateTool::ChooseLengthFlyoutsFromShape( TColgp_SequenceOfDir& theDirs,
+ const TopoDS_Vertex& theVertex1,
+ const TopoDS_Vertex& theVertex2,
+ const TopoDS_Shape& theShape )
+{
+}
+
+//=================================================================================
+// 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 );
+ }
+
+ // get average direction in case of two non-sharp angled faces
+ if ( theDirs.Length() == 2 )
+ {
+ const gp_Dir& aDir1 = theDirs.First();
+ const gp_Dir& aDir2 = theDirs.Last();
+ Standard_Boolean isSame = aDir1.IsParallel( aDir2, Precision::Angular() );
+ if ( !isSame )
+ {
+ gp_Dir aReferenceDir = aDir1 ^ aDir2;
+ // compute angle between face sides [0 - 2PI]
+ Standard_Real aDirAngle = aDir1.AngleWithRef( aDir2, aReferenceDir );
+ if ( aDirAngle < 0 )
+ {
+ aDirAngle = ( M_PI * 2.0 ) - aDirAngle;
+ }
+
+ // non-sharp angle, use averaged direction
+ if ( aDirAngle > M_PI )
+ {
+ theDirs.Clear();
+ theDirs.Append( aDir1.Rotated( gp_Ax1( gp::Origin(), aReferenceDir ), aDirAngle * 0.5 ) );
+ }
+ }
+ }
+}
+
+//=================================================================================
+// function : ChooseLengthFlyoutsFromBnd
+// purpose :
+//=================================================================================
+void MeasureGUI_DimensionCreateTool::ChooseLengthFlyoutsFromBnd( TColgp_SequenceOfDir& theDirs,
+ const gp_Pnt& thePnt1,
+ const gp_Pnt& thePnt2,
+ const Bnd_Box& theBnd )
+{
+ // compose a list of axis-aligned planes for lying-in flyouts
+ NCollection_Sequence anAAPlanes;
+
+ // the axis-aligned planes for flyouts are built from
+ // three points (P1, P2, and P1 translated in orthogonal
+ // direction dx, dy, dz)
+ gp_Dir anAxes[3] = { gp::DX(), gp::DY(), gp::DZ() };
+
+ for ( int anIt = 0; anIt < 3; ++anIt )
+ {
+ const gp_Dir& anAxisDir = anAxes[anIt];
+ gp_Pnt aPnt3 = thePnt1.Translated( gp_Vec( anAxisDir ) );
+ gce_MakePln aMakePlane( thePnt1, thePnt2, aPnt3 );
+ if ( !aMakePlane.IsDone() )
+ {
+ continue;
+ }
+
+ anAAPlanes.Append( aMakePlane.Value() );
+ }
+
+ // find out what is the closest direction outside of the bounding box
+ NCollection_Sequence::Iterator aPlaneIt( anAAPlanes );
+
+ gp_Dir aPointDir = gce_MakeDir( thePnt1, thePnt2 );
+
+ for ( ; aPlaneIt.More(); aPlaneIt.Next() )
+ {
+ const gp_Pln& aPlane = aPlaneIt.Value();
+
+ // transform bounding box to orthogonal coordiantes relative to
+ // dimension points P1, P2 (x-axis) and plane direction (z-axis),
+ // where y coordinates will correspond to flyout direction against
+ // the dimension point line
+ gp_Ax3 aFlyoutSpace( thePnt1, aPlane.Axis().Direction(), aPointDir );
+
+ 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 );
+
+ gp_Dir aPosFlyout = aPlane.Axis().Direction() ^ aPointDir;
+ gp_Dir aNegFlyout = aPosFlyout.Reversed();
+
+ // select positive or negative flyout
+ theDirs.Append( Abs( aYmax ) < Abs( aYmin ) ? aPosFlyout : aNegFlyout );
+ }
+}
+
+//=================================================================================
+// 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 )
+{
+ Quantity_Parameter U[3];
+ Quantity_Parameter N[3];
+ theView->Up( U[0], U[1], U[2] );
+ theView->Proj( N[0], N[1], N[2] );
+
+ 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();
+
+ Standard_Real aBestDotProduct = RealFirst();
+
+ for ( Standard_Integer aPlnIt = 1; aPlnIt <= thePlanes.Length(); ++aPlnIt )
+ {
+ const gp_Pln& aPlane = thePlanes.Value( aPlnIt );
+
+ Standard_Real aDotProduct = Abs( aPlane.Axis().Direction() * aViewN );
+
+ // preferred plane is "view parallel"
+ if ( aDotProduct <= aBestDotProduct )
+ {
+ continue;
+ }
+
+ aBestPlane = aPlane;
+
+ aBestDotProduct = aDotProduct;
+ }
+
+ return aBestPlane;
+}
+
+//=================================================================================
+// function : GetMainShape
+// purpose :
+//=================================================================================
+GEOM::GeomObjPtr MeasureGUI_DimensionCreateTool::GetMainShape( const GEOM::GeomObjPtr& theShape )
+{
+ // iterate over top-level objects to search for main shape
+ GEOM::GeomObjPtr aMainShapeIt = theShape;
+ while ( !aMainShapeIt->IsMainShape() )
+ {
+ aMainShapeIt = aMainShapeIt->GetMainShape();
+ }
+ return aMainShapeIt;
+}
+
+//=================================================================================
+// function : GetFaceSide
+// purpose :
+//=================================================================================
+bool MeasureGUI_DimensionCreateTool::GetFaceSide( const TopoDS_Face& theFace, const TopoDS_Edge& theEdge, gp_Dir& theDir )
+{
+ // get correctly oriented edge from main shape
+ TopoDS_Edge anEdgeFromFace;
+ TopExp_Explorer anExplorer( theFace.Oriented( TopAbs_FORWARD ), TopAbs_EDGE );
+ for ( ; anExplorer.More(); anExplorer.Next() )
+ {
+ TopoDS_Edge aCurrentEdge = TopoDS::Edge( anExplorer.Current() );
+ if ( theEdge.IsSame( aCurrentEdge ) )
+ {
+ anEdgeFromFace = aCurrentEdge;
+ break;
+ }
+ }
+
+ if ( anEdgeFromFace.IsNull() )
+ {
+ return false;
+ }
+
+ // check out the direction of face extensions from its boundaries at the edge location
+ // made assumption here that for any linear bounding edge the
+ // normals are same on the whole length of that edge
+ Handle(Geom_Surface) aSurface = BRep_Tool::Surface( theFace );
+ if ( aSurface.IsNull() || !aSurface->IsKind( STANDARD_TYPE(Geom_ElementarySurface) ) )
+ {
+ return false;
+ }
+
+ BRepAdaptor_Curve aSurfCurve( anEdgeFromFace, theFace );
+ if ( !aSurfCurve.IsCurveOnSurface() )
+ {
+ return false;
+ }
+
+ Standard_Real aHalfRange = ( aSurfCurve.FirstParameter() + aSurfCurve.LastParameter() ) / 2.0;
+
+ gp_Pnt aPoint = aSurfCurve.Value( aHalfRange );
+
+ Standard_Real aPointU = 0.0;
+ Standard_Real aPointV = 0.0;
+ GeomLib_Tool::Parameters( aSurface, aPoint, Precision::Confusion(), aPointU, aPointV );
+
+ gp_Dir aNorm;
+ if ( GeomLib::NormEstim( aSurface, gp_Pnt2d( aPointU, aPointV ), Precision::Confusion(), aNorm ) > 1 )
+ {
+ return false;
+ }
+
+ gp_Vec aTangent = aSurfCurve.DN( aHalfRange, 1 );
+ if ( aTangent.Magnitude() < Precision::Confusion() )
+ {
+ return false;
+ }
+
+ TopAbs_Orientation anEdgeOrientation = anEdgeFromFace.Orientation();
+ if ( anEdgeOrientation == TopAbs_REVERSED )
+ {
+ aTangent.Reverse();
+ }
+
+ theDir = gp_Dir( aTangent ) ^ aNorm;
+ return true;
+}
diff --git a/src/MeasureGUI/MeasureGUI_DimensionCreateTool.h b/src/MeasureGUI/MeasureGUI_DimensionCreateTool.h
new file mode 100644
index 000000000..978aaa915
--- /dev/null
+++ b/src/MeasureGUI/MeasureGUI_DimensionCreateTool.h
@@ -0,0 +1,106 @@
+// Copyright (C) 2007-2013 CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+// GEOM GEOMGUI : GUI for Geometry component
+// File : MeasureGUI_DimensionCreateTool.h
+// Author : Anton POLETAEV, Open CASCADE S.A.S.
+//
+#ifndef MEASUREGUI_DIMENSIONCREATETOOL_H
+#define MEASUREGUI_DIMENSIONCREATETOOL_H
+
+// GEOM includes
+#include
+#include
+
+// OCCT includes
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+//=================================================================================
+// class : MeasureGUI_DimensionCreateTool
+// purpose :
+//=================================================================================
+class MeasureGUI_DimensionCreateTool
+{
+public:
+ MeasureGUI_DimensionCreateTool( GeometryGUI* );
+
+/* construction methods */
+public:
+ Handle(AIS_LengthDimension) LengthOnEdge( const GEOM::GeomObjPtr& );
+
+ Handle(AIS_LengthDimension) LengthByPoints( const GEOM::GeomObjPtr&,
+ const GEOM::GeomObjPtr& );
+
+ Handle(AIS_LengthDimension) LengthByParallelEdges( const GEOM::GeomObjPtr&,
+ const GEOM::GeomObjPtr& );
+
+ Handle(AIS_DiameterDimension) Diameter( const GEOM::GeomObjPtr& );
+
+ Handle(AIS_AngleDimension) AngleByTwoEdges( const GEOM::GeomObjPtr&,
+ const GEOM::GeomObjPtr& );
+
+ Handle(AIS_AngleDimension) AngleByThreePoints( const GEOM::GeomObjPtr&,
+ const GEOM::GeomObjPtr&,
+ const GEOM::GeomObjPtr& );
+
+/* selecting flyout direction for length dimensions */
+protected:
+
+ void ChooseLengthFlyoutsFromShape( TColgp_SequenceOfDir&,
+ const TopoDS_Vertex&,
+ const TopoDS_Vertex&,
+ const TopoDS_Shape& );
+
+ void ChooseLengthFlyoutsFromShape( TColgp_SequenceOfDir&,
+ const TopoDS_Edge&,
+ const TopoDS_Shape& );
+
+ void ChooseLengthFlyoutsFromBnd( TColgp_SequenceOfDir&,
+ const gp_Pnt&,
+ const gp_Pnt&,
+ const Bnd_Box& );
+
+/* selecting best flyout direction taking into account view projection */
+protected:
+
+ gp_Pln SelectPlaneForProjection( const NCollection_Sequence&,
+ const Handle(V3d_View)& );
+
+/* utility */
+protected:
+ GEOM::GeomObjPtr GetMainShape( const GEOM::GeomObjPtr& );
+ bool GetFaceSide( const TopoDS_Face&,
+ const TopoDS_Edge&,
+ gp_Dir& );
+
+private:
+ GeometryGUI* myGeomGUI;
+};
+
+#endif
diff --git a/src/MeasureGUI/MeasureGUI_DimensionFilter.cxx b/src/MeasureGUI/MeasureGUI_DimensionFilter.cxx
new file mode 100644
index 000000000..b5abe2886
--- /dev/null
+++ b/src/MeasureGUI/MeasureGUI_DimensionFilter.cxx
@@ -0,0 +1,192 @@
+// Copyright (C) 2007-2013 CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+// GEOM GEOMGUI : GUI for Geometry component
+// File : MeasureGUI_DimensionFilter.cxx
+// Author : Anton POLETAEV, Open CASCADE S.A.S.
+
+#include "MeasureGUI_DimensionFilter.h"
+
+// GEOM includes
+#include
+
+// SALOME includes
+#include
+
+IMPLEMENT_STANDARD_HANDLE (MeasureGUI_DimensionFilter, SelectMgr_Filter)
+IMPLEMENT_STANDARD_RTTIEXT(MeasureGUI_DimensionFilter, SelectMgr_Filter)
+
+//=======================================================================
+// function : Constructor
+// purpose :
+//=======================================================================
+MeasureGUI_DimensionFilter::MeasureGUI_DimensionFilter( const Handle(AIS_InteractiveObject)& theIO )
+: SelectMgr_Filter(),
+ myFilterIO( theIO ),
+ myFilterEntry(),
+ myFilterId( 0 ),
+ myIsFilterIO( Standard_True ),
+ myIsFilterEntry( Standard_False ),
+ myIsFilterId( Standard_False )
+{
+}
+
+//=======================================================================
+// function : Constructor
+// purpose :
+//=======================================================================
+MeasureGUI_DimensionFilter::MeasureGUI_DimensionFilter( const int theId )
+: SelectMgr_Filter(),
+ myFilterIO(),
+ myFilterEntry(),
+ myFilterId( theId ),
+ myIsFilterIO( Standard_False ),
+ myIsFilterEntry( Standard_False ),
+ myIsFilterId( Standard_True )
+{
+}
+
+//=======================================================================
+// function : Constructor
+// purpose :
+//=======================================================================
+MeasureGUI_DimensionFilter::MeasureGUI_DimensionFilter( const std::string& theEntry )
+: SelectMgr_Filter(),
+ myFilterIO( NULL ),
+ myFilterEntry( theEntry ),
+ myFilterId( 0 ),
+ myIsFilterIO( Standard_False ),
+ myIsFilterEntry( Standard_True ),
+ myIsFilterId( Standard_False )
+{
+}
+
+//=======================================================================
+// function : Constructor
+// purpose :
+//=======================================================================
+MeasureGUI_DimensionFilter::MeasureGUI_DimensionFilter( const std::string& theEntry, const int theId )
+: SelectMgr_Filter(),
+ myFilterIO( NULL ),
+ myFilterEntry( theEntry ),
+ myFilterId( theId ),
+ myIsFilterIO( Standard_False ),
+ myIsFilterEntry( Standard_True ),
+ myIsFilterId( Standard_True )
+{
+}
+
+//=======================================================================
+// function : SetFilterIO
+// purpose :
+//=======================================================================
+void MeasureGUI_DimensionFilter::SetFilterIO( const Handle(AIS_InteractiveObject)& theIO )
+{
+ myFilterIO = theIO;
+ myIsFilterIO = Standard_True;
+}
+
+//=======================================================================
+// function : SetFilterEntry
+// purpose :
+//=======================================================================
+void MeasureGUI_DimensionFilter::SetFilterEntry( const std::string& theEntry )
+{
+ myFilterEntry = theEntry;
+ myIsFilterEntry = Standard_True;
+}
+
+//=======================================================================
+// function : SetFilterId
+// purpose :
+//=======================================================================
+void MeasureGUI_DimensionFilter::SetFilterId( const int theId )
+{
+ myFilterId = theId;
+ myIsFilterId = Standard_True;
+}
+
+//=======================================================================
+// function : IsOk
+// purpose :
+//=======================================================================
+Standard_Boolean MeasureGUI_DimensionFilter::IsOk( const Handle(SelectMgr_EntityOwner)& theEntity ) const
+{
+ Handle(AIS_InteractiveObject) anAIS = Handle(AIS_InteractiveObject)::DownCast( theEntity->Selectable() );
+
+ if ( anAIS.IsNull() || !anAIS->HasOwner() )
+ {
+ return Standard_False;
+ }
+
+ if ( !anAIS->IsKind( STANDARD_TYPE( AIS_LengthDimension ) )
+ && !anAIS->IsKind( STANDARD_TYPE( AIS_DiameterDimension ) )
+ && !anAIS->IsKind( STANDARD_TYPE( AIS_AngleDimension ) ) )
+ {
+ return Standard_False;
+ }
+
+ if ( myIsFilterIO )
+ {
+ if ( anAIS != myFilterIO )
+ {
+ return Standard_False;
+ }
+ }
+
+ if ( myIsFilterEntry )
+ {
+ Handle(SALOME_InteractiveObject) anIO = Handle(SALOME_InteractiveObject)::DownCast( anAIS->GetOwner() );
+ if ( anIO.IsNull() )
+ {
+ return Standard_False;
+ }
+
+ if ( std::string( anIO->getEntry() ) != myFilterEntry )
+ {
+ return Standard_False;
+ }
+ }
+
+ if ( myIsFilterId )
+ {
+ Handle(GEOM_AISLength) aLength = Handle(GEOM_AISLength)::DownCast( anAIS );
+ if ( !aLength.IsNull() && aLength->GetId() != myFilterId )
+ {
+ return Standard_False;
+ }
+
+ Handle(GEOM_AISDiameter) aDiameter = Handle(GEOM_AISDiameter)::DownCast( anAIS );
+ if ( !aDiameter.IsNull() && aDiameter->GetId() != myFilterId )
+ {
+ return Standard_False;
+ }
+
+ Handle(GEOM_AISAngle) anAngle = Handle(GEOM_AISAngle)::DownCast( anAIS );
+ if ( !anAngle.IsNull() && anAngle->GetId() != myFilterId )
+ {
+ return Standard_False;
+ }
+ }
+
+ return Standard_True;
+}
diff --git a/src/MeasureGUI/MeasureGUI_DimensionFilter.h b/src/MeasureGUI/MeasureGUI_DimensionFilter.h
new file mode 100644
index 000000000..89071a8b2
--- /dev/null
+++ b/src/MeasureGUI/MeasureGUI_DimensionFilter.h
@@ -0,0 +1,80 @@
+// Copyright (C) 2007-2013 CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+// GEOM GEOMGUI : GUI for Geometry component
+// File : MeasureGUI_DimensionFilter.h
+// Author : Anton POLETAEV, Open CASCADE S.A.S.
+//
+#ifndef MEASUREGUI_DIMENSIONFILTER_H
+#define MEASUREGUI_DIMENSIONFILTER_H
+
+// GEOM includes
+#include
+
+// OCCT includes
+#include
+#include
+#include
+
+DEFINE_STANDARD_HANDLE(MeasureGUI_DimensionFilter, SelectMgr_Filter)
+
+//=====================================================================================
+// class : MeasureGUI_DimensionFilter
+// purpose : OCC viewer filter for selecting dimensions displayed as part of
+// presentation of particular GEOM object by its entry (owner of dimension).
+//=====================================================================================
+class MeasureGUI_DimensionFilter : public SelectMgr_Filter
+{
+public:
+
+ DEFINE_STANDARD_RTTI(MeasureGUI_DimensionFilter);
+
+public:
+ Standard_EXPORT MeasureGUI_DimensionFilter( const Handle(AIS_InteractiveObject)& theIO );
+ Standard_EXPORT MeasureGUI_DimensionFilter( const int theId );
+ Standard_EXPORT MeasureGUI_DimensionFilter( const std::string& theEntry );
+ Standard_EXPORT MeasureGUI_DimensionFilter( const std::string& theEntry, const int theId );
+
+ Standard_EXPORT void SetFilterIO( const Handle(AIS_InteractiveObject)& theIO );
+ Standard_EXPORT void SetFilterEntry( const std::string& theEntry );
+ Standard_EXPORT void SetFilterId( const int theId );
+
+ Standard_Boolean IsFilterIO() const { return myIsFilterIO; }
+ Standard_Boolean IsFilterEntry() const { return myIsFilterEntry; }
+ Standard_Boolean IsFilterId() const { return myIsFilterId; }
+
+ void UnsetFilterIO() { myIsFilterIO = Standard_False; }
+ void UnsetFilterEntry() { myIsFilterEntry = Standard_False; }
+ void UnsetFilterId() { myIsFilterId = Standard_False; }
+
+ Standard_EXPORT virtual Standard_Boolean IsOk( const Handle(SelectMgr_EntityOwner)& theEntity ) const;
+
+private:
+ Handle(AIS_InteractiveObject) myFilterIO;
+ std::string myFilterEntry;
+ int myFilterId;
+ Standard_Boolean myIsFilterIO;
+ Standard_Boolean myIsFilterEntry;
+ Standard_Boolean myIsFilterId;
+};
+
+#endif
diff --git a/src/MeasureGUI/MeasureGUI_DimensionInteractor.cxx b/src/MeasureGUI/MeasureGUI_DimensionInteractor.cxx
new file mode 100644
index 000000000..48b9dbda4
--- /dev/null
+++ b/src/MeasureGUI/MeasureGUI_DimensionInteractor.cxx
@@ -0,0 +1,869 @@
+// Copyright (C) 2007-2013 CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+// GEOM GEOMGUI : GUI for Geometry component
+// File : MeasureGUI_DimensionInteractor.cxx
+// Author : Anton POLETAEV, Open CASCADE S.A.S.
+
+#include "MeasureGUI_DimensionInteractor.h"
+
+#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
+
+//=================================================================================
+// function : Constructor
+// purpose :
+//=================================================================================
+MeasureGUI_DimensionInteractor::MeasureGUI_DimensionInteractor( GeometryGUI* theGUI,
+ QObject* theParent )
+: QObject( theParent ),
+ myGeomGUI( theGUI ),
+ myIsEnabled( false ),
+ myVM( NULL ),
+ myViewer( NULL ),
+ myOperation( Operation_None )
+{
+}
+
+//=================================================================================
+// function : Deactivate
+// purpose :
+//=================================================================================
+MeasureGUI_DimensionInteractor::~MeasureGUI_DimensionInteractor()
+{
+ Disable();
+}
+
+//=================================================================================
+// function : Enable
+// purpose :
+//=================================================================================
+void MeasureGUI_DimensionInteractor::Enable()
+{
+ if ( myIsEnabled )
+ {
+ return;
+ }
+
+ myIsEnabled = true;
+
+ // install event filtering on viewer windows
+ SalomeApp_Application* anApp = myGeomGUI->getApp();
+ if ( !anApp )
+ {
+ return;
+ }
+
+ myVM = (OCCViewer_ViewManager*) anApp->getViewManager( OCCViewer_Viewer::Type(), false );
+ myViewer = (OCCViewer_Viewer*) myVM->getViewModel();
+ if ( !myVM || !myViewer )
+ {
+ return;
+ }
+
+ connect( myVM, SIGNAL( viewCreated( SUIT_ViewWindow* ) ), SLOT( OnViewCreated( SUIT_ViewWindow* ) ) );
+ connect( myVM, SIGNAL( deleteView ( SUIT_ViewWindow* ) ), SLOT( OnViewRemoved( SUIT_ViewWindow* ) ) );
+
+ QVector aViews = myVM->getViews();
+ QVector::iterator aViewIt = aViews.begin();
+ for ( ; aViewIt != aViews.end(); ++aViewIt )
+ {
+ ConnectView( *aViewIt );
+ }
+}
+
+//=================================================================================
+// function : Disable
+// purpose :
+//=================================================================================
+void MeasureGUI_DimensionInteractor::Disable()
+{
+ if ( !myIsEnabled )
+ {
+ return;
+ }
+
+ myIsEnabled = false;
+
+ // remove event filtering from viewer windows
+ QVector aViews = myVM->getViews();
+ QVector::iterator aViewIt = aViews.begin();
+ for ( ; aViewIt != aViews.end(); ++aViewIt )
+ {
+ DisconnectView( *aViewIt );
+ }
+}
+
+//=================================================================================
+// function : GetOperation
+// purpose :
+//=================================================================================
+MeasureGUI_DimensionInteractor::Operation
+ MeasureGUI_DimensionInteractor::GetOperation( const Handle(SelectMgr_EntityOwner)& theEntity,
+ const Qt::MouseButtons theButtons,
+ const Qt::KeyboardModifiers theKeys )
+{
+ if ( ( theButtons & Qt::LeftButton ) == 0 )
+ {
+ return Operation_None;
+ }
+
+ Handle(AIS_DimensionOwner) anOwner = Handle(AIS_DimensionOwner)::DownCast( theEntity );
+ if ( anOwner.IsNull() )
+ {
+ return Operation_None;
+ }
+
+ Standard_Real anAngTolerance = M_PI / 30.0; // 6 degree tolerance
+
+ switch ( anOwner->SelectionMode() )
+ {
+ case AIS_DSM_Line :
+ {
+ if ( ( theKeys & Qt::ControlModifier ) == 0 )
+ {
+ return Operation_MoveFlyoutInPlane;
+ }
+
+ // "free moving" is only available for length and diameter
+ if ( !myInteractedIO->IsKind( STANDARD_TYPE( AIS_LengthDimension ) )
+ && !myInteractedIO->IsKind( STANDARD_TYPE( AIS_DiameterDimension ) ) )
+ {
+ return Operation_None;
+ }
+
+ return Operation_MoveFlyoutFree;
+ }
+
+ case AIS_DSM_Text : return Operation_MoveText;
+ default : return Operation_None;
+ }
+}
+
+//=================================================================================
+// function : StartOperation
+// purpose :
+//=================================================================================
+bool MeasureGUI_DimensionInteractor::StartOperation( const Operation theOp,
+ const Handle(V3d_View)& theView,
+ const int theX,
+ const int theY )
+{
+ Standard_Real anAngTolerance = M_PI / 30.0; // 6 degree tolerance
+
+ switch ( theOp )
+ {
+ case Operation_MoveFlyoutInPlane :
+ case Operation_MoveText :
+ {
+ // operation can be started if the plane in which the flyout
+ // or text moved is not completely orthogonal to the screen
+ gp_Pln aPlane = myInteractedIO->GetPlane();
+ gp_Lin aProj = Projection( theView, theX, theY );
+ Standard_Real aCrossAng = aProj.Direction().Angle( aPlane.Axis().Direction() );
+ return Abs( M_PI * 0.5 - aCrossAng ) > anAngTolerance;
+ }
+
+ case Operation_MoveFlyoutFree :
+ {
+ // operation can be started only for linear dimensions
+ if ( !myInteractedIO->IsKind( STANDARD_TYPE( AIS_LengthDimension ) )
+ && !myInteractedIO->IsKind( STANDARD_TYPE( AIS_DiameterDimension ) ) )
+ {
+ return false;
+ }
+
+ // determine whether the rotation operation is frontal or side
+ gp_Pnt aFirstPoint;
+ gp_Pnt aSecondPoint;
+
+ // get first and second point from which the flyout line is normally extended
+ Handle(AIS_LengthDimension) aLength = Handle(AIS_LengthDimension)::DownCast( myInteractedIO );
+ if ( !aLength.IsNull() )
+ {
+ aFirstPoint = aLength->FirstPoint();
+ aSecondPoint = aLength->SecondPoint();
+ }
+
+ Handle(AIS_DiameterDimension) aDiameter = Handle(AIS_DiameterDimension)::DownCast( myInteractedIO );
+ if ( !aDiameter.IsNull() )
+ {
+ const gp_Pnt& aCenter = aDiameter->Circle().Location();
+ aFirstPoint = aDiameter->AnchorPoint();
+ aSecondPoint = gp_Pnt( aFirstPoint.XYZ() + gp_Vec( aFirstPoint, aCenter ).XYZ() * 2.0 );
+ }
+
+ gp_Dir aBaseDir = gce_MakeDir( aFirstPoint, aSecondPoint );
+ gp_Pln aPlane = myInteractedIO->GetPlane();
+ gp_Dir aPlaneN = aPlane.Axis().Direction();
+ gp_Lin aProj = Projection( theView, theX, theY );
+
+ const gp_Dir& aProjDir = aProj.Direction();
+
+ // can turn only if looking from side
+ if ( aProjDir.IsParallel( aPlaneN, anAngTolerance ) ||
+ aProjDir.IsNormal( aBaseDir, anAngTolerance ) )
+ {
+ return false;
+ }
+
+ bool isProjected = false;
+ gp_Pnt aPointOnPlane = ProjectPlane( theView, theX, theY, aPlane, isProjected );
+ if ( !isProjected )
+ {
+ return false;
+ }
+
+ gp_Vec aPointVector( aFirstPoint, aPointOnPlane );
+ gp_Pnt aPointOnBase = gp_Pnt( aFirstPoint.XYZ() + aBaseDir.XYZ() * aPointVector.Dot( aBaseDir ) );
+ myFreeMovePlane = gp_Pln( aPointOnBase, aBaseDir );
+
+ return true;
+ }
+
+ default:
+ return false;
+ }
+}
+
+//=================================================================================
+// function : MoveFlyoutFree
+// purpose :
+//=================================================================================
+void MeasureGUI_DimensionInteractor::MoveFlyoutFree( const Handle(V3d_View)& theView,
+ const int theX,
+ const int theY )
+{
+ // project point onto dimension plane
+ bool isProjected = false;
+ gp_Pln aPlane = myFreeMovePlane;
+ gp_Pnt aPointOnPlane = ProjectPlane( theView, theX, theY, aPlane, isProjected );
+ if ( !isProjected )
+ {
+ return;
+ }
+
+ gp_Pnt aFirstPoint;
+ gp_Pnt aSecondPoint;
+
+ // get first and second point from which the flyout line is normally extended
+ Handle(AIS_LengthDimension) aLength = Handle(AIS_LengthDimension)::DownCast( myInteractedIO );
+ if ( !aLength.IsNull() )
+ {
+ aFirstPoint = aLength->FirstPoint();
+ aSecondPoint = aLength->SecondPoint();
+ }
+
+ Handle(AIS_DiameterDimension) aDiameter = Handle(AIS_DiameterDimension)::DownCast( myInteractedIO );
+ if ( !aDiameter.IsNull() )
+ {
+ const gp_Pnt& aCenter = aDiameter->Circle().Location();
+ aFirstPoint = aDiameter->AnchorPoint();
+ aSecondPoint = gp_Pnt( aFirstPoint.XYZ() + gp_Vec( aFirstPoint, aCenter ).XYZ() * 2.0 );
+ }
+
+ gp_Vec aPointVector( aFirstPoint, aPointOnPlane );
+ gp_Dir aBaseDir = gce_MakeDir( aFirstPoint, aSecondPoint );
+ gp_Pnt aPointOnBase = gp_Pnt( aFirstPoint.XYZ() + aBaseDir.XYZ() * aPointVector.Dot( aBaseDir ) );
+
+ // snapping tolerance
+ Quantity_Length aSize[2];
+ theView->Size( aSize[0], aSize[1] );
+ Standard_Real aSnapTolerance = 1e-2 * Max( aSize[0], aSize[1] );
+
+ gp_Dir aFlyoutDir = gce_MakeDir( aPointOnBase, aPointOnPlane );
+
+ // snapping to planes
+ NCollection_Sequence aSnapPlanes;
+
+ if ( aPointOnPlane.Distance( aPointOnBase ) > aSnapTolerance )
+ {
+ if ( !aBaseDir.IsParallel( gp::DZ(), Precision::Angular() ) )
+ {
+ aSnapPlanes.Append( gp_Pln( aFirstPoint, gp::DZ().Crossed( aBaseDir ) ) );
+ }
+ if ( !aBaseDir.IsParallel( gp::DX(), Precision::Angular() ) )
+ {
+ aSnapPlanes.Append( gp_Pln( aFirstPoint, gp::DX().Crossed( aBaseDir ) ) );
+ }
+ if ( !aBaseDir.IsParallel( gp::DY(), Precision::Angular() ) )
+ {
+ aSnapPlanes.Append( gp_Pln( aFirstPoint, gp::DY().Crossed( aBaseDir ) ) );
+ }
+ }
+
+ // snap "drag proj" to Flyout plane, relative XOY, YOZ, ZOX planes
+ NCollection_Sequence::Iterator aSnapIt( aSnapPlanes );
+
+ for ( ; aSnapIt.More(); aSnapIt.Next() )
+ {
+ const gp_Pln& aSnapPln = aSnapIt.Value();
+
+ // project direction into plane
+ gp_Vec aPlaneDir = gp_Vec( aSnapPln.Axis().Direction() );
+ gp_Vec aFlyoutProj = gp_Vec( aFlyoutDir ) - aPlaneDir * gp_Vec( aFlyoutDir ).Dot( aPlaneDir );
+
+ // snapping is not applicable
+ if ( aSnapPln.Contains( gp_Lin( aFirstPoint, aFlyoutDir ), Precision::Confusion(), Precision::Angular() ) )
+ {
+ continue;
+ }
+ if ( Abs( gp_Vec( aPointOnBase, aPointOnPlane ).Dot( aPlaneDir ) ) > aSnapTolerance )
+ {
+ continue;
+ }
+ if ( aFlyoutProj.Magnitude() <= Precision::Confusion() )
+ {
+ continue;
+ }
+
+ aFlyoutDir = gp_Dir( aFlyoutProj );
+
+ break;
+ }
+
+ Standard_Real aNewFlyout = aPointOnPlane.Distance( aPointOnBase );
+
+ if ( aNewFlyout <= Precision::Confusion() )
+ {
+ myInteractedIO->SetFlyout( 0.0 );
+ myViewer->getAISContext()->Redisplay( myInteractedIO );
+ return;
+ }
+
+ gp_Pln aNewPlane = gp_Pln( aFirstPoint, aBaseDir.Crossed( aFlyoutDir ) );
+
+ myInteractedIO->SetFlyout( aNewFlyout );
+ myInteractedIO->SetCustomPlane( aNewPlane );
+
+ myViewer->getAISContext()->Redisplay( myInteractedIO );
+}
+
+//=================================================================================
+// function : MoveFlyoutInPlane
+// purpose :
+//=================================================================================
+void MeasureGUI_DimensionInteractor::MoveFlyoutInPlane( const Handle(V3d_View)& theView,
+ const int theX,
+ const int theY )
+{
+ // project point onto dimension plane
+ bool isProjected = false;
+ gp_Pln aPlane = myInteractedIO->GetPlane();
+ gp_Pnt aPointOnPlane = ProjectPlane( theView, theX, theY, aPlane, isProjected );
+ if ( !isProjected )
+ {
+ return;
+ }
+
+ const gp_Dir& aPlaneN = aPlane.Axis().Direction();
+
+ // new flyout value
+ Standard_Real aFlyout = 0.0;
+
+ // extend flyout of linear dimension
+ if ( myInteractedIO->IsKind( STANDARD_TYPE( AIS_LengthDimension ) )
+ || myInteractedIO->IsKind( STANDARD_TYPE( AIS_DiameterDimension ) ) )
+ {
+ gp_Pnt aFirstPoint;
+ gp_Pnt aSecondPoint;
+
+ // get first and second point from which the flyout line is normally extended
+ Handle(AIS_LengthDimension) aLength = Handle(AIS_LengthDimension)::DownCast( myInteractedIO );
+ if ( !aLength.IsNull() )
+ {
+ aFirstPoint = aLength->FirstPoint();
+ aSecondPoint = aLength->SecondPoint();
+ }
+
+ Handle(AIS_DiameterDimension) aDiameter = Handle(AIS_DiameterDimension)::DownCast( myInteractedIO );
+ if ( !aDiameter.IsNull() )
+ {
+ const gp_Pnt& aCenter = aDiameter->Circle().Location();
+ aFirstPoint = aDiameter->AnchorPoint();
+ aSecondPoint = gp_Pnt( aFirstPoint.XYZ() + gp_Vec( aFirstPoint, aCenter ).XYZ() * 2.0 );
+ }
+
+ gp_Lin aBaseLine( aFirstPoint, gce_MakeDir( aFirstPoint, aSecondPoint ) );
+
+ // check if the negative value is expected
+ gp_Dir aPositiveDir = aPlaneN.Crossed( aBaseLine.Direction() );
+ gp_Dir aPointDir = gce_MakeDir( aBaseLine.Location(), aPointOnPlane );
+ Standard_Boolean isPositive = aPointDir.Dot( aPositiveDir ) > 0;
+
+ aFlyout = isPositive
+ ? aBaseLine.Distance( aPointOnPlane )
+ : -aBaseLine.Distance( aPointOnPlane );
+ }
+
+ // exten flyout of angular dimension
+ if ( myInteractedIO->IsKind( STANDARD_TYPE( AIS_AngleDimension ) ) )
+ {
+ Handle(AIS_AngleDimension) anAngle = Handle(AIS_AngleDimension)::DownCast( myInteractedIO );
+
+ const gp_Pnt& aCenterPoint = anAngle->CenterPoint();
+ const gp_Pnt& aFirstPoint = anAngle->FirstPoint();
+ const gp_Pnt& aSecondPoint = anAngle->SecondPoint();
+
+ gp_Dir aFirstDir = gce_MakeDir( aCenterPoint, aFirstPoint );
+ gp_Dir aSecondDir = gce_MakeDir( aCenterPoint, aSecondPoint );
+
+ Standard_Real aDirAngle = aFirstDir.Angle( aSecondDir );
+
+ // p1 center p2
+ // \ dir /
+ // the direction are: \ | /
+ // first \|/ second
+ // dir c dir
+ //
+
+ gp_Dir aCenterDir = aFirstDir.Rotated( gp_Ax1( aCenterPoint, aPlaneN ), -aDirAngle * 0.5 );
+
+ gp_Dir aPointDir = gce_MakeDir( aCenterPoint, aPointOnPlane );
+
+ Standard_Boolean isPositive = aPointDir.Dot( aCenterDir ) > 0;
+
+ Standard_Real aPointAngle = aPointDir.AngleWithRef( aCenterDir, aPlaneN );
+ if ( !isPositive )
+ {
+ aPointAngle = ( M_PI - Abs( aPointAngle ) ) * ( -Sign( 1.0, aPointAngle ) );
+ }
+
+ gp_Vec aPointVec = gp_Vec( aCenterPoint, aPointOnPlane );
+
+ // calculate flyout for each separate case of point location
+ if ( aPointAngle < -aDirAngle * 0.5 ) // outside of second dir
+ {
+ aFlyout = aPointVec.Dot( aFirstDir );
+ }
+ else if ( aPointAngle > aDirAngle * 0.5 ) // outside of first dir
+ {
+ aFlyout = aPointVec.Dot( aSecondDir );
+ }
+ else // between first and second direction
+ {
+ aFlyout = isPositive
+ ? aPointVec.Magnitude()
+ : -aPointVec.Magnitude();
+ }
+ }
+
+ myInteractedIO->SetFlyout( aFlyout );
+
+ myViewer->getAISContext()->Redisplay( myInteractedIO );
+}
+
+//=================================================================================
+// function : MoveText
+// purpose :
+//=================================================================================
+void MeasureGUI_DimensionInteractor::MoveText( const Handle(V3d_View)& theView,
+ const int theX,
+ const int theY )
+{
+ // project point onto dimension plane
+ bool isProjected = false;
+ gp_Pln aPlane = myInteractedIO->GetPlane();
+ gp_Pnt aPointOnPlane = ProjectPlane( theView, theX, theY, aPlane, isProjected );
+ if ( !isProjected )
+ {
+ return;
+ }
+
+ const gp_Dir& aPlaneN = aPlane.Axis().Direction();
+
+ Prs3d_DimensionTextHorizontalPosition aHPos = myInteractedIO->DimensionAspect()->TextHorizontalPosition();
+ Prs3d_DimensionTextVerticalPosition aVPos = myInteractedIO->DimensionAspect()->TextVerticalPosition();
+
+ Standard_Real aHeight = myInteractedIO->DimensionAspect()->TextAspect()->Height() * 0.5;
+
+ // move text of linear dimension
+ if ( myInteractedIO->IsKind( STANDARD_TYPE( AIS_LengthDimension ) )
+ || myInteractedIO->IsKind( STANDARD_TYPE( AIS_DiameterDimension ) ) )
+ {
+ gp_Pnt aFirstPoint;
+ gp_Pnt aSecondPoint;
+
+ // get first and second point from which the flyout line is normally extended
+ Handle(AIS_LengthDimension) aLength = Handle(AIS_LengthDimension)::DownCast( myInteractedIO );
+ if ( !aLength.IsNull() )
+ {
+ aFirstPoint = aLength->FirstPoint();
+ aSecondPoint = aLength->SecondPoint();
+ }
+
+ Handle(AIS_DiameterDimension) aDiameter = Handle(AIS_DiameterDimension)::DownCast( myInteractedIO );
+ if ( !aDiameter.IsNull() )
+ {
+ const gp_Pnt& aCenter = aDiameter->Circle().Location();
+ aFirstPoint = aDiameter->AnchorPoint();
+ aSecondPoint = gp_Pnt( aFirstPoint.XYZ() + gp_Vec( aFirstPoint, aCenter ).XYZ() * 2.0 );
+ }
+
+ // get flyout line
+ Standard_Real aFlyout = myInteractedIO->GetFlyout();
+ gp_Dir aBaseDir = gce_MakeDir( aFirstPoint, aSecondPoint );
+ gp_Dir aFlyoutDir = aFlyout >= 0.0
+ ? aPlaneN.Crossed( gce_MakeDir( aFirstPoint, aSecondPoint ) )
+ : -aPlaneN.Crossed( gce_MakeDir( aFirstPoint, aSecondPoint ) );
+ gp_Vec aFlyoutTranslate = gp_Vec( aFlyoutDir ) * Abs( myInteractedIO->GetFlyout() );
+ gp_Lin aFlyoutLine = gp_Lin( aFirstPoint, aBaseDir ).Translated( aFlyoutTranslate );
+
+ // check if positive or negative offset along flyout line
+ gp_Vec aFlyout2Point = gp_Vec( aFlyoutLine.Location(), aPointOnPlane );
+
+ Standard_Real aPosY = aFlyout2Point.Dot( aFlyoutDir );
+ Standard_Real aPosX = aFlyout2Point.Dot( aFlyoutLine.Direction() );
+
+ if ( aPosX < 0.0 )
+ {
+ aHPos = Prs3d_DTHP_Left;
+ }
+ else if ( aPosX > aFirstPoint.Distance( aSecondPoint ) )
+ {
+ aHPos = Prs3d_DTHP_Right;
+ }
+ else
+ {
+ aHPos = Prs3d_DTHP_Center;
+ }
+
+ if ( aPosY > aHeight )
+ {
+ aVPos = Prs3d_DTVP_Above;
+ }
+ else if ( aPosY < -aHeight )
+ {
+ aVPos = Prs3d_DTVP_Below;
+ }
+ else
+ {
+ aVPos = Prs3d_DTVP_Center;
+ }
+ }
+
+ // move text of angular dimension
+ if ( myInteractedIO->IsKind( STANDARD_TYPE( AIS_AngleDimension ) ) )
+ {
+ Handle(AIS_AngleDimension) anAngle = Handle(AIS_AngleDimension)::DownCast( myInteractedIO );
+
+ const gp_Pnt& aCenterPoint = anAngle->CenterPoint();
+ const gp_Pnt& aFirstPoint = anAngle->FirstPoint();
+ const gp_Pnt& aSecondPoint = anAngle->SecondPoint();
+
+ gp_Dir aFirstDir = gce_MakeDir( aCenterPoint, aFirstPoint );
+ gp_Dir aSecondDir = gce_MakeDir( aCenterPoint, aSecondPoint );
+
+ Standard_Real aDirAngle = aFirstDir.Angle( aSecondDir );
+
+ // p1 center p2
+ // \ dir /
+ // the direction are: \ | /
+ // first \|/ second
+ // dir c dir
+ //
+
+ gp_Dir aCenterDir = aFirstDir.Rotated( gp_Ax1( aCenterPoint, aPlaneN ), -aDirAngle * 0.5 );
+
+ gp_Dir aPointDir = gce_MakeDir( aCenterPoint, aPointOnPlane );
+
+ Standard_Boolean isPositive = aPointDir.Dot( aCenterDir ) > 0;
+
+ Standard_Real aPointAngle = aPointDir.AngleWithRef( aCenterDir, aPlaneN );
+ if ( !isPositive )
+ {
+ aPointAngle = ( M_PI - Abs( aPointAngle ) ) * ( -Sign( 1.0, aPointAngle ) );
+ }
+
+ gp_Vec aPointVec = gp_Vec( aCenterPoint, aPointOnPlane );
+
+ Standard_Real aPosY = 0.0;
+
+ // the point should lie within the dimension flyout area
+ if ( isPositive && aPointVec.Dot( aFirstDir ) < 0.0
+ || !isPositive && aPointVec.Dot( aFirstDir ) > 0.0 )
+ {
+ return;
+ }
+
+ // calculate flyout for each separate case of point location
+ if ( aPointAngle < -aDirAngle * 0.5 ) // outside of second dir
+ {
+ aHPos = Prs3d_DTHP_Left;
+ aPosY = Abs( aPointVec.Dot( aFirstDir ) ) - Abs( myInteractedIO->GetFlyout() );
+ }
+ else if ( aPointAngle > aDirAngle * 0.5 ) // outside of first dir
+ {
+ aHPos = Prs3d_DTHP_Right;
+ aPosY = Abs( aPointVec.Dot( aSecondDir ) ) - Abs( myInteractedIO->GetFlyout() );
+ }
+ else // between first and second direction
+ {
+ aHPos = Prs3d_DTHP_Center;
+ aPosY = Abs( aPointVec.Magnitude() ) - Abs( myInteractedIO->GetFlyout() );
+ }
+
+ if ( aPosY > aHeight )
+ {
+ aVPos = Prs3d_DTVP_Above;
+ }
+ else if ( aPosY < -aHeight )
+ {
+ aVPos = Prs3d_DTVP_Below;
+ }
+ else
+ {
+ aVPos = Prs3d_DTVP_Center;
+ }
+ }
+
+ myInteractedIO->DimensionAspect()->SetTextVerticalPosition( aVPos );
+ myInteractedIO->DimensionAspect()->SetTextHorizontalPosition( aHPos );
+ myInteractedIO->SetToUpdate();
+
+ myViewer->getAISContext()->Redisplay( myInteractedIO );
+}
+
+//=================================================================================
+// function : eventFilter
+// purpose :
+//=================================================================================
+bool MeasureGUI_DimensionInteractor::eventFilter( QObject* theObject, QEvent* theEvent )
+{
+ OCCViewer_ViewPort3d* aViewPort = (OCCViewer_ViewPort3d*) theObject;
+
+ Handle(V3d_View) aView3d = aViewPort->getView();
+
+ switch ( theEvent->type() )
+ {
+ // check whether it is the "dimension modify" operation or not.
+ case QEvent::MouseButtonPress :
+ {
+ Handle(AIS_InteractiveContext) anAISContext = myViewer->getAISContext();
+
+ QMouseEvent* aMouseEv = dynamic_cast( theEvent );
+
+ // init detection
+ anAISContext->MoveTo( aMouseEv->x(), aMouseEv->y(), aView3d );
+ if ( !anAISContext->HasDetected() )
+ {
+ return false;
+ }
+
+ // check that there is only one detected entity
+ anAISContext->InitDetected();
+ if ( anAISContext->MoreDetected() )
+ {
+ return false;
+ }
+
+ Handle(SelectMgr_EntityOwner) aDetectedOwner = anAISContext->DetectedOwner();
+
+ myInteractedIO = Handle(AIS_Dimension)::DownCast( aDetectedOwner->Selectable() );
+
+ // try to start operation for the detected entity
+ Operation aStartOp = GetOperation( aDetectedOwner, aMouseEv->buttons(), aMouseEv->modifiers() );
+ if ( aStartOp == Operation_None )
+ {
+ return false;
+ }
+
+ if ( !StartOperation( aStartOp, aView3d, aMouseEv->x(), aMouseEv->y() ) )
+ {
+ return false;
+ }
+
+ myOperation = aStartOp;
+
+ mySelection.Clear();
+
+ for ( anAISContext->InitSelected(); anAISContext->MoreSelected(); anAISContext->NextSelected() )
+ {
+ mySelection.Append( anAISContext->SelectedOwner() );
+ }
+
+ anAISContext->ClearSelected( Standard_False );
+ anAISContext->AddOrRemoveSelected( aDetectedOwner );
+
+ emit InteractionStarted( myInteractedIO );
+
+ return true;
+ }
+
+ // stop event processing on mouse release
+ case QEvent::MouseButtonRelease :
+ {
+ if ( myOperation != Operation_None )
+ {
+ Handle(AIS_InteractiveContext) anAISContext = myViewer->getAISContext();
+
+ anAISContext->ClearSelected( Standard_False );
+ SeqOfOwners::Iterator anIt( mySelection );
+ for( ; anIt.More(); anIt.Next() )
+ {
+ anAISContext->AddOrRemoveSelected( anIt.Value(), Standard_False );
+ }
+
+ anAISContext->UpdateCurrentViewer();
+
+ mySelection.Clear();
+
+ myOperation = Operation_None;
+
+ emit InteractionFinished( myInteractedIO );
+
+ return true;
+ }
+
+ return false;
+ }
+
+ // perform operation
+ case QEvent::MouseMove :
+ {
+ QMouseEvent* aMouseEv = (QMouseEvent*) theEvent;
+ switch( myOperation )
+ {
+ case Operation_MoveFlyoutFree : MoveFlyoutFree ( aView3d, aMouseEv->x(), aMouseEv->y() ); return true;
+ case Operation_MoveFlyoutInPlane : MoveFlyoutInPlane( aView3d, aMouseEv->x(), aMouseEv->y() ); return true;
+ case Operation_MoveText : MoveText ( aView3d, aMouseEv->x(), aMouseEv->y() ); return true;
+ default : return false;
+ }
+ }
+
+ default: return false;
+ }
+}
+
+//=================================================================================
+// function : ConnectView
+// purpose :
+//=================================================================================
+void MeasureGUI_DimensionInteractor::ConnectView( SUIT_ViewWindow* theView )
+{
+ ( (OCCViewer_ViewWindow*) theView )->getViewPort()->installEventFilter( this );
+}
+
+//=================================================================================
+// function : DisconnectView
+// purpose :
+//=================================================================================
+void MeasureGUI_DimensionInteractor::DisconnectView( SUIT_ViewWindow* theView )
+{
+ ( (OCCViewer_ViewWindow*) theView )->getViewPort()->removeEventFilter( this );
+}
+
+//=================================================================================
+// function : Projection
+// purpose :
+//=================================================================================
+gp_Lin MeasureGUI_DimensionInteractor::Projection( const Handle(V3d_View)& theView,
+ const int theMouseX,
+ const int theMouseY )
+{
+ Standard_Real P[3], D[3];
+ theView->ConvertWithProj( theMouseX, theMouseY, P[0], P[1], P[2], D[0], D[1], D[2] );
+ return gp_Lin( gp_Pnt( P[0], P[1], P[2] ), gp_Dir( D[0], D[1], D[2] ) );
+}
+
+//=================================================================================
+// function : ProjectPlane
+// purpose :
+//=================================================================================
+gp_Pnt MeasureGUI_DimensionInteractor::ProjectPlane( const Handle(V3d_View)& theView,
+ const int theMouseX,
+ const int theMouseY,
+ const gp_Pln& thePlane,
+ bool& theIsDone )
+{
+ gp_Lin aProjection = Projection( theView, theMouseX, theMouseY );
+
+ Handle(Geom_Line) aCrossLine = new Geom_Line( aProjection );
+ Handle(Geom_Plane) aCrossPlane = new Geom_Plane( thePlane );
+
+ GeomAPI_IntCS aFindCross( aCrossLine, aCrossPlane );
+ if ( !aFindCross.IsDone() || aFindCross.NbPoints() == 0 )
+ {
+ theIsDone = false;
+ return gp::Origin();
+ }
+
+ theIsDone = true;
+ return aFindCross.Point( 1 );
+}
+
+//=================================================================================
+// function : SensitivityTolerance
+// purpose :
+//=================================================================================
+Standard_Real MeasureGUI_DimensionInteractor::SensitivityTolerance( const Handle(V3d_View)& theView )
+{
+ // snapping tolerance
+ Quantity_Length aSize[2];
+ theView->Size( aSize[0], aSize[1] );
+ return 1e-2 * Max( aSize[0], aSize[1] );
+}
+
+//=================================================================================
+// function : OnViewCreated
+// purpose :
+//=================================================================================
+void MeasureGUI_DimensionInteractor::OnViewCreated( SUIT_ViewWindow* theView )
+{
+ ConnectView( theView );
+}
+
+//=================================================================================
+// function : OnViewRemoved
+// purpose :
+//=================================================================================
+void MeasureGUI_DimensionInteractor::OnViewRemoved( SUIT_ViewWindow* theView )
+{
+ DisconnectView( theView );
+}
diff --git a/src/MeasureGUI/MeasureGUI_DimensionInteractor.h b/src/MeasureGUI/MeasureGUI_DimensionInteractor.h
new file mode 100644
index 000000000..4ed77c29d
--- /dev/null
+++ b/src/MeasureGUI/MeasureGUI_DimensionInteractor.h
@@ -0,0 +1,177 @@
+// Copyright (C) 2007-2013 CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+// GEOM GEOMGUI : GUI for Geometry component
+// File : MeasureGUI_DimensionEditor.h
+// Author : Anton POLETAEV, Open CASCADE S.A.S.
+//
+#ifndef MEASUREGUI_DIMENSIONINTERACTOR_H
+#define MEASUREGUI_DIMENSIONINTERACTOR_H
+
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+class OCCViewer_ViewManager;
+class OCCViewer_Viewer;
+class SUIT_ViewWindow;
+class Handle(V3d_View);
+
+//=================================================================================
+// class : MeasureGUI_DimensionInteractor
+// purpose : Interactive editor of dimension presentations
+//=================================================================================
+class MeasureGUI_DimensionInteractor : public QObject
+{
+ Q_OBJECT
+
+public:
+ enum Operation
+ {
+ Operation_MoveFlyoutFree,
+ Operation_MoveFlyoutInPlane,
+ Operation_MoveText,
+ Operation_None
+ };
+
+public:
+ MeasureGUI_DimensionInteractor( GeometryGUI*, QObject* );
+ ~MeasureGUI_DimensionInteractor();
+
+public:
+ void Enable();
+ void Disable();
+
+protected:
+ /*!
+ * \brief Identify interactive operation by picked entity and pressed buttons with modifiers
+ *
+ * \param theEntity [in] the picked entity.
+ * \param theButtons [in] the mouse buttons.
+ * \param theKeys [in] the keyboard modifiers.
+ */
+ Operation GetOperation( const Handle(SelectMgr_EntityOwner)& theEntity,
+ const Qt::MouseButtons theButtons,
+ const Qt::KeyboardModifiers theKeys );
+
+ /*!
+ * \brief Prepare for interactive operation.
+ *
+ * \param theOp [in] the operation.
+ * \param theView [in] the interacted view.
+ * \param theX [in] the mouse position x.
+ * \param theY [in] the mouse position y.
+ * \return TRUE if operation can be started.
+ */
+ bool StartOperation( const Operation theOperation,
+ const Handle(V3d_View)& theView,
+ const int theX,
+ const int theY );
+
+ /*!
+ * \brief Perform "Operation_MoveFlyoutFree".
+ * Modify flyout of interactive dimension so as the flyout follows
+ * the mouse by its length and orientation.
+ *
+ * \param theView [in] the interacted view.
+ * \param theX [in] the mouse position x.
+ * \param theY [in] the mouse position y.
+ */
+ void MoveFlyoutFree( const Handle(V3d_View)& theView, const int theX, const int theY );
+
+ /*!
+ * \brief Perform "Operation_MoveFlyoutInPlane".
+ * Modify flyout of interactive dimension so as the flyout is extended
+ * to the mouse point location in the presentation plane.
+ *
+ * \param theView [in] the interacted view.
+ * \param theX [in] the mouse position x.
+ * \param theY [in] the mouse position y.
+ */
+ void MoveFlyoutInPlane( const Handle(V3d_View)& theView, const int theX, const int theY );
+
+ /*!
+ * \brief Perform "Operation_MoveText".
+ * Modify text of interactive dimension so as the text is moved to its fixed positions.
+ *
+ * \param theView [in] the interacted view.
+ * \param theX [in] the mouse position x.
+ * \param theY [in] the mouse position y.
+ */
+ void MoveText( const Handle(V3d_View)& theView, const int theX, const int theY );
+
+signals:
+ void InteractionStarted( Handle_AIS_InteractiveObject theIO );
+ void InteractionFinished( Handle_AIS_InteractiveObject theIO );
+
+protected:
+ void ConnectView( SUIT_ViewWindow* );
+ void DisconnectView( SUIT_ViewWindow* );
+ gp_Lin Projection( const Handle(V3d_View)&, const int, const int );
+ gp_Pnt ProjectPlane( const Handle(V3d_View)&,
+ const int,
+ const int,
+ const gp_Pln&,
+ bool& );
+ Standard_Real SensitivityTolerance( const Handle(V3d_View)& );
+
+protected:
+ /*!
+ * \brief Process events from OCC viewer prior to their coming into the base viewer class.
+ *
+ * It handles the events coming to viewport and identifies whether the events correspond to
+ * interactive operation on dimension. If yes, the operation is performed within the
+ * interactor class and events are "accepted". Otherwise, the events are passed to
+ * viewer subroutines.
+ *
+ * The method manages internal workflow related to starting and stopping interactive
+ * operations to modify the presentations which were passed for this interactor class.
+ *
+ */
+ virtual bool eventFilter( QObject*, QEvent* );
+
+protected slots:
+ void OnViewCreated( SUIT_ViewWindow* );
+ void OnViewRemoved( SUIT_ViewWindow* );
+
+private:
+ typedef NCollection_Sequence SeqOfOwners;
+
+private:
+ GeometryGUI* myGeomGUI;
+ bool myIsEnabled;
+ OCCViewer_ViewManager* myVM;
+ OCCViewer_Viewer* myViewer;
+ Operation myOperation;
+ bool myOperationStarted;
+ gp_Pln myFreeMovePlane;
+ Handle(AIS_Dimension) myInteractedIO;
+ SeqOfOwners mySelection;
+};
+
+#endif
diff --git a/src/MeasureGUI/MeasureGUI_ManageDimensionsDlg.cxx b/src/MeasureGUI/MeasureGUI_ManageDimensionsDlg.cxx
new file mode 100644
index 000000000..62b43b4e2
--- /dev/null
+++ b/src/MeasureGUI/MeasureGUI_ManageDimensionsDlg.cxx
@@ -0,0 +1,1183 @@
+// Copyright (C) 2007-2013 CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+// GEOM GEOMGUI : GUI for Geometry component
+// File : MeasureGUI_ManageDimensionsDlg.cxx
+// Author : Anton POLETAEV, Open CASCADE S.A.S.
+
+#include "MeasureGUI_ManageDimensionsDlg.h"
+#include "MeasureGUI_CreateDimensionDlg.h"
+#include "MeasureGUI_DimensionFilter.h"
+
+#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
+#include
+
+//=================================================================================
+// function : Constructor
+// purpose :
+//=================================================================================
+MeasureGUI_ManageDimensionsDlg::MeasureGUI_ManageDimensionsDlg( GeometryGUI* theGUI, QWidget* theParent )
+: GEOMBase_Skeleton( theGUI, theParent ),
+ myOperatedViewer( NULL ),
+ myCurrentSelection( Selection_None )
+{
+ SUIT_ResourceMgr* aResMgr = SUIT_Session::session()->resourceMgr();
+
+ QPixmap aSelectorIcon = aResMgr->loadPixmap( "GEOM", tr( "ICON_SELECT" ) );
+
+ setWindowTitle( tr( "MANAGE_DIMENSIONS_TITLE" ) );
+
+ mainFrame()->GroupConstructors->setVisible( false );
+ mainFrame()->GroupBoxName->setVisible( false );
+
+ // construct object selector pane
+ myObjectSelector = new DlgRef_1Sel( centralWidget() );
+ myObjectSelector->TextLabel1->setText( tr( "OBJECT_LABEL" ) );
+ myObjectSelector->LineEdit1->setReadOnly( true );
+ myObjectSelector->PushButton1->setIcon( aSelectorIcon );
+ myObjectSelector->PushButton1->setCheckable( true );
+
+ // construct dimension list view pane
+ myDimensionView = new MeasureGUI_1TreeWidget_4Button( centralWidget() );
+ myDimensionView->GroupBox->setTitle( tr( "DIMENSIONS_GROUP" ) );
+ myDimensionView->PushButton1->setText( tr( "ADD_BTN" ) );
+ myDimensionView->PushButton2->setText( tr( "REMOVE_BTN" ) );
+ myDimensionView->PushButton3->setText( tr( "SHOW_ALL_BTN" ) );
+ myDimensionView->PushButton4->setText( tr( "HIDE_ALL_BTN" ) );
+ myDimensionView->TreeWidget->setMinimumHeight( 250 );
+ myDimensionView->setEnabled( false );
+
+ connect( myDimensionView->PushButton1, SIGNAL( clicked() ), SLOT( OnAdd() ) );
+ connect( myDimensionView->PushButton2, SIGNAL( clicked() ), SLOT( OnRemove() ) );
+ connect( myDimensionView->PushButton3, SIGNAL( clicked() ), SLOT( OnShowAll() ) );
+ connect( myDimensionView->PushButton4, SIGNAL( clicked() ), SLOT( OnHideAll() ) );
+ connect( myDimensionView->TreeWidget,
+ SIGNAL( itemChanged( QTreeWidgetItem*, int ) ),
+ SLOT( OnChangeItem( QTreeWidgetItem* ) ) );
+ connect( myDimensionView->TreeWidget,
+ SIGNAL( currentItemChanged( QTreeWidgetItem*, QTreeWidgetItem* ) ),
+ SLOT( OnSelectItem() ) );
+
+ // populate tree with top-level items
+ myDimensionView->TreeWidget->setHeaderItem( new QTreeWidgetItem( (QTreeWidget*)NULL, QStringList( QString() ) ) );
+
+ // construct main frame layout
+ QVBoxLayout* aMainLayout = new QVBoxLayout( centralWidget() );
+ aMainLayout->setMargin( 0 );
+ aMainLayout->addWidget( myObjectSelector, 0 );
+ aMainLayout->addWidget( myDimensionView, 1 );
+
+ // signals and slots connections
+ connect( myObjectSelector->PushButton1, SIGNAL( clicked() ), SLOT( StartObjectSelection() ) );
+ connect( buttonOk(), SIGNAL( clicked() ), SLOT( ClickOnOk() ) );
+ connect( buttonApply(), SIGNAL( clicked() ), SLOT( ClickOnApply() ) );
+
+ connect( this, SIGNAL( finished( int ) ), SLOT( OnFinish() ) );
+
+ myDimensionInteractor = new MeasureGUI_DimensionInteractor( theGUI, theParent ),
+
+ SelectionIntoArgument( Selection_Object );
+
+ if ( myEditObject.isNull() )
+ {
+ myObjectSelector->PushButton1->click();
+ }
+}
+
+//=================================================================================
+// function : Destructor
+// purpose :
+//=================================================================================
+MeasureGUI_ManageDimensionsDlg::~MeasureGUI_ManageDimensionsDlg()
+{
+ StopSelection();
+}
+
+//=================================================================================
+// function : StartSelection
+// purpose : Starts specific selection
+//=================================================================================
+void MeasureGUI_ManageDimensionsDlg::StartSelection( const Selection theSelection )
+{
+ StopSelection();
+
+ myCurrentSelection = theSelection;
+
+ if ( theSelection == Selection_Object && WarnUnsaved() )
+ {
+ /* ----------------------------------------------- *
+ * selection of object *
+ * ------------------------------------------------ */
+
+ globalSelection( GEOM_ALLSHAPES );
+ connect( myGeomGUI->getApp()->selectionMgr(),
+ SIGNAL( currentSelectionChanged() ),
+ this,
+ SLOT( OnSelection() ) );
+ }
+ else if ( theSelection == Selection_Dimension && !myEditObject.isNull() )
+ {
+ /* ----------------------------------------------- *
+ * selection of dimension *
+ * ------------------------------------------------ */
+
+ SalomeApp_Application* anApp = myGeomGUI->getApp();
+ if ( !anApp )
+ {
+ return;
+ }
+
+ SUIT_ViewManager* aViewMgr = anApp->activeViewManager();
+ if ( aViewMgr->getType() != SOCC_Viewer::Type() )
+ {
+ return;
+ }
+
+ myOperatedViewer = dynamic_cast( aViewMgr->getViewModel() );
+
+ globalSelection();
+
+ Handle(AIS_InteractiveContext) anAISContext = myOperatedViewer->getAISContext();
+
+ anAISContext->ClearCurrents( Standard_False );
+ anAISContext->ClearSelected( Standard_False );
+ anAISContext->OpenLocalContext( Standard_True, Standard_False );
+
+ Handle(MeasureGUI_DimensionFilter) aFilter = new MeasureGUI_DimensionFilter( myEditObject->GetStudyEntry() );
+
+ anAISContext->AddFilter( aFilter );
+
+ LightApp_SelectionMgr* aSelectionMgr = myGeomGUI->getApp()->selectionMgr();
+
+ QList aSelectors;
+ aSelectionMgr->selectors( aSelectors );
+ QList::iterator aSelectorIt = aSelectors.begin();
+ for ( ; aSelectorIt != aSelectors.end(); ++aSelectorIt )
+ {
+ SUIT_Selector* aSelector = *aSelectorIt;
+
+ GEOMGUI_OCCSelector* aGeomSelector = dynamic_cast( aSelector );
+ if ( !aGeomSelector )
+ {
+ continue;
+ }
+
+ aGeomSelector->setEnabled( false );
+ }
+
+ connect( myOperatedViewer,
+ SIGNAL( selectionChanged() ),
+ this,
+ SLOT( OnSelection() ) );
+
+ myDimensionInteractor->Enable();
+
+ connect( myDimensionInteractor,
+ SIGNAL( InteractionFinished( Handle_AIS_InteractiveObject ) ),
+ this,
+ SLOT( OnInteractionFinished( Handle_AIS_InteractiveObject ) ) );
+
+ anAISContext->UpdateCurrentViewer();
+ }
+}
+
+//=================================================================================
+// function : StopObjectSelection
+// purpose : Stops specific selection
+//=================================================================================
+void MeasureGUI_ManageDimensionsDlg::StopSelection()
+{
+ if ( myCurrentSelection == Selection_Object )
+ {
+ /* ----------------------------------------------- *
+ * selection of object *
+ * ------------------------------------------------ */
+
+ myObjectSelector->PushButton1->setChecked( false );
+ disconnect( myGeomGUI->getApp()->selectionMgr(),
+ SIGNAL( currentSelectionChanged() ),
+ this,
+ SLOT( OnSelection() ) );
+ }
+ else if ( myCurrentSelection == Selection_Dimension && myOperatedViewer )
+ {
+ /* ----------------------------------------------- *
+ * selection of dimension *
+ * ------------------------------------------------ */
+
+ Handle(AIS_InteractiveContext) anAISContext = myOperatedViewer->getAISContext();
+
+ anAISContext->CloseLocalContext();
+
+ LightApp_SelectionMgr* aSelectionMgr = myGeomGUI->getApp()->selectionMgr();
+
+ QList aSelectors;
+ aSelectionMgr->selectors( aSelectors );
+ QList::iterator aSelectorIt = aSelectors.begin();
+ for ( ; aSelectorIt != aSelectors.end(); ++aSelectorIt )
+ {
+ SUIT_Selector* aSelector = *aSelectorIt;
+
+ GEOMGUI_OCCSelector* aGeomSelector = dynamic_cast( aSelector );
+ if ( !aGeomSelector )
+ {
+ continue;
+ }
+
+ aGeomSelector->setEnabled( true );
+ }
+
+ disconnect( myOperatedViewer,
+ SIGNAL( selectionChanged() ),
+ this,
+ SLOT( OnSelection() ) );
+
+ myDimensionInteractor->Disable();
+
+ disconnect( myDimensionInteractor,
+ SIGNAL( InteractionFinished( Handle_AIS_InteractiveObject ) ),
+ this,
+ SLOT( OnInteractionFinished( Handle_AIS_InteractiveObject ) ) );
+ }
+
+ myCurrentSelection = Selection_None;
+
+ globalSelection();
+}
+
+//=================================================================================
+// function : OnSelection
+// purpose :
+//=================================================================================
+void MeasureGUI_ManageDimensionsDlg::OnSelection()
+{
+ SelectionIntoArgument( myCurrentSelection );
+}
+
+//=================================================================================
+// function : SelectionIntoArgument
+// purpose :
+//=================================================================================
+void MeasureGUI_ManageDimensionsDlg::SelectionIntoArgument( const Selection theSelection )
+{
+ if ( theSelection == Selection_Object )
+ {
+ /* ----------------------------------------------- *
+ * selection of object *
+ * ------------------------------------------------ */
+
+ LightApp_SelectionMgr* aSelectionMgr = myGeomGUI->getApp()->selectionMgr();
+ SALOME_ListIO aSelection;
+ aSelectionMgr->selectedObjects( aSelection );
+
+ GEOM::GeomObjPtr aSelected;
+
+ if ( aSelection.Extent() == 1 )
+ {
+ aSelected = GEOMBase::ConvertIOinGEOMObject( aSelection.First() );
+ }
+
+ SetEditObject( aSelected );
+ StartSelection( Selection_Dimension );
+ }
+ else if ( theSelection == Selection_Dimension && myOperatedViewer )
+ {
+ /* ----------------------------------------------- *
+ * selection of dimension *
+ * ------------------------------------------------ */
+
+ QTreeWidget* aDimensionList = myDimensionView->TreeWidget;
+
+ Handle(AIS_InteractiveContext) anAISContext = myOperatedViewer->getAISContext();
+
+ // non-single selection is prohibited
+ if ( anAISContext->NbSelected() != 1 )
+ {
+ aDimensionList->setCurrentIndex( QModelIndex() );
+ return;
+ }
+
+ anAISContext->InitSelected();
+
+ Handle(AIS_InteractiveObject) anAIS;
+
+ if ( anAISContext->HasOpenedContext() )
+ {
+ Handle(SelectMgr_EntityOwner) anAISOwner = anAISContext->SelectedOwner();
+ anAIS = Handle(AIS_InteractiveObject)::DownCast( anAISOwner->Selectable() );
+ }
+ else
+ {
+ anAIS = anAISContext->Current();
+ }
+
+ int aDimensionId = IdFromPrs( anAIS );
+
+ SelectInList( aDimensionId );
+
+ if ( aDimensionId >= 0 )
+ {
+ SelectInViewer( myOperatedViewer, aDimensionId );
+ }
+ }
+}
+
+//=================================================================================
+// function : OnAdd
+// purpose :
+//=================================================================================
+void MeasureGUI_ManageDimensionsDlg::OnAdd()
+{
+ QWidget* aParent = qobject_cast( this->parent() );
+
+ this->Suspend();
+
+ MeasureGUI_CreateDimensionDlg* aCreateDlg = new MeasureGUI_CreateDimensionDlg( myEditObject, myGeomGUI, aParent );
+
+ connect( aCreateDlg, SIGNAL( finished( int ) ), this, SLOT( Resume() ) );
+
+ // this is necessary as the GEOMBase_Helper switches selection mode on destruction
+ connect( aCreateDlg, SIGNAL( destroyed( QObject* ) ), this, SLOT( Resume() ) );
+
+ aCreateDlg->updateGeometry();
+ aCreateDlg->resize( aCreateDlg->minimumSizeHint() );
+ aCreateDlg->show();
+}
+
+//=================================================================================
+// function : OnRemove
+// purpose :
+//=================================================================================
+void MeasureGUI_ManageDimensionsDlg::OnRemove()
+{
+ int aDimensionId = IdFromItem( myDimensionView->TreeWidget->currentItem() );
+ if ( aDimensionId < 0 )
+ {
+ return;
+ }
+
+ SalomeApp_Application* anApp = myGeomGUI->getApp();
+ if ( !anApp )
+ {
+ return;
+ }
+
+ SalomeApp_Study* aStudy = dynamic_cast( anApp->activeStudy() );
+ if ( !aStudy )
+ {
+ return;
+ }
+
+ // get property data to change
+ GEOMGUI_DimensionProperty aProp =
+ aStudy->getObjectProperty( GEOM::sharedPropertiesId(),
+ myEditObject->GetStudyEntry(),
+ GEOM::propertyName( GEOM::Dimensions ),
+ QVariant() )
+ .value();
+
+ aProp.RemoveRecord( aDimensionId );
+
+ // store modified property data
+ aStudy->setObjectProperty( GEOM::sharedPropertiesId(),
+ myEditObject->GetStudyEntry(),
+ GEOM::propertyName( GEOM::Dimensions ),
+ aProp );
+
+ PopulateList();
+
+ RedisplayObject();
+}
+
+//=================================================================================
+// function : OnChangeItem
+// purpose :
+//=================================================================================
+void MeasureGUI_ManageDimensionsDlg::OnChangeItem( QTreeWidgetItem* theItem )
+{
+ int aDimensionId = IdFromItem( theItem );
+ if ( aDimensionId < 0 )
+ {
+ return;
+ }
+
+ SalomeApp_Application* anApp = myGeomGUI->getApp();
+ if ( !anApp )
+ {
+ return;
+ }
+
+ SalomeApp_Study* aStudy = dynamic_cast( anApp->activeStudy() );
+ if ( !aStudy )
+ {
+ return;
+ }
+
+ // get property data to change
+ GEOMGUI_DimensionProperty aProp =
+ aStudy->getObjectProperty( GEOM::sharedPropertiesId(),
+ myEditObject->GetStudyEntry(),
+ GEOM::propertyName( GEOM::Dimensions ),
+ QVariant() )
+ .value();
+
+ // change property data
+ bool isAnythingChanged = false;
+
+ QString aName = theItem->text( 0 );
+ if ( aProp.GetName( aDimensionId ) != aName )
+ {
+ isAnythingChanged = true;
+ aProp.SetName( aDimensionId, aName );
+ }
+
+ bool isVisible = theItem->checkState( 0 ) == Qt::Checked;
+ if ( aProp.IsVisible( aDimensionId ) != isVisible )
+ {
+ isAnythingChanged = true;
+ aProp.SetVisible( aDimensionId, isVisible );
+ }
+
+ // store property data
+ if ( !isAnythingChanged )
+ {
+ return;
+ }
+
+ // store modified property data
+ aStudy->setObjectProperty( GEOM::sharedPropertiesId(),
+ myEditObject->GetStudyEntry(),
+ GEOM::propertyName( GEOM::Dimensions ),
+ aProp );
+
+ RedisplayObject();
+}
+
+//=================================================================================
+// function : OnSelectItem
+// purpose :
+//=================================================================================
+void MeasureGUI_ManageDimensionsDlg::OnSelectItem()
+{
+ if ( !myOperatedViewer )
+ {
+ return;
+ }
+
+ QTreeWidgetItem* aSelectedItem = myDimensionView->TreeWidget->currentItem();
+
+ SelectInViewer( myOperatedViewer, IdFromItem( aSelectedItem ) );
+}
+
+//=================================================================================
+// function : OnShowAll
+// purpose :
+//=================================================================================
+void MeasureGUI_ManageDimensionsDlg::OnShowAll()
+{
+ // read propety data
+ SalomeApp_Application* anApp = myGeomGUI->getApp();
+ if ( !anApp )
+ {
+ return;
+ }
+
+ SalomeApp_Study* aStudy = dynamic_cast( anApp->activeStudy() );
+ if ( !aStudy )
+ {
+ return;
+ }
+
+ // get property data to change
+ GEOMGUI_DimensionProperty aProp =
+ aStudy->getObjectProperty( GEOM::sharedPropertiesId(),
+ myEditObject->GetStudyEntry(),
+ GEOM::propertyName( GEOM::Dimensions ),
+ QVariant() )
+ .value();
+
+ QTreeWidget* aDimensionList = myDimensionView->TreeWidget;
+
+ bool isBlocked = aDimensionList->blockSignals( true );
+
+ for ( int anIt = 0; anIt < aProp.GetNumber(); ++anIt )
+ {
+ aProp.SetVisible( anIt, true );
+ }
+
+ // store modified property data
+ aStudy->setObjectProperty( GEOM::sharedPropertiesId(),
+ myEditObject->GetStudyEntry(),
+ GEOM::propertyName( GEOM::Dimensions ),
+ aProp );
+
+ PopulateList();
+
+ RedisplayObject();
+
+ aDimensionList->blockSignals( isBlocked );
+}
+
+//=================================================================================
+// function : OnHideAll
+// purpose :
+//=================================================================================
+void MeasureGUI_ManageDimensionsDlg::OnHideAll()
+{
+ // read propety data
+ SalomeApp_Application* anApp = myGeomGUI->getApp();
+ if ( !anApp )
+ {
+ return;
+ }
+
+ SalomeApp_Study* aStudy = dynamic_cast( anApp->activeStudy() );
+ if ( !aStudy )
+ {
+ return;
+ }
+
+ // get property data to change
+ GEOMGUI_DimensionProperty aProp =
+ aStudy->getObjectProperty( GEOM::sharedPropertiesId(),
+ myEditObject->GetStudyEntry(),
+ GEOM::propertyName( GEOM::Dimensions ),
+ QVariant() )
+ .value();
+
+ QTreeWidget* aDimensionList = myDimensionView->TreeWidget;
+
+ bool isBlocked = aDimensionList->blockSignals( true );
+
+ for ( int anIt = 0; anIt < aProp.GetNumber(); ++anIt )
+ {
+ aProp.SetVisible( anIt, false );
+ }
+
+ // store modified property data
+ aStudy->setObjectProperty( GEOM::sharedPropertiesId(),
+ myEditObject->GetStudyEntry(),
+ GEOM::propertyName( GEOM::Dimensions ),
+ aProp );
+
+ PopulateList();
+
+ RedisplayObject();
+
+ aDimensionList->blockSignals( isBlocked );
+}
+
+//=================================================================================
+// function : OnInteractionFinished
+// purpose :
+//=================================================================================
+void MeasureGUI_ManageDimensionsDlg::OnInteractionFinished( Handle(AIS_InteractiveObject) theIO )
+{
+ // update property data
+ SalomeApp_Application* anApp = myGeomGUI->getApp();
+ if ( !anApp )
+ {
+ return;
+ }
+
+ SalomeApp_Study* aStudy = dynamic_cast( anApp->activeStudy() );
+ if ( !aStudy )
+ {
+ return;
+ }
+
+ gp_Ax3 aLCS;
+ TopoDS_Shape anParentSh;
+ if ( GEOMBase::GetShape( myEditObject.get(), anParentSh ) )
+ {
+ aLCS = GEOMUtils::GetPosition( anParentSh );
+ }
+
+ int aDimensionId = IdFromPrs( theIO );
+
+ // get property data to change
+ GEOMGUI_DimensionProperty aProp =
+ aStudy->getObjectProperty( GEOM::sharedPropertiesId(),
+ myEditObject->GetStudyEntry(),
+ GEOM::propertyName( GEOM::Dimensions ),
+ QVariant() )
+ .value();
+
+ aProp.SetRecord( aDimensionId, Handle(AIS_Dimension)::DownCast( theIO ), aLCS );
+
+ // store modified property data
+ aStudy->setObjectProperty( GEOM::sharedPropertiesId(),
+ myEditObject->GetStudyEntry(),
+ GEOM::propertyName( GEOM::Dimensions ),
+ aProp );
+}
+
+//=================================================================================
+// function : Suspend
+// purpose :
+//=================================================================================
+void MeasureGUI_ManageDimensionsDlg::Suspend()
+{
+ StopSelection();
+ hide();
+}
+
+//=================================================================================
+// function : Suspend
+// purpose :
+//=================================================================================
+void MeasureGUI_ManageDimensionsDlg::Resume()
+{
+ this->show();
+ if ( !myEditObject.isNull() )
+ {
+ PopulateList();
+ StartSelection( Selection_Dimension );
+ }
+}
+
+//=================================================================================
+// function : ClickOnOk
+// purpose :
+//=================================================================================
+void MeasureGUI_ManageDimensionsDlg::ClickOnOk()
+{
+ setIsApplyAndClose( true );
+ if ( ClickOnApply() )
+ {
+ ClickOnCancel();
+ }
+}
+
+//=================================================================================
+// function : ClickOnCancel
+// purpose :
+//=================================================================================
+void MeasureGUI_ManageDimensionsDlg::ClickOnCancel()
+{
+ if ( !WarnUnsaved() )
+ {
+ return;
+ }
+
+ GEOMBase_Skeleton::ClickOnCancel();
+}
+
+//=================================================================================
+// function : ClickOnApply
+// purpose :
+//=================================================================================
+bool MeasureGUI_ManageDimensionsDlg::ClickOnApply()
+{
+ if ( myEditObject.isNull() )
+ {
+ return true;
+ }
+
+ SalomeApp_Application* anApp = myGeomGUI->getApp();
+ if ( !anApp )
+ {
+ return true;
+ }
+
+ SalomeApp_Study* aStudy = dynamic_cast( anApp->activeStudy() );
+ if ( !aStudy )
+ {
+ return true;
+ }
+
+ mySavedPropertyState =
+ aStudy->getObjectProperty( GEOM::sharedPropertiesId(),
+ myEditObject->GetStudyEntry(),
+ GEOM::propertyName( GEOM::Dimensions ),
+ QVariant() )
+ .value();
+
+ mySavedPropertyState.SaveToAttribute( aStudy, myEditObject->GetStudyEntry() );
+
+ return true;
+}
+
+//=================================================================================
+// function : OnFinish
+// purpose :
+//=================================================================================
+void MeasureGUI_ManageDimensionsDlg::OnFinish()
+{
+ if ( myEditObject.isNull() )
+ {
+ GEOMBase_Skeleton::ClickOnCancel();
+ return;
+ }
+
+ SalomeApp_Application* anApp = myGeomGUI->getApp();
+ if ( !anApp )
+ {
+ GEOMBase_Skeleton::ClickOnCancel();
+ return;
+ }
+
+ SalomeApp_Study* aStudy = dynamic_cast( anApp->activeStudy() );
+ if ( !aStudy )
+ {
+ GEOMBase_Skeleton::ClickOnCancel();
+ return;
+ }
+
+ // reset preview property state
+ aStudy->setObjectProperty( GEOM::sharedPropertiesId(),
+ myEditObject->GetStudyEntry(),
+ GEOM::propertyName( GEOM::Dimensions ),
+ QVariant() );
+
+ redisplay( myEditObject.get() );
+}
+
+//=================================================================================
+// function : SetEditObject
+// purpose :
+//=================================================================================
+void MeasureGUI_ManageDimensionsDlg::SetEditObject( const GEOM::GeomObjPtr& theObj )
+{
+ RestoreState();
+
+ QString aName = GEOMBase::GetName( theObj.get() );
+
+ myObjectSelector->LineEdit1->setText( aName );
+
+ myEditObject = theObj;
+
+ if ( myEditObject.isNull() )
+ {
+ myDimensionView->setEnabled( false );
+
+ return;
+ }
+
+ SalomeApp_Application* anApp = myGeomGUI->getApp();
+ if ( !anApp )
+ {
+ return;
+ }
+
+ SUIT_ViewManager* aViewMgr = anApp->activeViewManager();
+ if ( aViewMgr->getType() != SOCC_Viewer::Type() )
+ {
+ return;
+ }
+
+ SalomeApp_Study* aStudy = dynamic_cast( anApp->activeStudy() );
+ if ( !aStudy )
+ {
+ return;
+ }
+
+ mySavedPropertyState.LoadFromAttribute( getStudy(), myEditObject->GetStudyEntry() );
+
+ // set property state for preview
+ aStudy->setObjectProperty( GEOM::sharedPropertiesId(),
+ myEditObject->GetStudyEntry(),
+ GEOM::propertyName( GEOM::Dimensions ),
+ mySavedPropertyState );
+
+ PopulateList();
+
+ myDimensionView->setEnabled( true );
+}
+
+//=================================================================================
+// function : RestoreState
+// purpose :
+//=================================================================================
+void MeasureGUI_ManageDimensionsDlg::RestoreState()
+{
+ if ( myEditObject.isNull() )
+ {
+ return;
+ }
+
+ SalomeApp_Application* anApp = myGeomGUI->getApp();
+ if ( !anApp )
+ {
+ return;
+ }
+
+ SalomeApp_Study* aStudy = dynamic_cast( anApp->activeStudy() );
+ if ( !aStudy )
+ {
+ return;
+ }
+
+ QString aEntry = myEditObject->GetStudyEntry();
+
+ // reset preview property state
+ aStudy->setObjectProperty( GEOM::sharedPropertiesId(),
+ myEditObject->GetStudyEntry(),
+ GEOM::propertyName( GEOM::Dimensions ),
+ QVariant() );
+
+ RedisplayObject();
+}
+
+//=================================================================================
+// function : PopulateList
+// purpose :
+//=================================================================================
+void MeasureGUI_ManageDimensionsDlg::PopulateList()
+{
+ QTreeWidget* aListView = myDimensionView->TreeWidget;
+
+ // clear list completely if object is null
+ if ( myEditObject.isNull() )
+ {
+ aListView->clear();
+ return;
+ }
+
+ // clear only groups data if object is ok
+ QTreeWidgetItem* aDistanceGroupItem = aListView->topLevelItem( GroupItem_Distance );
+ QTreeWidgetItem* aDiameterGroupItem = aListView->topLevelItem( GroupItem_Diameter );
+ QTreeWidgetItem* anAngleGroupItem = aListView->topLevelItem( GroupItem_Angle );
+
+ // create group items if not exist yet
+ if ( !aDistanceGroupItem || !aDiameterGroupItem || !anAngleGroupItem )
+ {
+ aDistanceGroupItem = new QTreeWidgetItem( (QTreeWidget*)NULL, QStringList( tr( "DISTANCE_ITEM" ) ) );
+ aDiameterGroupItem = new QTreeWidgetItem( (QTreeWidget*)NULL, QStringList( tr( "DIAMETER_ITEM" ) ) );
+ anAngleGroupItem = new QTreeWidgetItem( (QTreeWidget*)NULL, QStringList( tr( "ANGLE_ITEM" ) ) );
+
+ aListView->clear();
+
+ aListView->addTopLevelItem( aDistanceGroupItem );
+ aListView->addTopLevelItem( aDiameterGroupItem );
+ aListView->addTopLevelItem( anAngleGroupItem );
+ aListView->expandAll();
+ }
+
+ qDeleteAll( aDistanceGroupItem->takeChildren() );
+ qDeleteAll( aDiameterGroupItem->takeChildren() );
+ qDeleteAll( anAngleGroupItem->takeChildren() );
+
+ // collect all groupped items
+ QList