Salome HOME
21854: Add persistent dimensions
authorapl <apl@opencascade.com>
Tue, 21 Jan 2014 12:51:45 +0000 (12:51 +0000)
committerapl <apl@opencascade.com>
Tue, 21 Jan 2014 12:51:45 +0000 (12:51 +0000)
- Final commit: help documents, preferences.

28 files changed:
doc/salome/gui/GEOM/images/add_dimension.png [new file with mode: 0644]
doc/salome/gui/GEOM/images/dialog.png
doc/salome/gui/GEOM/images/dimensions_preview.png [new file with mode: 0644]
doc/salome/gui/GEOM/images/pref15.png
doc/salome/gui/GEOM/input/add_dimension.doc [new file with mode: 0644]
doc/salome/gui/GEOM/input/geometry_preferences.doc
doc/salome/gui/GEOM/input/managing_dimensions.doc [new file with mode: 0644]
doc/salome/gui/GEOM/input/using_measurement_tools.doc
doc/salome/gui/GEOM/input/viewing_geom_obj.doc
resources/SalomeApp.xml.in
src/GEOMGUI/GEOMGUI_DimensionProperty.cxx
src/GEOMGUI/GEOMGUI_DimensionProperty.h
src/GEOMGUI/GEOMGUI_Selection.cxx
src/GEOMGUI/GEOMGUI_Selection.h
src/GEOMGUI/GEOM_Displayer.cxx
src/GEOMGUI/GEOM_msg_en.ts
src/GEOMGUI/GEOM_msg_fr.ts
src/GEOMGUI/GEOM_msg_ja.ts
src/GEOMGUI/GeometryGUI.cxx
src/GEOMGUI/GeometryGUI_Operations.h
src/MeasureGUI/MeasureGUI.cxx
src/MeasureGUI/MeasureGUI.h
src/MeasureGUI/MeasureGUI_CreateDimensionDlg.cxx
src/MeasureGUI/MeasureGUI_DimensionCreateTool.cxx
src/MeasureGUI/MeasureGUI_DimensionCreateTool.h
src/MeasureGUI/MeasureGUI_DimensionInteractor.cxx
src/MeasureGUI/MeasureGUI_ManageDimensionsDlg.cxx
src/MeasureGUI/MeasureGUI_ManageDimensionsDlg.h

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