0024389: Invalid hilight of AIS dimension line in local selection
authorapl <apl@opencascade.com>
Sat, 7 Dec 2013 10:07:41 +0000 (14:07 +0400)
committerabv <abv@opencascade.com>
Thu, 12 Dec 2013 15:36:47 +0000 (19:36 +0400)
- Fixed invalid presentation of dimension highlight.
- Fixed bug on switching between selection modes. Individual sensitive entities generated for each selection mode.
- Revised selection: AIS_DimensionSelectionMode enumeration added, redundant AIS_DimensionDisplayMode is removed.
- Revised entity owner usage: used standard SelectMgr_EntityOwner for neutral selection, AIS_DimensionOwner for "line", "text" selection modes.
- Made arrows selectable.
- Got rid of predefined arrow angle. The arrow angle is now taken from dimension aspect.
- The 3D text is now centered by bounding box for better alignment.

18 files changed:
src/AIS/AIS.cdl
src/AIS/AIS_AngleDimension.cxx
src/AIS/AIS_AngleDimension.hxx
src/AIS/AIS_DiameterDimension.cxx
src/AIS/AIS_DiameterDimension.hxx
src/AIS/AIS_Dimension.cxx
src/AIS/AIS_Dimension.hxx
src/AIS/AIS_DimensionOwner.cdl
src/AIS/AIS_DimensionOwner.cxx
src/AIS/AIS_LengthDimension.cxx
src/AIS/AIS_LengthDimension.hxx
src/AIS/AIS_RadiusDimension.cxx
src/Prs3d/Prs3d_DimensionAspect.cxx
tests/bugs/vis/bug24351_1
tests/bugs/vis/bug24351_2
tests/bugs/vis/bug24351_3
tests/bugs/vis/bug24351_4
tests/bugs/vis/bug24389 [new file with mode: 0644]

index 087521e..31bfd96 100755 (executable)
@@ -321,8 +321,8 @@ is
     enumeration DisplaySpecialSymbol is DSS_No, DSS_Before, DSS_After;
     ---Purpose: Specifies dimension special symbol display options
 
-    enumeration DimensionDisplayMode is DDM_All, DDM_Line, DDM_Text;
-    ---Purpose: Specifies dimension display modes for advanced highlighting and selection.
+    enumeration DimensionSelectionMode is DSM_All, DSM_Line, DSM_Text;
+    ---Purpose: Specifies dimension selection modes.
 
     class Triangulation;
 
index e9432be..c18b5f4 100755 (executable)
 #include <ElCLib.hxx>
 #include <gce_MakeLin2d.hxx>
 #include <gce_MakeCone.hxx>
+#include <gce_MakePln.hxx>
+#include <gce_MakeCirc.hxx>
+#include <gce_MakeDir.hxx>
+#include <GC_MakeArcOfCircle.hxx>
+#include <GCPnts_UniformAbscissa.hxx>
+#include <Geom_TrimmedCurve.hxx>
 #include <Geom_Circle.hxx>
 #include <Geom_ConicalSurface.hxx>
 #include <Geom_SurfaceOfRevolution.hxx>
@@ -53,8 +59,10 @@ IMPLEMENT_STANDARD_RTTIEXT (AIS_AngleDimension, AIS_Dimension)
 
 namespace
 {
-  static const TCollection_ExtendedString THE_EMPTY_LABEL;
-  static const Standard_ExtCharacter THE_DEGREE_SYMBOL (0x00B0);
+  static const TCollection_ExtendedString THE_EMPTY_LABEL_STRING;
+  static const Standard_Real              THE_EMPTY_LABEL_WIDTH = 0.0;
+  static const Standard_ExtCharacter      THE_DEGREE_SYMBOL (0x00B0);
+  static const Standard_Real              THE_3D_TEXT_MARGIN = 0.1;
 };
 
 //=======================================================================
@@ -305,6 +313,7 @@ Standard_Boolean AIS_AngleDimension::initTwoFacesAngle ()
   TopoDS_Face aSecondFace = TopoDS::Face (mySecondShape);
   gp_Dir aFirstDir, aSecondDir;
   gp_Pln aFirstPlane, aSecondPlane;
+  gp_Pnt aTextPos;
   Handle(Geom_Surface) aFirstBasisSurf, aSecondBasisSurf;
   AIS_KindOfSurface aFirstSurfType, aSecondSurfType;
   Standard_Real aFirstOffset, aSecondOffset;
@@ -323,7 +332,7 @@ Standard_Boolean AIS_AngleDimension::initTwoFacesAngle ()
                                         GetWorkingPlane().Axis(),
                                         myValue,
                                         Standard_True,
-                                        myGeom.myTextPosition,
+                                        aTextPos,
                                         myCenter,
                                         myFirstPoint,
                                         mySecondPoint,
@@ -343,7 +352,7 @@ Standard_Boolean AIS_AngleDimension::initTwoFacesAngle ()
                                              GetWorkingPlane().Axis(),
                                              myValue,
                                              Standard_True,
-                                             myGeom.myTextPosition,
+                                             aTextPos,
                                              myCenter,
                                              myFirstPoint,
                                              mySecondPoint,
@@ -572,67 +581,81 @@ void AIS_AngleDimension::drawArcWithText (const Handle(Prs3d_Presentation)& theP
                                           const gp_Pnt& theFirstAttach,
                                           const gp_Pnt& theSecondAttach,
                                           const TCollection_ExtendedString& theText,
-                                          const AIS_DimensionDisplayMode theMode,
+                                          const Standard_Real theTextWidth,
+                                          const Standard_Integer theMode,
                                           const Standard_Integer theLabelPosition)
 {
-  gp_Pnt2d aCenter2d       = ProjLib::Project (GetWorkingPlane(), myCenter),
-           aFirstAttach2d  = ProjLib::Project (GetWorkingPlane(), theFirstAttach),
-           aSecondAttach2d = ProjLib::Project (GetWorkingPlane(), theSecondAttach);
-  gp_Lin2d anAttachLine2d = gce_MakeLin2d (aFirstAttach2d, aSecondAttach2d);
-
-  // Getting text center
-  gp_Pnt2d aTextCenterPnt = ElCLib::Value ((ElCLib::Parameter (anAttachLine2d, aFirstAttach2d) + ElCLib::Parameter (anAttachLine2d, aSecondAttach2d)) / 2., anAttachLine2d);
-  gp_Lin2d aCenterToTextCenterLin = gce_MakeLin2d (aCenter2d, aTextCenterPnt);
+  // construct plane where the circle and the arc are located
+  gce_MakePln aConstructPlane (theFirstAttach, theSecondAttach, myCenter);
+  if (!aConstructPlane.IsDone())
+  {
+    return;
+  }
+  
+  gp_Pln aPlane = aConstructPlane.Value();
 
-  // Drawing circle
   Standard_Real aRadius = theFirstAttach.Distance (myCenter);
-  gp_Circ2d aCircle (gp_Ax22d (aCenter2d, gp_Dir2d (1, 0)), aRadius);
 
-  // Getting text position in the center of arc
-  IntAna2d_AnaIntersection anInt2d (aCenterToTextCenterLin, aCircle);
-  gp_Pnt2d aTextCenterOnArc2d;
-  if (anInt2d.IsDone())
-    if (!anInt2d.IsEmpty())
-      aTextCenterOnArc2d = gp_Pnt2d (anInt2d.Point (1).Value());
-  myGeom.myTextPosition = ElCLib::To3d (GetWorkingPlane().Position().Ax2(), aTextCenterOnArc2d);
+  // construct circle forming the arc
+  gce_MakeCirc aConstructCircle (myCenter, aPlane, aRadius);
+  if (!aConstructCircle.IsDone())
+  {
+    return;
+  }
 
-  // Drawing text
-  gp_Vec aVec (theFirstAttach, theSecondAttach);
-  Standard_Real aTextWidth = drawText (thePresentation,
-                                       myIsTextReversed ? aVec.Reversed() : aVec,
-                                       theText, theMode,
-                                       theLabelPosition);
+  gp_Circ aCircle = aConstructCircle.Value();
 
-  // Getting text begin and end points
-  gp_Pnt2d aTextBeginPnt = ElCLib::Value ((ElCLib::Parameter (anAttachLine2d, aFirstAttach2d) +
-                                           ElCLib::Parameter (anAttachLine2d, aSecondAttach2d) -
-                                           aTextWidth) / 2., anAttachLine2d),
-           aTextEndPnt   = ElCLib::Value (ElCLib::Parameter (anAttachLine2d,aTextBeginPnt) + aTextWidth, anAttachLine2d);
+  // compute angle parameters of arc end-points on circle
+  Standard_Real aParamBeg = ElCLib::Parameter (aCircle, theFirstAttach);
+  Standard_Real aParamEnd = ElCLib::Parameter (aCircle, theSecondAttach);
+  ElCLib::AdjustPeriodic (aParamBeg, aParamEnd,
+                          Precision::PConfusion(),
+                          aParamBeg, aParamEnd);
 
+  // middle point of arc parameter on circle
+  Standard_Real aParamMid = (aParamBeg + aParamEnd) * 0.5;
 
-  gp_Lin2d aCenterToTextBeginLin = gce_MakeLin2d (aCenter2d, aTextBeginPnt),
-           aCenterToTextEndLin   = gce_MakeLin2d (aCenter2d, aTextEndPnt);
+  // add text graphical primitives
+  if (theMode == ComputeMode_All || theMode == ComputeMode_Text)
+  {
+    gp_Pnt aTextPos = ElCLib::Value (aParamMid, aCircle);
+    gp_Dir aTextDir = IsTextReversed()
+      ? gce_MakeDir (theSecondAttach, theFirstAttach)
+      : gce_MakeDir (theFirstAttach, theSecondAttach);
+
+    // Drawing text
+    drawText (thePresentation,
+              aTextPos,
+              aTextDir,
+              theText,
+              theLabelPosition);
+  }
 
-  // Text begin and end on the dimension arc
-  gp_Pnt2d aTextBeginOnArc2d, aTextEndOnArc2d;
-  anInt2d.Perform (aCenterToTextBeginLin, aCircle);
-  if (anInt2d.IsDone())
-    if (!anInt2d.IsEmpty())
-      aTextBeginOnArc2d = gp_Pnt2d (anInt2d.Point (1).Value());
+  if (theMode != ComputeMode_All && theMode != ComputeMode_Line)
+  {
+    return;
+  }
 
-  anInt2d.Perform (aCenterToTextEndLin, aCircle);
-  if (anInt2d.IsDone())
-    if (!anInt2d.IsEmpty())
-      aTextEndOnArc2d = gp_Pnt2d (anInt2d.Point (1).Value());
+  Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
 
-  gp_Pnt aTextBeginOnArc = ElCLib::To3d (GetWorkingPlane().Position().Ax2(), aTextBeginOnArc2d);
-  gp_Pnt aTextEndOnArc   = ElCLib::To3d (GetWorkingPlane().Position().Ax2(), aTextEndOnArc2d);
+  Standard_Boolean isLineBreak = aDimensionAspect->TextVerticalPosition() == Prs3d_DTVP_Center
+                              && aDimensionAspect->IsText3d();
 
-  // Drawing arcs
-  if (theMode != AIS_DDM_Text)
+  if (isLineBreak)
   {
-    drawArc (thePresentation, theFirstAttach, aTextBeginOnArc, myCenter, aRadius, theMode);
-    drawArc (thePresentation, aTextEndOnArc, theSecondAttach, myCenter, aRadius, theMode);
+    // compute gap for label as parameteric size of sector on circle segment
+    Standard_Real aSectorOnCircle = theTextWidth / aRadius;
+  
+    gp_Pnt aTextPntBeg = ElCLib::Value (aParamMid - aSectorOnCircle * 0.5, aCircle);
+    gp_Pnt aTextPntEnd = ElCLib::Value (aParamMid + aSectorOnCircle * 0.5, aCircle);
+
+    // Drawing arcs
+    drawArc (thePresentation, theFirstAttach, aTextPntBeg, myCenter, aRadius, theMode);
+    drawArc (thePresentation, theSecondAttach, aTextPntEnd, myCenter, aRadius, theMode);
+  }
+  else
+  {
+    drawArc (thePresentation, theFirstAttach, theSecondAttach, myCenter, aRadius, theMode);
   }
 }
 
@@ -645,48 +668,74 @@ void AIS_AngleDimension::drawArc (const Handle(Prs3d_Presentation)& thePresentat
                                   const gp_Pnt& theSecondAttach,
                                   const gp_Pnt& theCenter,
                                   const Standard_Real theRadius,
-                                  const AIS_DimensionDisplayMode theMode)
+                                  const Standard_Integer theMode)
 {
-  Handle(SelectMgr_EntityOwner) anEmptyOwner;
+  // construct plane where the circle and the arc are located
+  gce_MakePln aConstructPlane (theFirstAttach, theSecondAttach, theCenter);
+  if (!aConstructPlane.IsDone())
+  {
+    return;
+  }
+
+  gp_Pln aPlane = aConstructPlane.Value();
+
+  // construct circle forming the arc
+  gce_MakeCirc aConstructCircle (theCenter, aPlane, theRadius);
+  if (!aConstructCircle.IsDone())
+  {
+    return;
+  }
+
+  gp_Circ aCircle = aConstructCircle.Value();
 
-  gp_Vec aCenterToFirstVec (theCenter,theFirstAttach);
-  gp_Vec aCenterToSecondVec (theCenter,theSecondAttach);
-  gp_Dir aCenterToFirstDir (aCenterToFirstVec);
-  gp_Dir aPlaneNormal = GetWorkingPlane().Axis().Direction();
-  gp_Dir aCenterToSecondDir = aPlaneNormal.Crossed (aCenterToFirstDir);
+  // construct the arc
+  GC_MakeArcOfCircle aConstructArc (aCircle, theFirstAttach, theSecondAttach, Standard_True);
+  if (!aConstructArc.IsDone())
+  {
+    return;
+  }
+
+  // generate points with specified deflection
+  const Handle(Geom_TrimmedCurve)& anArcCurve = aConstructArc.Value();
+  
+  GeomAdaptor_Curve anArcAdaptor (anArcCurve, anArcCurve->FirstParameter(), anArcCurve->LastParameter());
 
-  const Standard_Real anAngle = aCenterToFirstVec.Angle(aCenterToSecondVec);
-  const Standard_Integer aPointsOnArc = Max (4 , Standard_Integer (50. * anAngle / M_PI));
-  const Standard_Real anAngleStep = anAngle / (aPointsOnArc - 1);
-  TColgp_Array1OfPnt aPointArray (0,aPointsOnArc-1);
-  Handle(Graphic3d_ArrayOfPolylines) aPrimSegments = new Graphic3d_ArrayOfPolylines (aPointsOnArc,2);
-  aPrimSegments->AddVertex (theFirstAttach);
-  aPointArray.SetValue(0, theFirstAttach);
-  gp_Pnt aPoint = theFirstAttach;
-  gp_Vec aVector;
+  // compute number of discretization elements in old-fanshioned way
+  gp_Vec aCenterToFirstVec  (theCenter, theFirstAttach);
+  gp_Vec aCenterToSecondVec (theCenter, theSecondAttach);
+  const Standard_Real anAngle = aCenterToFirstVec.Angle (aCenterToSecondVec);
+  const Standard_Integer aNbPoints = Max (4, Standard_Integer (50.0 * anAngle / M_PI));
 
-  for (Standard_Integer anI = 1; anI < aPointsOnArc - 1; ++anI)
+  GCPnts_UniformAbscissa aMakePnts (anArcAdaptor, aNbPoints);
+  if (!aMakePnts.IsDone())
   {
-    aVector = (gp_Vec(aCenterToFirstDir) * Cos ( (anI - 1) * anAngleStep) + gp_Vec(aCenterToSecondDir) * Sin ( (anI - 1) * anAngleStep)) * theRadius;
-    aPoint = theCenter.Translated(aVector);
-    aPrimSegments->AddVertex(aPoint);
-    aPointArray.SetValue (anI,aPoint);
+    return;
   }
-  aPrimSegments->AddVertex (theSecondAttach);
-  aPointArray.SetValue (aPointsOnArc - 1,theSecondAttach);
 
-  // Fill sensitive list
-  myGeom.mySensitiveSegments.Append(new Select3D_SensitiveCurve(anEmptyOwner,aPointArray));
+  // init data arrays for graphical and selection primitives
+  Handle(Graphic3d_ArrayOfPolylines) aPrimSegments = new Graphic3d_ArrayOfPolylines (aNbPoints);
+
+  SelectionGeometry::Curve& aSensitiveCurve = mySelectionGeom.NewCurve();
 
-  // Fill display presentation
-  if (!myDrawer->DimensionAspect()->IsText3d() && theMode == AIS_DDM_All)
+  // load data into arrays
+  for (Standard_Integer aPntIt = 1; aPntIt <= aMakePnts.NbPoints(); ++aPntIt)
+  {
+    gp_Pnt aPnt = anArcAdaptor.Value (aMakePnts.Parameter (aPntIt));
+
+    aPrimSegments->AddVertex (aPnt);
+
+    aSensitiveCurve.Append (aPnt);
+  }
+
+  // add display presentation
+  if (!myDrawer->DimensionAspect()->IsText3d() && theMode == ComputeMode_All)
   {
     Prs3d_Root::CurrentGroup (thePresentation)->SetStencilTestOptions (Standard_True);
   }
   Handle(Graphic3d_AspectLine3d) aDimensionLineStyle = myDrawer->DimensionAspect()->LineAspect()->Aspect();
   Prs3d_Root::CurrentGroup (thePresentation)->SetPrimitivesAspect (aDimensionLineStyle);
   Prs3d_Root::CurrentGroup (thePresentation)->AddPrimitiveArray (aPrimSegments);
-  if (!myDrawer->DimensionAspect()->IsText3d() && theMode == AIS_DDM_All)
+  if (!myDrawer->DimensionAspect()->IsText3d() && theMode == ComputeMode_All)
   {
     Prs3d_Root::CurrentGroup (thePresentation)->SetStencilTestOptions (Standard_False);
   }
@@ -701,7 +750,7 @@ void AIS_AngleDimension::Compute (const Handle(PrsMgr_PresentationManager3d)& /*
                                   const Standard_Integer theMode)
 {
   thePresentation->Clear();
-  myGeom.mySensitiveSegments.Clear();
+  mySelectionGeom.Clear (theMode);
   Handle(SelectMgr_EntityOwner) anEmptyOwner;
 
   if (!myIsInitialized)
@@ -752,6 +801,12 @@ void AIS_AngleDimension::Compute (const Handle(PrsMgr_PresentationManager3d)& /*
   Standard_Real aTextLength;
   getTextWidthAndString (aTextLength, aValueString);
 
+  // add margins to label width
+  if (aDimensionAspect->IsText3d())
+  {
+    aTextLength += aDimensionAspect->TextAspect()->Height() * THE_3D_TEXT_MARGIN * 2.0;
+  }
+
   if (!myIsWorkingPlaneCustom)
   {
     countDefaultPlane();
@@ -770,7 +825,13 @@ void AIS_AngleDimension::Compute (const Handle(PrsMgr_PresentationManager3d)& /*
     {
       gp_Vec anAttachVector (aFirstAttach, aSecondAttach);
       Standard_Real aDimensionWidth = anAttachVector.Magnitude();
-      Standard_Real anArrowsWidth   = anArrowLength * 2.0;
+
+      // add margin to ensure a small tail between text and arrow
+      Standard_Real anArrowMargin   = aDimensionAspect->IsText3d() 
+                                    ? aDimensionAspect->TextAspect()->Height() * THE_3D_TEXT_MARGIN
+                                    : 0.0;
+
+      Standard_Real anArrowsWidth   = (anArrowLength + anArrowMargin) * 2.0;
 
       isArrowsExternal = aDimensionWidth < aTextLength + anArrowsWidth;
       break;
@@ -850,31 +911,35 @@ void AIS_AngleDimension::Compute (const Handle(PrsMgr_PresentationManager3d)& /*
                          aFirstAttach,
                          aSecondAttach,
                          aValueString,
-                         (AIS_DimensionDisplayMode)theMode,
+                         aTextLength,
+                         theMode,
                          aLabelPosition);
         break;
       }
 
-      gp_Vec aTextDir (aFirstArrowEnd, aSecondArrowBegin);
-      myGeom.myTextPosition = getCenterOnArc (aFirstArrowEnd, aSecondArrowBegin);
-
-      drawText (thePresentation,
-                myIsTextReversed ? aTextDir.Reversed() : aTextDir,
-                aValueString,
-                (AIS_DimensionDisplayMode)theMode,
-                aLabelPosition);
-
-      if (theMode == AIS_DDM_Text)
+      // compute text primitives
+      if (theMode == ComputeMode_All || theMode == ComputeMode_Text)
       {
-        break;
+        gp_Vec aDimensionDir (aFirstArrowEnd, aSecondArrowBegin);
+        gp_Pnt aTextPos = getCenterOnArc (aFirstArrowEnd, aSecondArrowBegin);
+        gp_Dir aTextDir = myIsTextReversed ? aDimensionDir.Reversed() : aDimensionDir;
+
+        drawText (thePresentation,
+                  aTextPos,
+                  aTextDir,
+                  aValueString,
+                  aLabelPosition);
       }
 
-      drawArc (thePresentation,
-               isArrowsExternal ? aFirstAttach : aFirstArrowEnd,
-               isArrowsExternal ? aSecondAttach : aSecondArrowEnd,
-               myCenter,
-               Abs (GetFlyout()),
-               (AIS_DimensionDisplayMode)theMode);
+      if (theMode == ComputeMode_All || theMode == ComputeMode_Line)
+      {
+        drawArc (thePresentation,
+                 isArrowsExternal ? aFirstAttach : aFirstArrowEnd,
+                 isArrowsExternal ? aSecondAttach : aSecondArrowEnd,
+                 myCenter,
+                 Abs (GetFlyout()),
+                 theMode);
+      }
     }
     break;
 
@@ -885,7 +950,8 @@ void AIS_AngleDimension::Compute (const Handle(PrsMgr_PresentationManager3d)& /*
                      isArrowsExternal ? aFirstArrowEnd : aFirstAttach,
                      aFirstExtensionDir,
                      aValueString,
-                     (AIS_DimensionDisplayMode)theMode,
+                     aTextLength,
+                     theMode,
                      aLabelPosition);
     }
     break;
@@ -897,14 +963,15 @@ void AIS_AngleDimension::Compute (const Handle(PrsMgr_PresentationManager3d)& /*
                      isArrowsExternal ? aSecondArrowEnd : aSecondAttach,
                      aSecondExtensionDir,
                      aValueString,
-                     (AIS_DimensionDisplayMode)theMode,
+                     aTextLength,
+                     theMode,
                      aLabelPosition);
     }
     break;
   }
 
   // dimension arc without text
-  if (theMode != AIS_DDM_Text && aHPosition != LabelPosition_HCenter)
+  if ((theMode == ComputeMode_All || theMode == ComputeMode_Line) && aHPosition != LabelPosition_HCenter)
   {
     Prs3d_Root::NewGroup (thePresentation);
 
@@ -913,11 +980,11 @@ void AIS_AngleDimension::Compute (const Handle(PrsMgr_PresentationManager3d)& /*
              isArrowsExternal ? aSecondAttach : aSecondArrowEnd,
              myCenter,
              Abs(GetFlyout ()),
-             (AIS_DimensionDisplayMode)theMode);
+             theMode);
   }
 
   // arrows and arrow extensions
-  if (theMode != AIS_DDM_Text)
+  if (theMode == ComputeMode_All || theMode == ComputeMode_Line)
   {
     Prs3d_Root::NewGroup (thePresentation);
 
@@ -925,7 +992,7 @@ void AIS_AngleDimension::Compute (const Handle(PrsMgr_PresentationManager3d)& /*
     drawArrow (thePresentation, aSecondArrowBegin, gp_Dir (aSecondArrowVec));
   }
 
-  if (theMode != AIS_DDM_Text && isArrowsExternal)
+  if ((theMode == ComputeMode_All || theMode == ComputeMode_Line) && isArrowsExternal)
   {
     Prs3d_Root::NewGroup (thePresentation);
 
@@ -935,8 +1002,9 @@ void AIS_AngleDimension::Compute (const Handle(PrsMgr_PresentationManager3d)& /*
                      anExtensionSize,
                      aFirstArrowEnd,
                      aFirstExtensionDir,
-                     THE_EMPTY_LABEL,
-                     (AIS_DimensionDisplayMode)theMode,
+                     THE_EMPTY_LABEL_STRING,
+                     THE_EMPTY_LABEL_WIDTH,
+                     theMode,
                      LabelPosition_None);
     }
 
@@ -946,14 +1014,15 @@ void AIS_AngleDimension::Compute (const Handle(PrsMgr_PresentationManager3d)& /*
                      anExtensionSize,
                      aSecondArrowEnd,
                      aSecondExtensionDir,
-                     THE_EMPTY_LABEL,
-                     (AIS_DimensionDisplayMode)theMode,
+                     THE_EMPTY_LABEL_STRING,
+                     THE_EMPTY_LABEL_WIDTH,
+                     theMode,
                      LabelPosition_None);
     }
   }
 
   // flyouts
-  if (theMode == AIS_DDM_All && myIsFlyoutLines)
+  if (theMode == ComputeMode_All && myIsFlyoutLines)
   {
     Prs3d_Root::NewGroup (thePresentation);
 
@@ -976,17 +1045,19 @@ void AIS_AngleDimension::Compute (const Handle(PrsMgr_PresentationManager3d)& /*
 //purpose  : computes selection for flyouts
 //=======================================================================
 void AIS_AngleDimension::computeFlyoutSelection (const Handle(SelectMgr_Selection)& theSelection,
-                                                const Handle(AIS_DimensionOwner)& theOwner)
+                                                 const Handle(SelectMgr_EntityOwner)& theOwner)
 {
- if (!myIsFlyoutLines)
- {
-   return;
- }
-
- gp_Pnt aFirstAttach = myCenter.Translated (gp_Vec (myCenter, myFirstPoint).Normalized() * GetFlyout());
- gp_Pnt aSecondAttach = myCenter.Translated (gp_Vec (myCenter, mySecondPoint).Normalized() * GetFlyout());
- Handle(Select3D_SensitiveGroup) aSensitiveEntity = new Select3D_SensitiveGroup (theOwner);
- aSensitiveEntity->Add (new Select3D_SensitiveSegment (theOwner, myCenter, aFirstAttach));
- aSensitiveEntity->Add (new Select3D_SensitiveSegment (theOwner, myCenter, aSecondAttach));
- theSelection->Add (aSensitiveEntity);
+  if (!myIsFlyoutLines)
+  {
+    return;
+  }
+
+  gp_Pnt aFirstAttach  = myCenter.Translated (gp_Vec (myCenter, myFirstPoint).Normalized()  * GetFlyout());
+  gp_Pnt aSecondAttach = myCenter.Translated (gp_Vec (myCenter, mySecondPoint).Normalized() * GetFlyout());
+
+  Handle(Select3D_SensitiveGroup) aSensitiveEntity = new Select3D_SensitiveGroup (theOwner);
+  aSensitiveEntity->Add (new Select3D_SensitiveSegment (theOwner, myCenter, aFirstAttach));
+  aSensitiveEntity->Add (new Select3D_SensitiveSegment (theOwner, myCenter, aSecondAttach));
+
+  theSelection->Add (aSensitiveEntity);
 }
index 805d651..3c9d702 100644 (file)
@@ -101,13 +101,14 @@ protected:
                                  const gp_Pnt& theSecondAttach,
                                  const gp_Pnt& theCenter,
                                  const Standard_Real theRadius,
-                                 const AIS_DimensionDisplayMode theMode);
+                                 const Standard_Integer theMode);
 
   Standard_EXPORT  void drawArcWithText (const Handle(Prs3d_Presentation)& thePresentation,
                                          const gp_Pnt& theFirstAttach,
                                          const gp_Pnt& theSecondAttach,
                                          const TCollection_ExtendedString& theText,
-                                         const AIS_DimensionDisplayMode theMode,
+                                         const Standard_Real theTextWidth,
+                                         const Standard_Integer theMode,
                                          const Standard_Integer theLabelPosition);
 
   Standard_EXPORT  virtual void Compute (const Handle(PrsMgr_PresentationManager3d)& thePM,
@@ -134,7 +135,7 @@ protected:
   
  //! Fills sensitive entity for flyouts and adds it to the selection
  Standard_EXPORT virtual void computeFlyoutSelection (const Handle(SelectMgr_Selection)& theSelection,
-                                                      const Handle(AIS_DimensionOwner)& theOwner);
+                                                      const Handle(SelectMgr_EntityOwner)& theOwner);
 
 protected:
 
index ef31b02..e420737 100755 (executable)
@@ -108,6 +108,7 @@ void AIS_DiameterDimension::Compute (const Handle(PrsMgr_PresentationManager3d)&
                                      const Standard_Integer theMode)
 {
   thePresentation->Clear();
+  mySelectionGeom.Clear (theMode);
 
   Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
   Prs3d_Root::CurrentGroup (thePresentation)->SetPrimitivesAspect (aDimensionAspect->LineAspect()->Aspect());
@@ -126,7 +127,7 @@ void AIS_DiameterDimension::Compute (const Handle(PrsMgr_PresentationManager3d)&
    countDefaultPlane();
   }
 
-  drawLinearDimension (thePresentation, (AIS_DimensionDisplayMode)theMode);
+  drawLinearDimension (thePresentation, theMode);
 }
 
 //=======================================================================
index 1842759..efc186a 100644 (file)
@@ -42,7 +42,8 @@ public:
   //! Constructs a diameter display object defined by the <br>
   //! circle <theCircle>
   Standard_EXPORT  AIS_DiameterDimension(const gp_Circ& theCircle);
-  //! Consctructor that allows to set a attach point <br>
+
+  //! Constructor that allows to set a attach point <br>
   //! on the circle <theCircle> where to attach dimension
   Standard_EXPORT  AIS_DiameterDimension (const gp_Circ& theCircle,
                                           const gp_Pnt& theAttachPoint);
index b6d38d9..c0639ee 100644 (file)
 #include <AIS_Dimension.hxx>
 
 #include <AIS.hxx>
-#include <AIS_DimensionDisplayMode.hxx>
 #include <AIS_DimensionOwner.hxx>
 #include <AIS_Drawer.hxx>
 #include <Adaptor3d_HCurve.hxx>
 #include <BRepAdaptor_Curve.hxx>
 #include <BRepAdaptor_Surface.hxx>
-#include <BRepBuilderAPI_MakeEdge.hxx>
-#include <BRepLib_MakeVertex.hxx>
 #include <BRepBndLib.hxx>
-#include <GeomAdaptor_Curve.hxx>
 #include <ElCLib.hxx>
 #include <Font_BRepFont.hxx>
 #include <GC_MakeCircle.hxx>
+#include <GeomAdaptor_Curve.hxx>
 #include <Geom_Circle.hxx>
-#include <Geom_Plane.hxx>
 #include <Geom_TrimmedCurve.hxx>
 #include <gce_MakeDir.hxx>
 #include <gce_MakeLin.hxx>
 #include <SelectMgr_SequenceOfOwner.hxx>
 #include <Select3D_ListIteratorOfListOfSensitive.hxx>
 #include <Select3D_ListOfSensitive.hxx>
-#include <Select3D_SensitiveBox.hxx>
 #include <Select3D_SensitiveCircle.hxx>
 #include <Select3D_SensitiveGroup.hxx>
+#include <Select3D_SensitiveCurve.hxx>
 #include <Select3D_SensitiveSegment.hxx>
+#include <Select3D_SensitiveFace.hxx>
+#include <Select3D_SensitiveTriangle.hxx>
 #include <Standard_CString.hxx>
 #include <StdPrs_ShadedShape.hxx>
 #include <StdPrs_WFShape.hxx>
@@ -78,9 +76,17 @@ IMPLEMENT_STANDARD_RTTIEXT(AIS_Dimension, AIS_InteractiveObject)
 
 namespace
 {
+  // default text strings
   static const Standard_Utf32Char THE_FILL_CHARACTER ('0');
   static const TCollection_ExtendedString THE_EMPTY_LABEL;
-  static const Standard_Real THE_3D_TEXT_MARGIN = 0.1;
+
+  // default text margin and resolution
+  static const Standard_Real THE_3D_TEXT_MARGIN    = 0.1;
+  static const unsigned int  THE_2D_TEXT_RESOLUTION = 72;
+
+  // default selection priorities
+  static const Standard_Integer THE_NEUTRAL_SEL_PRIORITY = 5;
+  static const Standard_Integer THE_LOCAL_SEL_PRIORITY   = 6;
 };
 
 //=======================================================================
@@ -115,7 +121,7 @@ AIS_Dimension::AIS_Dimension()
 //=======================================================================
 Standard_Boolean AIS_Dimension::AcceptDisplayMode (const Standard_Integer theMode) const
 {
-  return theMode == 0 ? Standard_True : Standard_False;
+  return theMode == ComputeMode_All;
 }
 
 //=======================================================================
@@ -279,21 +285,37 @@ void AIS_Dimension::getTextWidthAndString (Quantity_Length& theWidth,
   Standard_Real aFactor;
   Standard_Real aSpace;
   myDrawer->DimensionAspect()->TextAspect()->Aspect()->Values (aColor, aFontName, aFactor, aSpace);
-  // Init font instance
-  Handle(Font_FTFont) aFont = new Font_FTFont ();
-  aFont->Init (aFontName,
-               myDrawer->DimensionAspect()->TextAspect()->Aspect()->GetTextFontAspect(),
-               (Standard_Integer) myDrawer->DimensionAspect()->TextAspect()->Height(), 72);
-
-  TCollection_ExtendedString aString (theString);
-  aString += ".";
-  Standard_PCharacter aUtf8String = new Standard_Character[aString.Length()];
-  Standard_Integer aStrLength = aString.ToUTF8CString(aUtf8String);
+  Font_FontAspect aFontAspect = myDrawer->DimensionAspect()->TextAspect()->Aspect()->GetTextFontAspect();
+  Standard_Real   aFontHeight = myDrawer->DimensionAspect()->TextAspect()->Height();
+
+  NCollection_Utf8String anUTFString = (Standard_Utf16Char* )theString.ToExtString();
+
   theWidth = 0.0;
-  for (Standard_Integer anIt = 0; anIt < aStrLength - 1; ++anIt)
+
+  if (myDrawer->DimensionAspect()->IsText3d())
+  {
+    // text width produced by BRepFont
+    Font_BRepFont aFont (aFontName, aFontAspect, aFontHeight);
+
+    for (NCollection_Utf8Iter anIter = anUTFString.Iterator(); *anIter != 0; )
+    {
+      Standard_Utf32Char aCurrChar = *anIter;
+      Standard_Utf32Char aNextChar = *(++anIter);
+      theWidth += aFont.AdvanceX (aCurrChar, aNextChar);
+    }
+  }
+  else
   {
-    Standard_Real anAdvance = aFont->AdvanceX (aUtf8String[anIt], aUtf8String[anIt + 1]);
-    theWidth += anAdvance;
+    // Text width for 1:1 scale 2D case
+    Handle(Font_FTFont) aFont = new Font_FTFont ();
+    aFont->Init (aFontName, aFontAspect, (const unsigned int)aFontHeight, THE_2D_TEXT_RESOLUTION);
+
+    for (NCollection_Utf8Iter anIter = anUTFString.Iterator(); *anIter != 0; )
+    {
+      Standard_Utf32Char aCurrChar = *anIter;
+      Standard_Utf32Char aNextChar = *(++anIter);
+      theWidth += (Standard_Real) aFont->AdvanceX (aCurrChar, aNextChar);
+    }
   }
 }
 
@@ -306,23 +328,27 @@ void AIS_Dimension::drawArrow (const Handle(Prs3d_Presentation)& thePresentation
                                const gp_Dir& theDirection)
 {
   Prs3d_Root::NewGroup (thePresentation);
-  Quantity_Length anArrowLength = myDrawer->DimensionAspect()->ArrowAspect()->Length();
+
+  Quantity_Length aLength = myDrawer->DimensionAspect()->ArrowAspect()->Length();
+  Standard_Real   anAngle = myDrawer->DimensionAspect()->ArrowAspect()->Angle();
 
   if (myDrawer->DimensionAspect()->IsArrows3d())
   {
     Prs3d_Arrow::Draw (thePresentation,
                        theLocation,
                        theDirection,
-                       myDrawer->DimensionAspect()->ArrowAspect()->Angle(),
-                       anArrowLength);
+                       anAngle,
+                       aLength);
   }
   else
   {
-    gp_Vec aBackDir (theDirection.Reversed());
-    Quantity_Length theCathetusLength = anArrowLength / Cos (M_PI / 9.0);
+    gp_Pnt aLeftPoint (gp::Origin());
+    gp_Pnt aRightPoint (gp::Origin());
+    const gp_Dir& aPlane = myWorkingPlane.Axis().Direction();
+
+    PointsForArrow (theLocation, theDirection, aPlane, aLength, anAngle, aLeftPoint, aRightPoint);
+
     Handle(Graphic3d_ArrayOfTriangles) anArrow = new Graphic3d_ArrayOfTriangles(3);
-    gp_Pnt aLeftPoint (theLocation.Translated (aBackDir.Rotated (myWorkingPlane.Axis(), M_PI / 9.0) * theCathetusLength));
-    gp_Pnt aRightPoint (theLocation.Translated (aBackDir.Rotated (myWorkingPlane.Axis(), M_PI * 17.0 / 9.0) * theCathetusLength));
 
     anArrow->AddVertex (aLeftPoint);
     anArrow->AddVertex (theLocation);
@@ -345,55 +371,57 @@ void AIS_Dimension::drawArrow (const Handle(Prs3d_Presentation)& thePresentation
     Prs3d_Root::CurrentGroup (thePresentation)->SetPrimitivesAspect (aShadingStyle->Aspect());
     Prs3d_Root::CurrentGroup (thePresentation)->AddPrimitiveArray (anArrow);
   }
+
+  SelectionGeometry::Arrow& aSensitiveArrow = mySelectionGeom.NewArrow();
+  aSensitiveArrow.Position  = theLocation;
+  aSensitiveArrow.Direction = theDirection;
 }
 
 //=======================================================================
 //function : drawText
 //purpose  : 
 //=======================================================================
-Standard_Real AIS_Dimension::drawText (const Handle(Prs3d_Presentation)& thePresentation,
-                                       const gp_Dir& theTextDir,
-                                       const TCollection_ExtendedString theText,
-                                       const AIS_DimensionDisplayMode theMode,
-                                       const Standard_Integer theLabelPosition)
+void AIS_Dimension::drawText (const Handle(Prs3d_Presentation)& thePresentation,
+                              const gp_Pnt& theTextPos,
+                              const gp_Dir& theTextDir,
+                              const TCollection_ExtendedString& theText,
+                              const Standard_Integer theLabelPosition)
 {
-  Standard_Real aTextWidth (0.0), aTextHeight (0.0);
-  if (theMode == AIS_DDM_Line)
-  {
-    return 0.0;
-  }
-
   if (myDrawer->DimensionAspect()->IsText3d())
   {
-    // Getting font parameters
+    // getting font parameters
     Quantity_Color aColor;
     Standard_CString aFontName;
     Standard_Real anExpansionFactor;
     Standard_Real aSpace;
     myDrawer->DimensionAspect()->TextAspect()->Aspect()->Values (aColor, aFontName, anExpansionFactor, aSpace);
     Font_FontAspect aFontAspect = myDrawer->DimensionAspect()->TextAspect()->Aspect()->GetTextFontAspect();
-    Standard_Real aHeight = myDrawer->DimensionAspect()->TextAspect()->Height();
+    Standard_Real aFontHeight = myDrawer->DimensionAspect()->TextAspect()->Height();
 
-    // Creating TopoDS_Shape for text
-    Font_BRepFont aFont (aFontName, aFontAspect, aHeight);
-    NCollection_String aText = (Standard_Utf16Char* )theText.ToExtString();
-    TopoDS_Shape aTextShape = aFont.RenderText (aText);
+    // creating TopoDS_Shape for text
+    Font_BRepFont aFont (aFontName, aFontAspect, aFontHeight);
+    NCollection_Utf8String anUTFString = (Standard_Utf16Char* )theText.ToExtString();
+    TopoDS_Shape aTextShape = aFont.RenderText (anUTFString);
 
-    // Formating text position in XOY plane
-    Bnd_Box aTextBndBox;
-    BRepBndLib::AddClose (aTextShape, aTextBndBox);
-    Standard_Real aXMin, anYMin, aZMin, aXMax, anYMax, aZMax;
-    aTextBndBox.Get (aXMin, anYMin, aZMin, aXMax, anYMax, aZMax);
-    aTextWidth  = aXMax  - aXMin;
-    aTextHeight = anYMax - anYMin;
+    // compute text width with kerning
+    Standard_Real aTextWidth  = 0.0;
+    Standard_Real aTextHeight = aFont.Ascender() + aFont.Descender();
 
+    for (NCollection_Utf8Iter anIter = anUTFString.Iterator(); *anIter != 0; )
+    {
+      Standard_Utf32Char aCurrChar = *anIter;
+      Standard_Utf32Char aNextChar = *(++anIter);
+      aTextWidth += aFont.AdvanceX (aCurrChar, aNextChar);
+    }
+
+    // formating text position in XOY plane
     Standard_Integer aHLabelPos = theLabelPosition & LabelPosition_HMask;
     Standard_Integer aVLabelPos = theLabelPosition & LabelPosition_VMask;
 
     gp_Dir aTextDir (aHLabelPos == LabelPosition_Left ? -theTextDir : theTextDir);
 
     // compute label offsets
-    Standard_Real aMarginSize    = aHeight * THE_3D_TEXT_MARGIN;
+    Standard_Real aMarginSize    = aFontHeight * THE_3D_TEXT_MARGIN;
     Standard_Real aCenterHOffset = 0.0;
     Standard_Real aCenterVOffset = 0.0;
     switch (aHLabelPos)
@@ -410,35 +438,44 @@ Standard_Real AIS_Dimension::drawText (const Handle(Prs3d_Presentation)& thePres
     }
 
     // compute shape offset transformation
-    Standard_Real aShapeHOffset = aCenterHOffset -  aTextWidth / 2.0;
+    Standard_Real aShapeHOffset = aCenterHOffset - aTextWidth / 2.0;
     Standard_Real aShapeVOffset = aCenterVOffset - aTextHeight / 2.0;
 
+    // center shape in its bounding box (suppress border spacing added by FT_Font)
+    Bnd_Box aShapeBnd;
+    BRepBndLib::AddClose (aTextShape, aShapeBnd);
+
+    Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
+    aShapeBnd.Get (aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
+
+    Standard_Real aXalign = aTextWidth  * 0.5 - (aXmax + aXmin) * 0.5;
+    Standard_Real aYalign = aTextHeight * 0.5 - (aYmax + aYmin) * 0.5;
+    aShapeHOffset += aXalign;
+    aShapeVOffset += aYalign;
+
     gp_Trsf anOffsetTrsf;
     anOffsetTrsf.SetTranslation (gp::Origin(), gp_Pnt (aShapeHOffset, aShapeVOffset, 0.0));
     aTextShape.Move (anOffsetTrsf);
 
-    // Transform text to myWorkingPlane coordinate system
-    gp_Ax3 aTextCoordSystem (myGeom.myTextPosition, myWorkingPlane.Axis().Direction(), aTextDir);
+    // transform text to myWorkingPlane coordinate system
+    gp_Ax3 aTextCoordSystem (theTextPos, myWorkingPlane.Axis().Direction(), aTextDir);
     gp_Trsf aTextPlaneTrsf;
     aTextPlaneTrsf.SetTransformation (aTextCoordSystem, gp_Ax3 (gp::XOY()));
     aTextShape.Move (aTextPlaneTrsf);
 
-    // Set display parameters for advanced selection
-    BRepBndLib::AddClose (aTextShape, myGeom.myTextBndBox);
-
-    // Set text flipping anchors
+    // set text flipping anchors
     gp_Trsf aCenterOffsetTrsf;
     gp_Pnt aCenterOffset (aCenterHOffset, aCenterVOffset, 0.0);
     aCenterOffsetTrsf.SetTranslation (gp::Origin(), aCenterOffset);
 
-    gp_Pnt aCenterOfFlip (gp::Origin());
-    aCenterOfFlip.Transform (aCenterOffsetTrsf);
-    aCenterOfFlip.Transform (aTextPlaneTrsf);
+    gp_Pnt aCenterOfLabel (gp::Origin());
+    aCenterOfLabel.Transform (aCenterOffsetTrsf);
+    aCenterOfLabel.Transform (aTextPlaneTrsf);
 
-    gp_Ax2 aFlippingAxes (aCenterOfFlip, myWorkingPlane.Axis().Direction(), aTextDir);
+    gp_Ax2 aFlippingAxes (aCenterOfLabel, myWorkingPlane.Axis().Direction(), aTextDir);
     Prs3d_Root::CurrentGroup (thePresentation)->SetFlippingOptions (Standard_True, aFlippingAxes);
 
-    // Draw text
+    // draw text
     if (myDrawer->DimensionAspect()->IsTextShaded())
     {
       // Setting text shading and color parameters
@@ -450,31 +487,38 @@ Standard_Real AIS_Dimension::drawText (const Handle(Prs3d_Presentation)& thePres
       myDrawer->ShadingAspect()->Aspect()->SetBackInteriorColor (aColor);
       myDrawer->ShadingAspect()->SetMaterial (aShadeMat);
 
-      // Drawing text
+      // drawing text
       StdPrs_ShadedShape::Add (thePresentation, aTextShape, myDrawer);
     }
     else
     {
-      // Setting color for text
+      // setting color for text
       myDrawer->FreeBoundaryAspect()->Aspect()->SetColor (aColor);
-      // Drawing text
+      // drawing text
       StdPrs_WFShape::Add (thePresentation, aTextShape, myDrawer);
     }
     Prs3d_Root::CurrentGroup (thePresentation)->SetFlippingOptions (Standard_False, gp_Ax2());
 
-    return aTextWidth + aMarginSize * 2.0;
+    mySelectionGeom.TextPos    = aCenterOfLabel;
+    mySelectionGeom.TextDir    = aTextDir;
+    mySelectionGeom.TextWidth  = aTextWidth + aMarginSize * 2.0;
+    mySelectionGeom.TextHeight = aTextHeight;
+
+    return;
   }
 
+  // generate primitives for 2D text
   myDrawer->DimensionAspect()->TextAspect()->Aspect()->SetDisplayType (Aspect_TODT_DIMENSION);
 
   Prs3d_Text::Draw (thePresentation,
                     myDrawer->DimensionAspect()->TextAspect(),
                     theText,
-                    myGeom.myTextPosition);
+                    theTextPos);
 
-  // For 2d text we don not create new group for lines and draw them in the same group with text
-  // for the proper handling of stencil test buffer.
-  return 0.0;
+  mySelectionGeom.TextPos    = theTextPos;
+  mySelectionGeom.TextDir    = theTextDir;
+  mySelectionGeom.TextWidth  = 0.0;
+  mySelectionGeom.TextHeight = 0.0;
 }
 
 //=======================================================================
@@ -485,53 +529,61 @@ void AIS_Dimension::drawExtension (const Handle(Prs3d_Presentation)& thePresenta
                                    const Standard_Real theExtensionSize,
                                    const gp_Pnt& theExtensionStart,
                                    const gp_Dir& theExtensionDir,
-                                   const TCollection_ExtendedString& theValueString,
-                                   const AIS_DimensionDisplayMode theMode,
+                                   const TCollection_ExtendedString& theLabelString,
+                                   const Standard_Real theLabelWidth,
+                                   const Standard_Integer theMode,
                                    const Standard_Integer theLabelPosition)
 {
-  Standard_Real aTextWidth = 0.0;
+  // reference line for extension starting at its connection point
+  gp_Lin anExtensionLine (theExtensionStart, theExtensionDir);
 
-  Standard_Boolean isLabel = theValueString.Length() > 0;
-  if (isLabel)
+  Standard_Boolean hasLabel = theLabelString.Length() > 0;
+
+  if (hasLabel && (theMode == ComputeMode_All || theMode == ComputeMode_Text))
   {
     // compute text primitives; get its model width
-    myGeom.myTextPosition = theExtensionStart.Translated (
-      gp_Vec (theExtensionDir).Scaled (theExtensionSize));
-
-    aTextWidth = drawText (thePresentation,
-                           myIsTextReversed ? -theExtensionDir : theExtensionDir,
-                           theValueString,
-                           theMode,
-                           theLabelPosition);
+    gp_Pnt aTextPos = ElCLib::Value (theExtensionSize, anExtensionLine);
+    gp_Dir aTextDir = myIsTextReversed ? -theExtensionDir : theExtensionDir;
+
+    drawText (thePresentation,
+              aTextPos,
+              aTextDir,
+              theLabelString,
+              theLabelPosition);
   }
 
-  if (theMode == AIS_DDM_Text)
+  if (theMode != ComputeMode_All && theMode != ComputeMode_Line)
   {
     return;
   }
 
+  Standard_Boolean isShortLine =  !myDrawer->DimensionAspect()->IsText3d()
+                               || theLabelPosition & LabelPosition_VCenter;
+
   // compute graphical primitives and sensitives for extension line
   gp_Pnt anExtStart = theExtensionStart;
-  gp_Pnt anExtEnd   = !isLabel || (theLabelPosition & LabelPosition_VCenter) != 0
-    ? theExtensionStart.Translated (gp_Vec (theExtensionDir) * theExtensionSize)
-    : theExtensionStart.Translated (gp_Vec (theExtensionDir) * (theExtensionSize + aTextWidth));
+  gp_Pnt anExtEnd   = !hasLabel || isShortLine
+    ? ElCLib::Value (theExtensionSize, anExtensionLine)
+    : ElCLib::Value (theExtensionSize + theLabelWidth, anExtensionLine);
 
+  // add graphical primitives
   Handle(Graphic3d_ArrayOfSegments) anExtPrimitive = new Graphic3d_ArrayOfSegments (2);
   anExtPrimitive->AddVertex (anExtStart);
   anExtPrimitive->AddVertex (anExtEnd);
 
-  Handle(SelectMgr_EntityOwner) aDummyOwner;
-
-  myGeom.mySensitiveSegments.Append (new Select3D_SensitiveSegment (aDummyOwner, anExtStart, anExtEnd));
+  // add selection primitives
+  SelectionGeometry::Curve& aSensitiveCurve = mySelectionGeom.NewCurve();
+  aSensitiveCurve.Append (anExtStart);
+  aSensitiveCurve.Append (anExtEnd);
 
-  if (!myDrawer->DimensionAspect()->IsText3d() && theMode == AIS_DDM_All)
+  if (!myDrawer->DimensionAspect()->IsText3d() && theMode == ComputeMode_All)
   {
     Prs3d_Root::CurrentGroup (thePresentation)->SetStencilTestOptions (Standard_True);
   }
   Handle(Graphic3d_AspectLine3d) aDimensionLineStyle = myDrawer->DimensionAspect()->LineAspect()->Aspect();
   Prs3d_Root::CurrentGroup (thePresentation)->SetPrimitivesAspect (aDimensionLineStyle);
   Prs3d_Root::CurrentGroup (thePresentation)->AddPrimitiveArray (anExtPrimitive);
-  if (!myDrawer->DimensionAspect()->IsText3d() && theMode == AIS_DDM_All)
+  if (!myDrawer->DimensionAspect()->IsText3d() && theMode == ComputeMode_All)
   {
     Prs3d_Root::CurrentGroup (thePresentation)->SetStencilTestOptions (Standard_False);
   }
@@ -560,10 +612,10 @@ Handle(Prs3d_DimensionAspect) AIS_Dimension::DimensionAspect() const
 //purpose  : 
 //=======================================================================
 void AIS_Dimension::drawLinearDimension (const Handle(Prs3d_Presentation)& thePresentation,
-                                         const AIS_DimensionDisplayMode theMode,
+                                         const Standard_Integer theMode,
                                          const Standard_Boolean isOneSideDimension/* = Standard_False*/)
 {
-  // Don't build any dimension for equal points
+  // don not build any dimension for equal points
   if (myFirstPoint.IsEqual (mySecondPoint, Precision::Confusion()))
   {
     setComputed (Standard_False);
@@ -587,7 +639,6 @@ void AIS_Dimension::drawLinearDimension (const Handle(Prs3d_Presentation)& thePr
 
   Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
   Handle(SelectMgr_EntityOwner) anEmptyOwner;
-  myGeom.mySensitiveSegments.Clear();
 
   gp_Lin aDimensionLine = gce_MakeLin (aLineBegPoint, aLineEndPoint);
 
@@ -600,11 +651,18 @@ void AIS_Dimension::drawLinearDimension (const Handle(Prs3d_Presentation)& thePr
    computeValue();
   }
 
-  TCollection_ExtendedString aValueString;
-  Standard_Real aTextLength;
-  getTextWidthAndString (aTextLength, aValueString);
+  // prepare label string and compute its geometrical width
+  Standard_Real aLabelWidth;
+  TCollection_ExtendedString aLabelString;
+  getTextWidthAndString (aLabelWidth, aLabelString);
 
-  // Handle user-defined and automatic arrow placement
+  // add margins to cut dimension lines for 3d text
+  if (aDimensionAspect->IsText3d())
+  {
+    aLabelWidth += aDimensionAspect->TextAspect()->Height() * THE_3D_TEXT_MARGIN * 2.0;
+  }
+
+  // handle user-defined and automatic arrow placement
   bool isArrowsExternal = false;
   switch (aDimensionAspect->ArrowOrientation())
   {
@@ -612,14 +670,22 @@ void AIS_Dimension::drawLinearDimension (const Handle(Prs3d_Presentation)& thePr
     case Prs3d_DAO_Internal: isArrowsExternal = false; break;
     case Prs3d_DAO_Fit:
     {
+      // add margin to ensure a small tail between text and arrow
+      Standard_Real anArrowMargin   = aDimensionAspect->IsText3d() 
+                                    ? aDimensionAspect->TextAspect()->Height() * THE_3D_TEXT_MARGIN
+                                    : 0.0;
+
       Standard_Real aDimensionWidth = aLineBegPoint.Distance (aLineEndPoint);
-      Standard_Real anArrowsWidth   = isOneSideDimension ? anArrowLength : 2.0 * anArrowLength;
-      isArrowsExternal = aDimensionWidth < aTextLength + anArrowsWidth;
+      Standard_Real anArrowsWidth   = isOneSideDimension 
+                                    ?  anArrowLength + anArrowMargin
+                                    : (anArrowLength + anArrowMargin) * 2.0;
+
+      isArrowsExternal = aDimensionWidth < aLabelWidth + anArrowsWidth;
       break;
     }
   }
 
-  // Arrows positions and directions
+  // compute arrows positions and directions
   gp_Dir aFirstArrowDir       = aDimensionLine.Direction().Reversed();
   gp_Dir aSecondArrowDir      = aDimensionLine.Direction();
   gp_Dir aFirstExtensionDir   = aDimensionLine.Direction().Reversed();
@@ -649,7 +715,7 @@ void AIS_Dimension::drawLinearDimension (const Handle(Prs3d_Presentation)& thePr
 
   Standard_Integer aLabelPosition = LabelPosition_None;
 
-  // Handle user-defined and automatic text placement
+  // handle user-defined and automatic text placement
   switch (aDimensionAspect->TextHorizontalPosition())
   {
     case Prs3d_DTHP_Left  : aLabelPosition |= LabelPosition_Left; break;
@@ -659,13 +725,14 @@ void AIS_Dimension::drawLinearDimension (const Handle(Prs3d_Presentation)& thePr
     {
       Standard_Real aDimensionWidth = aLineBegPoint.Distance (aLineEndPoint);
       Standard_Real anArrowsWidth   = isOneSideDimension ? anArrowLength : 2.0 * anArrowLength;
-      Standard_Real aContentWidth   = isArrowsExternal ? aTextLength : aTextLength + anArrowsWidth;
+      Standard_Real aContentWidth   = isArrowsExternal ? aLabelWidth : aLabelWidth + anArrowsWidth;
 
       aLabelPosition |= aDimensionWidth < aContentWidth ? LabelPosition_Left : LabelPosition_HCenter;
       break;
     }
   }
 
+  // handle vertical text placement options
   switch (aDimensionAspect->TextVerticalPosition())
   {
     case Prs3d_DTVP_Above  : aLabelPosition |= LabelPosition_Above; break;
@@ -678,108 +745,113 @@ void AIS_Dimension::drawLinearDimension (const Handle(Prs3d_Presentation)& thePr
     // ------------------------------------------------------------------------ //
     //                                CENTER                                    //
     // -------------------------------------------------------------------------//
-
     case LabelPosition_HCenter:
     {
       // add label on dimension or extension line to presentation
       Prs3d_Root::NewGroup (thePresentation);
 
-      gp_Vec aTextDir (aLineBegPoint, aLineEndPoint);
-
-      myGeom.myTextPosition = gp_XYZ (aLineBegPoint.XYZ() + aLineEndPoint.XYZ()) * 0.5;
-
-      Standard_Real aTextWidth = drawText (thePresentation,
-                                           myIsTextReversed ? -aTextDir : aTextDir,
-                                           aValueString,
-                                           theMode,
-                                           aLabelPosition);
+      gp_Pnt aTextPos = (aCenterLineBegin.XYZ() + aCenterLineEnd.XYZ()) * 0.5;
+      gp_Dir aTextDir = myIsTextReversed 
+                      ? -aDimensionLine.Direction()
+                      :  aDimensionLine.Direction();
 
-      if (theMode == AIS_DDM_Text)
+      // add text primitives
+      if (theMode == ComputeMode_All || theMode == ComputeMode_Text)
       {
-        break;
+        drawText (thePresentation,
+                  aTextPos,
+                  aTextDir,
+                  aLabelString,
+                  aLabelPosition);
       }
 
-      Standard_Real aLabelMargin = 
-        aDimensionAspect->IsText3d() ? aDimensionAspect->TextAspect()->Height() * THE_3D_TEXT_MARGIN : 0.0;
-
-      Standard_Boolean isLineBreak = aDimensionAspect->TextVerticalPosition() == Prs3d_DTVP_Center
-                                  && aDimensionAspect->IsText3d();
+      // add dimension line primitives
+      if (theMode == ComputeMode_All || theMode == ComputeMode_Line)
+      {
+        Standard_Boolean isLineBreak = aDimensionAspect->TextVerticalPosition() == Prs3d_DTVP_Center
+                                    && aDimensionAspect->IsText3d();
 
-      Handle(Graphic3d_ArrayOfSegments) aPrimSegments = new Graphic3d_ArrayOfSegments (isLineBreak ? 4 : 2);
+        Handle(Graphic3d_ArrayOfSegments) aPrimSegments = new Graphic3d_ArrayOfSegments (isLineBreak ? 4 : 2);
 
-      // compute dimension continuous or sectioned dimension line
-      if (isLineBreak)
-      {
-        Standard_Real aPTextPosition = ElCLib::Parameter (aDimensionLine, myGeom.myTextPosition);
-        gp_Pnt aSection1Beg = aCenterLineBegin;
-        gp_Pnt aSection1End = ElCLib::Value (aPTextPosition - aLabelMargin - (aTextWidth * 0.5), aDimensionLine);
-        gp_Pnt aSection2Beg = ElCLib::Value (aPTextPosition + aLabelMargin + (aTextWidth * 0.5), aDimensionLine);
-        gp_Pnt aSection2End = aCenterLineEnd;
-
-        aPrimSegments->AddVertex (aSection1Beg);
-        aPrimSegments->AddVertex (aSection1End);
-        aPrimSegments->AddVertex (aSection2Beg);
-        aPrimSegments->AddVertex (aSection2End);
-
-        myGeom.mySensitiveSegments.Append (new Select3D_SensitiveSegment (anEmptyOwner, aSection1Beg, aSection1End));
-        myGeom.mySensitiveSegments.Append (new Select3D_SensitiveSegment (anEmptyOwner, aSection2Beg, aSection2End));
-      }
-      else
-      {
-        aPrimSegments->AddVertex (aCenterLineBegin);
-        aPrimSegments->AddVertex (aCenterLineEnd);
+        // compute continuous or sectioned main line segments
+        if (isLineBreak)
+        {
+          Standard_Real aPTextPosition = ElCLib::Parameter (aDimensionLine, aTextPos);
+          gp_Pnt aSection1Beg = aCenterLineBegin;
+          gp_Pnt aSection1End = ElCLib::Value (aPTextPosition - (aLabelWidth * 0.5), aDimensionLine);
+          gp_Pnt aSection2Beg = ElCLib::Value (aPTextPosition + (aLabelWidth * 0.5), aDimensionLine);
+          gp_Pnt aSection2End = aCenterLineEnd;
+
+          aPrimSegments->AddVertex (aSection1Beg);
+          aPrimSegments->AddVertex (aSection1End);
+          aPrimSegments->AddVertex (aSection2Beg);
+          aPrimSegments->AddVertex (aSection2End);
+
+          SelectionGeometry::Curve& aLeftSensitiveCurve  = mySelectionGeom.NewCurve();
+          SelectionGeometry::Curve& aRightSensitiveCurve = mySelectionGeom.NewCurve();
+          aLeftSensitiveCurve.Append (aSection1Beg);
+          aLeftSensitiveCurve.Append (aSection1End);
+          aRightSensitiveCurve.Append (aSection2Beg);
+          aRightSensitiveCurve.Append (aSection2End);
+        }
+        else
+        {
+          aPrimSegments->AddVertex (aCenterLineBegin);
+          aPrimSegments->AddVertex (aCenterLineEnd);
 
-        myGeom.mySensitiveSegments.Append (
-          new Select3D_SensitiveSegment (anEmptyOwner, aCenterLineBegin, aCenterLineEnd));
-      }
+          SelectionGeometry::Curve& aSensitiveCurve = mySelectionGeom.NewCurve();
+          aSensitiveCurve.Append (aCenterLineBegin);
+          aSensitiveCurve.Append (aCenterLineEnd);
+        }
 
-      // set text label justification
-      Graphic3d_VerticalTextAlignment aTextJustificaton = Graphic3d_VTA_BOTTOM;
-      switch (aLabelPosition & LabelPosition_VMask)
-      {
-        case LabelPosition_Above   :
-        case LabelPosition_VCenter : aTextJustificaton = Graphic3d_VTA_BOTTOM; break;
-        case LabelPosition_Below   : aTextJustificaton = Graphic3d_VTA_TOP;    break;
-      }
-      aDimensionAspect->TextAspect()->SetVerticalJustification (aTextJustificaton);
+        // set text label justification
+        Graphic3d_VerticalTextAlignment aTextJustificaton = Graphic3d_VTA_BOTTOM;
+        switch (aLabelPosition & LabelPosition_VMask)
+        {
+          case LabelPosition_Above   :
+          case LabelPosition_VCenter : aTextJustificaton = Graphic3d_VTA_BOTTOM; break;
+          case LabelPosition_Below   : aTextJustificaton = Graphic3d_VTA_TOP;    break;
+        }
+        aDimensionAspect->TextAspect()->SetVerticalJustification (aTextJustificaton);
 
-      // Main dimension line, short extension
-      if (!aDimensionAspect->IsText3d() && theMode == AIS_DDM_All)
-      {
-        Prs3d_Root::CurrentGroup (thePresentation)->SetStencilTestOptions (Standard_True);
-      }
-      Prs3d_Root::CurrentGroup (thePresentation)->SetPrimitivesAspect (aDimensionAspect->LineAspect()->Aspect());
-      Prs3d_Root::CurrentGroup (thePresentation)->AddPrimitiveArray (aPrimSegments);
-      if (!aDimensionAspect->IsText3d() && theMode == AIS_DDM_All)
-      {
-        Prs3d_Root::CurrentGroup (thePresentation)->SetStencilTestOptions (Standard_False);
-      }
+        // main dimension line, short extension
+        if (!aDimensionAspect->IsText3d() && theMode == ComputeMode_All)
+        {
+          Prs3d_Root::CurrentGroup (thePresentation)->SetStencilTestOptions (Standard_True);
+        }
+        Prs3d_Root::CurrentGroup (thePresentation)->SetPrimitivesAspect (aDimensionAspect->LineAspect()->Aspect());
+        Prs3d_Root::CurrentGroup (thePresentation)->AddPrimitiveArray (aPrimSegments);
+        if (!aDimensionAspect->IsText3d() && theMode == ComputeMode_All)
+        {
+          Prs3d_Root::CurrentGroup (thePresentation)->SetStencilTestOptions (Standard_False);
+        }
 
-      // add arrows to presentation
-      Prs3d_Root::NewGroup (thePresentation);
+        // add arrows to presentation
+        Prs3d_Root::NewGroup (thePresentation);
 
-      drawArrow (thePresentation, aFirstArrowBegin, aFirstArrowDir);
-      if (!isOneSideDimension)
-      {
-        drawArrow (thePresentation, aSecondArrowBegin, aSecondArrowDir);
-      }
+        drawArrow (thePresentation, aFirstArrowBegin, aFirstArrowDir);
+        if (!isOneSideDimension)
+        {
+          drawArrow (thePresentation, aSecondArrowBegin, aSecondArrowDir);
+        }
 
-      if (!isArrowsExternal)
-      {
-        break;
-      }
+        if (!isArrowsExternal)
+        {
+          break;
+        }
 
-      // add arrow extension lines to presentation
-      Prs3d_Root::NewGroup (thePresentation);
+        // add arrow extension lines to presentation
+        Prs3d_Root::NewGroup (thePresentation);
 
-      drawExtension (thePresentation, anExtensionSize,
-                     aFirstArrowEnd, aFirstExtensionDir,
-                     THE_EMPTY_LABEL, theMode, LabelPosition_None);
-      if (!isOneSideDimension)
-      {
         drawExtension (thePresentation, anExtensionSize,
-                       aSecondArrowEnd, aSecondExtensionDir,
-                       THE_EMPTY_LABEL, theMode, LabelPosition_None);
+                       aFirstArrowEnd, aFirstExtensionDir,
+                       THE_EMPTY_LABEL, 0.0, theMode, LabelPosition_None);
+        if (!isOneSideDimension)
+        {
+          drawExtension (thePresentation, anExtensionSize,
+                         aSecondArrowEnd, aSecondExtensionDir,
+                         THE_EMPTY_LABEL, 0.0, theMode, LabelPosition_None);
+        }
       }
 
       break;
@@ -795,49 +867,53 @@ void AIS_Dimension::drawLinearDimension (const Handle(Prs3d_Presentation)& thePr
 
       // Left extension with the text
       drawExtension (thePresentation, anExtensionSize,
-                     isArrowsExternal ? aFirstArrowEnd : aLineBegPoint,
+                     isArrowsExternal ? aFirstArrowEnd : aFirstArrowBegin,
                      aFirstExtensionDir,
-                     aValueString,
+                     aLabelString,
+                     aLabelWidth,
                      theMode,
                      aLabelPosition);
 
-      if (theMode == AIS_DDM_Text)
+      // add dimension line primitives
+      if (theMode == ComputeMode_All || theMode == ComputeMode_Line)
       {
-        break;
-      }
+        // add central dimension line
+        Prs3d_Root::NewGroup (thePresentation);
 
-      // add central dimension line
-      Prs3d_Root::NewGroup (thePresentation);
+        // add graphical primitives
+        Handle(Graphic3d_ArrayOfSegments) aPrimSegments = new Graphic3d_ArrayOfSegments (2);
+        aPrimSegments->AddVertex (aCenterLineBegin);
+        aPrimSegments->AddVertex (aCenterLineEnd);
 
-      Handle(Graphic3d_ArrayOfSegments) aPrimSegments = new Graphic3d_ArrayOfSegments (2);
-      aPrimSegments->AddVertex (aCenterLineBegin);
-      aPrimSegments->AddVertex (aCenterLineEnd);
-      Prs3d_Root::CurrentGroup (thePresentation)->SetPrimitivesAspect (aDimensionAspect->LineAspect()->Aspect());
-      Prs3d_Root::CurrentGroup (thePresentation)->AddPrimitiveArray (aPrimSegments);
+        Prs3d_Root::CurrentGroup (thePresentation)->SetPrimitivesAspect (aDimensionAspect->LineAspect()->Aspect());
+        Prs3d_Root::CurrentGroup (thePresentation)->AddPrimitiveArray (aPrimSegments);
 
-      myGeom.mySensitiveSegments.Append (
-        new Select3D_SensitiveSegment (anEmptyOwner, aCenterLineBegin, aCenterLineEnd));
+        // add selection primitives
+        SelectionGeometry::Curve& aSensitiveCurve = mySelectionGeom.NewCurve();
+        aSensitiveCurve.Append (aCenterLineBegin);
+        aSensitiveCurve.Append (aCenterLineEnd);
 
-      // add arrows to presentation
-      Prs3d_Root::NewGroup (thePresentation);
+        // add arrows to presentation
+        Prs3d_Root::NewGroup (thePresentation);
 
-      drawArrow (thePresentation, aFirstArrowBegin, aFirstArrowDir);
-      if (!isOneSideDimension)
-      {
-        drawArrow (thePresentation, aSecondArrowBegin, aSecondArrowDir);
-      }
+        drawArrow (thePresentation, aFirstArrowBegin, aFirstArrowDir);
+        if (!isOneSideDimension)
+        {
+          drawArrow (thePresentation, aSecondArrowBegin, aSecondArrowDir);
+        }
 
-      if (!isArrowsExternal || isOneSideDimension)
-      {
-        break;
-      }
+        if (!isArrowsExternal || isOneSideDimension)
+        {
+          break;
+        }
 
-      // add extension lines for external arrows
-      Prs3d_Root::NewGroup (thePresentation);
+        // add extension lines for external arrows
+        Prs3d_Root::NewGroup (thePresentation);
 
-      drawExtension (thePresentation, anExtensionSize,
-                     aSecondArrowEnd, aSecondExtensionDir,
-                     THE_EMPTY_LABEL, theMode, LabelPosition_None);
+        drawExtension (thePresentation, anExtensionSize,
+                       aSecondArrowEnd, aSecondExtensionDir,
+                       THE_EMPTY_LABEL, 0.0, theMode, LabelPosition_None);
+      }
 
       break;
     }
@@ -854,53 +930,55 @@ void AIS_Dimension::drawLinearDimension (const Handle(Prs3d_Presentation)& thePr
       drawExtension (thePresentation, anExtensionSize,
                      isArrowsExternal ? aSecondArrowEnd : aSecondArrowBegin,
                      aSecondExtensionDir,
-                     aValueString,
+                     aLabelString, aLabelWidth,
                      theMode,
                      aLabelPosition);
 
-      if (theMode == AIS_DDM_Text)
+      if (theMode == ComputeMode_All || theMode == ComputeMode_Line)
       {
-        break;
-      }
+        // add central dimension line
+        Prs3d_Root::NewGroup (thePresentation);
 
-      // add central dimension line
-      Prs3d_Root::NewGroup (thePresentation);
+        // add graphical primitives
+        Handle(Graphic3d_ArrayOfSegments) aPrimSegments = new Graphic3d_ArrayOfSegments (2);
+        aPrimSegments->AddVertex (aCenterLineBegin);
+        aPrimSegments->AddVertex (aCenterLineEnd);
+        Prs3d_Root::CurrentGroup (thePresentation)->SetPrimitivesAspect (aDimensionAspect->LineAspect()->Aspect());
+        Prs3d_Root::CurrentGroup (thePresentation)->AddPrimitiveArray (aPrimSegments);
 
-      Handle(Graphic3d_ArrayOfSegments) aPrimSegments = new Graphic3d_ArrayOfSegments (2);
-      aPrimSegments->AddVertex (aCenterLineBegin);
-      aPrimSegments->AddVertex (aCenterLineEnd);
-      Prs3d_Root::CurrentGroup (thePresentation)->SetPrimitivesAspect (aDimensionAspect->LineAspect()->Aspect());
-      Prs3d_Root::CurrentGroup (thePresentation)->AddPrimitiveArray (aPrimSegments);
+        // add selection primitives
+        SelectionGeometry::Curve& aSensitiveCurve = mySelectionGeom.NewCurve();
+        aSensitiveCurve.Append (aCenterLineBegin);
+        aSensitiveCurve.Append (aCenterLineEnd);
 
-      myGeom.mySensitiveSegments.Append (
-        new Select3D_SensitiveSegment (anEmptyOwner, aCenterLineBegin, aCenterLineEnd));
+        // add arrows to presentation
+        Prs3d_Root::NewGroup (thePresentation);
 
-      // add arrows to presentation
-      Prs3d_Root::NewGroup (thePresentation);
+        drawArrow (thePresentation, aSecondArrowBegin, aSecondArrowDir);
+        if (!isOneSideDimension)
+        {
+          drawArrow (thePresentation, aFirstArrowBegin, aFirstArrowDir);
+        }
 
-      drawArrow (thePresentation, aSecondArrowBegin, aSecondArrowDir);
-      if (!isOneSideDimension)
-      {
-        drawArrow (thePresentation, aFirstArrowBegin, aFirstArrowDir);
-      }
+        if (!isArrowsExternal || isOneSideDimension)
+        {
+          break;
+        }
 
-      if (!isArrowsExternal || isOneSideDimension)
-      {
-        break;
-      }
+        // add extension lines for external arrows
+        Prs3d_Root::NewGroup (thePresentation);
 
-      // add extension lines for external arrows
-      Prs3d_Root::NewGroup (thePresentation);
+        drawExtension (thePresentation, anExtensionSize,
+                       aFirstArrowEnd, aFirstExtensionDir,
+                       THE_EMPTY_LABEL, 0.0, theMode, LabelPosition_None);
+      }
 
-      drawExtension (thePresentation, anExtensionSize,
-                     aFirstArrowEnd, aFirstExtensionDir,
-                     THE_EMPTY_LABEL, theMode, LabelPosition_None);
       break;
     }
   }
 
   // add flyout lines to presentation
-  if (theMode == AIS_DDM_All)
+  if (theMode == ComputeMode_All)
   {
     Prs3d_Root::NewGroup (thePresentation);
 
@@ -1248,7 +1326,7 @@ void AIS_Dimension::SetDisplayUnits (const TCollection_AsciiString& theUnits)
 //=======================================================================
 Standard_Boolean AIS_Dimension::isComputed() const
 {
-  return myGeom.myIsComputed;
+  return myIsComputed;
 }
 
 //=======================================================================
@@ -1257,25 +1335,7 @@ Standard_Boolean AIS_Dimension::isComputed() const
 //=======================================================================
 void AIS_Dimension::setComputed (Standard_Boolean isComputed)
 {
-  myGeom.myIsComputed = isComputed;
-}
-
-//=======================================================================
-//function : textPosition
-//purpose  :
-//=======================================================================
-gp_Pnt AIS_Dimension::textPosition() const
-{
-  return myGeom.myTextPosition;
-}
-
-//=======================================================================
-//function : setTextPosition
-//purpose  :
-//=======================================================================
-void AIS_Dimension::setTextPosition (const gp_Pnt thePosition)
-{
-  myGeom.myTextPosition = thePosition;
+  myIsComputed = isComputed;
 }
 
 //=======================================================================
@@ -1284,7 +1344,7 @@ void AIS_Dimension::setTextPosition (const gp_Pnt thePosition)
 //=======================================================================
 void AIS_Dimension::resetGeom()
 {
-  setComputed (Standard_False);
+  mySelectionGeom.Clear (ComputeMode_All);
 }
 
 //=======================================================================
@@ -1311,7 +1371,7 @@ void AIS_Dimension::MakeTextReversed (const Standard_Boolean isTextReversed)
 //=======================================================================
 void AIS_Dimension::SetSelToleranceForText2d (const Standard_Real theTol)
 {
-  myGeom.mySelToleranceForText2d = theTol;
+  mySelToleranceForText2d = theTol;
 }
 
 //=======================================================================
@@ -1320,7 +1380,7 @@ void AIS_Dimension::SetSelToleranceForText2d (const Standard_Real theTol)
 //=======================================================================
 Standard_Real AIS_Dimension::SelToleranceForText2d() const
 {
-  return myGeom.mySelToleranceForText2d;
+  return mySelToleranceForText2d;
 }
 
 //=======================================================================
@@ -1343,14 +1403,14 @@ void AIS_Dimension::SetFlyout (const Standard_Real theFlyout)
 //purpose  : computes selection for flyouts
 //=======================================================================
 void AIS_Dimension::computeFlyoutSelection (const Handle(SelectMgr_Selection)& theSelection,
-                                            const Handle(AIS_DimensionOwner)& theOwner)
+                                            const Handle(SelectMgr_EntityOwner)& theOwner)
 {
   //Count flyout direction
   gp_Ax1 aWorkingPlaneNormal = GetWorkingPlane().Axis();
   gp_Dir aTargetPointsVector = gce_MakeDir (myFirstPoint, mySecondPoint);
 
   // Count a flyout direction vector.
-  gp_Dir aFlyoutVector = aWorkingPlaneNormal.Direction()^aTargetPointsVector;
+  gp_Dir aFlyoutVector = aWorkingPlaneNormal.Direction() ^ aTargetPointsVector;
 
   // Create lines for layouts
   gp_Lin aLine1 (myFirstPoint, aFlyoutVector);
@@ -1379,43 +1439,144 @@ void AIS_Dimension::ComputeSelection (const Handle(SelectMgr_Selection)& theSele
     return;
   }
 
-  Handle(Select3D_SensitiveGroup) aSensitiveForLine;
-  Handle(Select3D_SensitiveEntity) aSensitiveForText;
-  Select3D_ListOfSensitive aSensitiveList;
-  aSensitiveList.Assign (myGeom.mySensitiveSegments);
+  AIS_DimensionSelectionMode aSelectionMode = (AIS_DimensionSelectionMode)theMode;
 
-  // Full dimension selection
-  Handle(AIS_DimensionOwner) anOwner = new AIS_DimensionOwner (this, AIS_DDM_All, theMode == 0 ? 5 : 6);
-  for (Select3D_ListIteratorOfListOfSensitive anIt (aSensitiveList); anIt.More(); anIt.Next())
-  {
-    anIt.Value()->Set (anOwner);
-  }
-  aSensitiveForLine = new Select3D_SensitiveGroup (anOwner, aSensitiveList);
+  // init appropriate entity owner
+  Handle(SelectMgr_EntityOwner) aSensitiveOwner;
 
-  // Text
-  if (myDrawer->DimensionAspect()->IsText3d())
+  switch (aSelectionMode)
   {
-    aSensitiveForText = new Select3D_SensitiveBox (anOwner,myGeom.myTextBndBox);
+    // neutral selection owner
+    case AIS_DSM_All :
+      aSensitiveOwner = new SelectMgr_EntityOwner (this, THE_NEUTRAL_SEL_PRIORITY);
+      break;
+
+    // local selection owners
+    case AIS_DSM_Line :
+    case AIS_DSM_Text :
+      aSensitiveOwner = new AIS_DimensionOwner (this, aSelectionMode, THE_LOCAL_SEL_PRIORITY);
+      break;
   }
-  else
+
+  if (aSelectionMode == AIS_DSM_All || aSelectionMode == AIS_DSM_Line)
   {
-    Handle(Geom_Circle) aSensitiveGeom = new Geom_Circle (gp_Circ (gp_Ax2 (myGeom.myTextPosition,
-                                                            myWorkingPlane.Position().XDirection()),
-                                                            myGeom.mySelToleranceForText2d != 0
-                                                          ? myGeom.mySelToleranceForText2d : 1.0));
-    aSensitiveForText = new Select3D_SensitiveCircle (anOwner, aSensitiveGeom, Standard_True);
+    // sensitives for dimension line segments
+    Handle(Select3D_SensitiveGroup) aGroupOfSensitives = new Select3D_SensitiveGroup (aSensitiveOwner);
+
+    SelectionGeometry::SeqOfCurves::Iterator aCurveIt (mySelectionGeom.DimensionLine);
+    for (; aCurveIt.More(); aCurveIt.Next())
+    {
+      const SelectionGeometry::HCurve& aCurveData = aCurveIt.Value();
+
+      TColgp_Array1OfPnt aSensitivePnts (1, aCurveData->Length());
+      for (Standard_Integer aPntIt = 1; aPntIt <= aCurveData->Length(); ++aPntIt)
+      {
+        aSensitivePnts.ChangeValue (aPntIt) = aCurveData->Value (aPntIt);
+      }
+
+      aGroupOfSensitives->Add (new Select3D_SensitiveCurve (aSensitiveOwner, aSensitivePnts));
+    }
+
+    Quantity_Length anArrowLength = myDrawer->DimensionAspect()->ArrowAspect()->Length();
+    Standard_Real   anArrowAngle  = myDrawer->DimensionAspect()->ArrowAspect()->Angle();
+
+    // sensitives for arrows
+    SelectionGeometry::SeqOfArrows::Iterator anArrowIt (mySelectionGeom.Arrows);
+    for (; anArrowIt.More(); anArrowIt.Next())
+    {
+      const SelectionGeometry::HArrow& anArrow = anArrowIt.Value();
+
+      gp_Pnt aSidePnt1 (gp::Origin());
+      gp_Pnt aSidePnt2 (gp::Origin());
+      const gp_Dir& aPlane = myWorkingPlane.Axis().Direction();
+      const gp_Pnt& aPeak  = anArrow->Position;
+      const gp_Dir& aDir   = anArrow->Direction;
+
+      // compute points for arrow in plane
+      PointsForArrow (aPeak, aDir, aPlane, anArrowLength, anArrowAngle, aSidePnt1, aSidePnt2);
+
+      aGroupOfSensitives->Add (new Select3D_SensitiveTriangle (aSensitiveOwner, aPeak, aSidePnt1, aSidePnt2));
+
+      if (!myDrawer->DimensionAspect()->IsArrows3d())
+      {
+        continue;
+      }
+
+      // compute points for orthogonal sensitive plane
+      gp_Dir anOrthoPlane = anArrow->Direction.Crossed (aPlane);
+
+      PointsForArrow (aPeak, aDir, anOrthoPlane, anArrowLength, anArrowAngle, aSidePnt1, aSidePnt2);
+
+      aGroupOfSensitives->Add (new Select3D_SensitiveTriangle (aSensitiveOwner, aPeak, aSidePnt1, aSidePnt2));
+    }
+
+    theSelection->Add (aGroupOfSensitives);
   }
-  if (theMode > 0)
+
+  // sensitives for text element
+  if (aSelectionMode == AIS_DSM_All || aSelectionMode == AIS_DSM_Text)
   {
-    anOwner->SetDisplayMode (AIS_DDM_Line);
-    Handle(AIS_DimensionOwner) aTextOwner = new AIS_DimensionOwner (this, AIS_DDM_Text, 7);
-    aSensitiveForText->Set (aTextOwner);
+    Handle(Select3D_SensitiveEntity) aTextSensitive;
+
+    gp_Ax2 aTextAxes (mySelectionGeom.TextPos,
+                      myWorkingPlane.Axis().Direction(),
+                      mySelectionGeom.TextDir);
+
+    if (myDrawer->DimensionAspect()->IsText3d())
+    {
+      // sensitive planar rectangle for text
+      Standard_Real aDx = mySelectionGeom.TextWidth  * 0.5;
+      Standard_Real aDy = mySelectionGeom.TextHeight * 0.5;
+
+      gp_Trsf aLabelPlane;
+      aLabelPlane.SetTransformation (aTextAxes, gp::XOY());
+
+      TColgp_Array1OfPnt aRectanglePoints (1, 4);
+      aRectanglePoints.ChangeValue (1) = gp_Pnt (-aDx, -aDy, 0.0).Transformed (aLabelPlane);
+      aRectanglePoints.ChangeValue (2) = gp_Pnt (-aDx,  aDy, 0.0).Transformed (aLabelPlane);
+      aRectanglePoints.ChangeValue (3) = gp_Pnt ( aDx,  aDy, 0.0).Transformed (aLabelPlane);
+      aRectanglePoints.ChangeValue (4) = gp_Pnt ( aDx, -aDy, 0.0).Transformed (aLabelPlane);
+
+      aTextSensitive = new Select3D_SensitiveFace (aSensitiveOwner, aRectanglePoints);
+    }
+    else
+    {
+      gp_Circ aTextGeom (aTextAxes, mySelToleranceForText2d != 0.0 
+                                      ? mySelToleranceForText2d : 1.0);
+
+      Handle(Geom_Circle) aSensGeom = new Geom_Circle (aTextGeom);
+
+      aTextSensitive = new Select3D_SensitiveCircle (aSensitiveOwner, aSensGeom, Standard_True);
+    }
+
+    theSelection->Add (aTextSensitive);
   }
-  else
+
+  // callback for flyout sensitive calculation
+  if (aSelectionMode == AIS_DSM_All)
   {
-    computeFlyoutSelection (theSelection, anOwner);
+    computeFlyoutSelection (theSelection, aSensitiveOwner);
   }
+}
+
+//=======================================================================
+//function : PointsForArrow
+//purpose  : 
+//=======================================================================
+void AIS_Dimension::PointsForArrow (const gp_Pnt& thePeakPnt,
+                                    const gp_Dir& theDirection,
+                                    const gp_Dir& thePlane,
+                                    const Standard_Real theArrowLength,
+                                    const Standard_Real theArrowAngle,
+                                    gp_Pnt& theSidePnt1,
+                                    gp_Pnt& theSidePnt2)
+{
+  gp_Lin anArrowLin (thePeakPnt, theDirection.Reversed());
+  gp_Pnt anArrowEnd = ElCLib::Value (theArrowLength, anArrowLin);
+  gp_Lin anEdgeLin (anArrowEnd, theDirection.Crossed (thePlane));
+
+  Standard_Real anEdgeLength = Tan (theArrowAngle) * theArrowLength;
 
-  theSelection->Add (aSensitiveForLine);
-  theSelection->Add (aSensitiveForText);
+  theSidePnt1 = ElCLib::Value ( anEdgeLength, anEdgeLin);
+  theSidePnt2 = ElCLib::Value (-anEdgeLength, anEdgeLin);
 }
index 534794a..361814e 100644 (file)
@@ -19,7 +19,7 @@
 #ifndef _AIS_Dimension_Headerfile
 #define _AIS_Dimension_Headerfile
 
-#include <AIS_DimensionDisplayMode.hxx>
+#include <AIS_DimensionSelectionMode.hxx>
 #include <AIS_DimensionOwner.hxx>
 #include <AIS_DisplaySpecialSymbol.hxx>
 #include <AIS_InteractiveObject.hxx>
 #include <SelectMgr_EntityOwner.hxx>
 #include <Standard.hxx>
 #include <TCollection_ExtendedString.hxx>
-#include <TColgp_HArray1OfPnt.hxx>
+#include <TColgp_HSequenceOfPnt.hxx>
 #include <TopoDS_Face.hxx>
 #include <TopoDS_Shape.hxx>
+#include <NCollection_Sequence.hxx>
+#include <NCollection_Handle.hxx>
 
 DEFINE_STANDARD_HANDLE(AIS_Dimension, AIS_InteractiveObject)
 
@@ -67,6 +69,18 @@ protected:
 
 public:
 
+  //! Specifies supported presentation compute modes.
+  //! Used to compute only parts of presentation for
+  //! advanced highlighting.
+  enum ComputeMode
+  {
+    ComputeMode_All  = 0, //!< "0" is reserved as neutral mode
+    ComputeMode_Line = 1, //!< corresponds to selection mode
+    ComputeMode_Text = 2  //!< corresponds to selection mode
+  };
+
+public:
+
   //! Constructor with default parameters values
   Standard_EXPORT  AIS_Dimension();
 
@@ -136,7 +150,7 @@ public:
   //! shows if Units are to be displayed along with dimension value
   Standard_EXPORT  Standard_Boolean IsUnitsDisplayed() const;
 
-  //! sets to display units along with the dimansion value or no
+  //! sets to display units along with the dimension value or no
   Standard_EXPORT  void MakeUnitsDisplayed (const Standard_Boolean toDisplayUnits);
 
   //! returns the current type of units
@@ -218,31 +232,33 @@ protected:
 
   //! Performs drawing of 2d or 3d text on the working plane
   //! @return text width relative to the dimension working plane. For 2d text this value will be zero.
-  Standard_EXPORT Standard_Real drawText (const Handle(Prs3d_Presentation)& thePresentation,
-                                          const gp_Dir& theTextDir,
-                                          const TCollection_ExtendedString theText,
-                                          const AIS_DimensionDisplayMode theMode,
-                                          const Standard_Integer theLabelPosition);
+  Standard_EXPORT void drawText (const Handle(Prs3d_Presentation)& thePresentation,
+                                 const gp_Pnt& theTextPos,
+                                 const gp_Dir& theTextDir,
+                                 const TCollection_ExtendedString& theText,
+                                 const Standard_Integer theLabelPosition);
 
   //! Performs computing of dimension linear extension with text
   //! @param thePresentation [in] the presentation to fill with graphical primitives.
   //! @param theExtensionSize [in] the size of extension line.
   //! @param theExtensionStart [in] the point where extension line connects to dimension.
   //! @param theExtensionDir [in] the direction of extension line.
-  //! @param theValueString [in] the string with value.
+  //! @param theLabelString [in] the string with value.
+  //! @param theLabelWidth [in] the geometrical width computed for value string.
   //! @param theMode [in] the display mode.
   //! @param theLabelPosition [in] position flags for the text label.
   Standard_EXPORT void drawExtension (const Handle(Prs3d_Presentation)& thePresentation,
                                       const Standard_Real theExtensionSize,
                                       const gp_Pnt& theExtensionStart,
                                       const gp_Dir& theExtensionDir,
-                                      const TCollection_ExtendedString& theValueString,
-                                      const AIS_DimensionDisplayMode theMode,
+                                      const TCollection_ExtendedString& theLabelString,
+                                      const Standard_Real theLabelWidth,
+                                      const Standard_Integer theMode,
                                       const Standard_Integer theLabelPosition);
 
   //! Performs computing of linear dimension (for length, diameter, radius and so on)
   Standard_EXPORT void drawLinearDimension (const Handle(Prs3d_Presentation)& thePresentation,
-                                            const AIS_DimensionDisplayMode theMode,
+                                            const Standard_Integer theMode,
                                             const Standard_Boolean isOneSideDimension = Standard_False);
 
   //! If it's possible computes circle from planar face
@@ -261,15 +277,28 @@ protected:
 
   Standard_EXPORT void setComputed (Standard_Boolean isComputed);
 
-  Standard_EXPORT gp_Pnt textPosition() const;
-
-  Standard_EXPORT void setTextPosition (const gp_Pnt thePosition);
-
   Standard_EXPORT void resetGeom();
 
   //! Fills sensitive entity for flyouts and adds it to the selection.
   Standard_EXPORT virtual void computeFlyoutSelection (const Handle(SelectMgr_Selection)& theSelection,
-                                                       const Handle(AIS_DimensionOwner)& theOwner);
+                                                       const Handle(SelectMgr_EntityOwner)& theOwner);
+
+  //! Produce points for triangular arrow face.
+  //! @param thePeakPnt [in] the arrow peak position.
+  //! @param theDirection [in] the arrow direction.
+  //! @param thePlane [in] the face plane.
+  //! @param theArrowLength [in] the length of arrow.
+  //! @param theArrowAngle [in] the angle of arrow.
+  //! @param thePeakPnt [in] the arrow peak point.
+  //! @param theSidePnt1 [in] the first side point.
+  //! @param theSidePnt2 [in] the second side point.
+  Standard_EXPORT void PointsForArrow (const gp_Pnt& thePeakPnt,
+                                       const gp_Dir& theDirection,
+                                       const gp_Dir& thePlane,
+                                       const Standard_Real theArrowLength,
+                                       const Standard_Real theArrowAngle,
+                                       gp_Pnt& theSidePnt1,
+                                       gp_Pnt& theSidePnt2);
 
 protected: //! @name Working plane properties
 
@@ -307,34 +336,74 @@ protected: // !@name Units properties
   //! Special symbol display options
   AIS_DisplaySpecialSymbol myDisplaySpecialSymbol;
 
-protected: //! @name Geometry properties
+protected: //! @name Selection geometry
 
-  //! Geometry of dimensions, needs for advanced selection
-  //! Geometry is computed in Compute() method and is used 
-  //! in ComputeSelection() method.
-  //! If it is computed successfully, myIsComputed = Standard_True.
-  //! to check computing result use IsComputed() method
-  struct DimensionGeom
+  //! Selection geometry of dimension presentation. The structure is filled with data
+  //! during compute of presentation, then this data is used to generate selection
+  //! sensitives when computing selection.
+  struct SelectionGeometry
   {
-    //! Text position
-    gp_Pnt myTextPosition;
-
-    //! Text bounding box, stored for advanced selection
-    Bnd_Box myTextBndBox;
+    //! Arrows are represented by directed triangles.
+    struct Arrow
+    {
+      gp_Pnt Position;
+      gp_Dir Direction;
+    };
+    typedef NCollection_Sequence<gp_Pnt> Curve;
+    typedef NCollection_Handle<Curve>    HCurve;
+    typedef NCollection_Handle<Arrow>    HArrow;
+    typedef NCollection_Sequence<HCurve> SeqOfCurves;
+    typedef NCollection_Sequence<HArrow> SeqOfArrows;
+
+    gp_Pnt           TextPos;            //!< Center of text label.
+    gp_Dir           TextDir;            //!< Direction of text label.
+    Standard_Real    TextWidth;          //!< Width of text label.
+    Standard_Real    TextHeight;         //!< Height of text label.
+    SeqOfCurves      DimensionLine;      //!< Sequence of points for composing the segments of dimension line.
+    SeqOfArrows      Arrows;             //!< Sequence of arrow geometries.
+
+  public:
+
+    //! Clear geometry of sensitives for the specified compute mode.
+    //! @param theMode [in] the compute mode to clear.
+    void Clear (const Standard_Integer theMode)
+    {
+      if (theMode == ComputeMode_All || theMode == ComputeMode_Line)
+      {
+        DimensionLine.Clear();
+        Arrows.Clear();
+      }
+
+      if (theMode == ComputeMode_All || theMode == ComputeMode_Text)
+      {
+        TextPos    = gp::Origin();
+        TextDir    = gp::DX();
+        TextWidth  = 0.0;
+        TextHeight = 0.0;
+      }
+    }
+
+    //! Add new curve entry and return the referenece to populate it.
+    Curve& NewCurve()
+    {
+      DimensionLine.Append( new Curve );
+      HCurve& aLastCurve = DimensionLine.ChangeLast();
+      return *aLastCurve;
+    }
+
+    //! Add new arrow entry and return the referenece to populate it.
+    Arrow& NewArrow()
+    {
+      Arrows.Append( new Arrow );
+      HArrow& aLastArrow = Arrows.ChangeLast();
+      return *aLastArrow;
+    }
+  } mySelectionGeom;
+
+  Standard_Real mySelToleranceForText2d; //!< Sensitive point tolerance for 2d text selection.
+  Standard_Boolean myIsComputed;         //!< Shows if the presentation and selection was computed.
 
-    //! Sensitive point tolerance for 2d text selection
-    Standard_Real mySelToleranceForText2d;
-
-    //! For advanced dimension line selection
-    Select3D_ListOfSensitive mySensitiveSegments;
-
-    //! Shows if attachment points were computed
-    Standard_Boolean myIsComputed;
-
-  public: 
-
-    DimensionGeom () : myIsComputed (Standard_False) {}
-  };
+protected:
 
   //! Shows if text is inverted
   Standard_Boolean myIsTextReversed;
@@ -365,13 +434,6 @@ protected: //! @name Geometry properties
   //! myFlyout value defined the size of flyout.
   Standard_Real myFlyout;
 
-  //! Geometry of dimensions, needs for advanced selection
-  //! Geometry is computed in Compute() method and is used 
-  //! in ComputeSelection() method.
-  //! If it is computed successfully, myIsComputed = Standard_True.
-  //! to check computing result use IsComputed() method
-  DimensionGeom myGeom;
-
 private:
 
   //! Type of dimension
index bc96076..b0a429e 100755 (executable)
@@ -35,26 +35,24 @@ class DimensionOwner from AIS inherits EntityOwner from SelectMgr
 
 uses
 
-    SelectableObject      from SelectMgr,
-    PresentationManager   from PrsMgr,
-    PresentationManager3d from PrsMgr,
-    NameOfColor           from Quantity,
-    DimensionDisplayMode  from AIS
+    SelectableObject       from SelectMgr,
+    PresentationManager    from PrsMgr,
+    PresentationManager3d  from PrsMgr,
+    NameOfColor            from Quantity,
+    DimensionSelectionMode from AIS
 
 is
 
     Create (theSelObject  : SelectableObject;
-            theDisplayMode    : DimensionDisplayMode from AIS;
+            theSelMode    : DimensionSelectionMode from AIS;
             thePriority   : Integer from Standard = 0)
     returns mutable DimensionOwner from AIS;
       ---Purpose:
       -- Initializes the dimension owner, theSO, and attributes it
       -- the priority, thePriority.
 
-    SetDisplayMode (me : mutable; theMode : DimensionDisplayMode from AIS);
-
-    DisplayMode (me)
-    returns DimensionDisplayMode from AIS;
+    SelectionMode (me)
+    returns DimensionSelectionMode from AIS;
 
     HilightWithColor (me       : mutable;
                       thePM    : PresentationManager3d from PrsMgr;
@@ -77,8 +75,9 @@ is
               thePM   : PresentationManager from PrsMgr;
               theMode : Integer  from  Standard  =0) is redefined virtual;
     ---Purpose: Removes highlighting from the selected part of dimension.
+
 fields
 
-    myDisplayMode : DimensionDisplayMode from AIS;
+    mySelectionMode : DimensionSelectionMode from AIS;
 
 end DimensionOwner;
index 93d186d..86d9672 100755 (executable)
 // purpose or non-infringement. Please see the License for the specific terms
 // and conditions governing the rights and limitations under the License.
 
-
-
 #include <AIS_DimensionOwner.ixx>
-#include <AIS_DimensionDisplayMode.hxx>
+#include <AIS_Dimension.hxx>
+
 #include <StdSelect_Shape.hxx>
+
 #include <TopoDS.hxx>
 #include <TopoDS_Vertex.hxx>
 
+namespace
+{
+  //=======================================================================
+  //function : HighlightMode
+  //purpose  : Return corresponding compute mode for selection type.
+  //=======================================================================
+  static AIS_Dimension::ComputeMode HighlightMode (const Standard_Integer theSelMode)
+  {
+    switch (theSelMode)
+    {
+      case AIS_DSM_Line : return AIS_Dimension::ComputeMode_Line;
+      case AIS_DSM_Text : return AIS_Dimension::ComputeMode_Text;
+      default:
+        return AIS_Dimension::ComputeMode_All;
+    }
+  }
+};
 
 //=======================================================================
 //function : Constructor
 //purpose  : 
 //=======================================================================
-
 AIS_DimensionOwner::AIS_DimensionOwner (const Handle(SelectMgr_SelectableObject)& theSelObject,
-                                        const AIS_DimensionDisplayMode theMode,
+                                        const AIS_DimensionSelectionMode theMode,
                                         const Standard_Integer thePriority)
 : SelectMgr_EntityOwner(theSelObject, thePriority),
-  myDisplayMode (theMode)
+  mySelectionMode (theMode)
 {
 }
 
 //=======================================================================
-//function : SetDisplayMode
+//function : AIS_DimensionSelectionMode
 //purpose  : 
 //=======================================================================
-
-void AIS_DimensionOwner::SetDisplayMode (const AIS_DimensionDisplayMode theMode)
+AIS_DimensionSelectionMode AIS_DimensionOwner::SelectionMode () const
 {
-  myDisplayMode = theMode;
-}
-
-//=======================================================================
-//function : DisplayMode
-//purpose  : 
-//=======================================================================
-
-AIS_DimensionDisplayMode AIS_DimensionOwner::DisplayMode () const
-{
-  return myDisplayMode;
+  return mySelectionMode;
 }
 
 //=======================================================================
 //function : IsHilighted
 //purpose  : 
 //=======================================================================
-
 Standard_Boolean AIS_DimensionOwner::IsHilighted (const Handle(PrsMgr_PresentationManager)& thePM,
-                                                  const Standard_Integer theMode) const
+                                                  const Standard_Integer /*theMode*/) const
 {
-  if (HasSelectable())
+  if (!HasSelectable())
   {
-    Standard_Integer aMode = myDisplayMode != 0 ? myDisplayMode : theMode;
-    return thePM->IsHighlighted(Selectable (), aMode);
+    return Standard_False;
   }
-  return Standard_False;
+
+  return thePM->IsHighlighted (Selectable(), HighlightMode (mySelectionMode));
 }
 
 //=======================================================================
 //function : Hilight
 //purpose  : 
 //=======================================================================
-
 void AIS_DimensionOwner::Hilight (const Handle(PrsMgr_PresentationManager)& thePM,
-                                  const Standard_Integer theMode)
+                                  const Standard_Integer /*theMode*/)
 {
-  if (HasSelectable())
+  if (!HasSelectable())
   {
-    Standard_Integer aMode = myDisplayMode != 0 ? myDisplayMode : theMode;
-    thePM->Highlight (Selectable(),aMode);
+    return;
   }
+
+  thePM->Highlight (Selectable(), HighlightMode (mySelectionMode));
 }
 
 //=======================================================================
 //function : Unhilight
 //purpose  : 
 //=======================================================================
-
 void AIS_DimensionOwner::Unhilight (const Handle(PrsMgr_PresentationManager)& thePM,
-                                    const Standard_Integer theMode)
+                                    const Standard_Integer /*theMode*/)
 {
-  if (HasSelectable())
+  if (!HasSelectable())
   {
-    Standard_Integer aMode = myDisplayMode != 0 ? myDisplayMode : theMode;
-    thePM->Unhighlight(Selectable(),aMode);
+    return;
   }
+
+  thePM->Unhighlight (Selectable(), HighlightMode (mySelectionMode));
 }
 
 //=======================================================================
 //function : HilightWithColor
 //purpose  : 
 //=======================================================================
-
 void AIS_DimensionOwner::HilightWithColor (const Handle(PrsMgr_PresentationManager3d)& thePM,
                                            const Quantity_NameOfColor theColor,
-                                           const Standard_Integer theMode)
+                                           const Standard_Integer /*theMode*/)
 {
-  // Highlight selectable part of dimension with color
-  if (myDisplayMode != 0)
-  {
-    thePM->Color (Selectable(), theColor, myDisplayMode);
-  }
-  else
-    thePM->Color (Selectable(), theColor, theMode);
+  thePM->Color (Selectable(), theColor, HighlightMode (mySelectionMode));
 }
index f602bb0..5705829 100755 (executable)
@@ -183,29 +183,29 @@ Standard_Boolean AIS_LengthDimension::initTwoEdgesLength (const TopoDS_Edge & th
   
   // Offset to avoid confusion Edge and Dimension
   gp_Vec anOffset(theDirAttach);
-  anOffset = anOffset*myDrawer->DimensionAspect()->ArrowAspect()->Length()*(-10.);
-  aCurPos.Translate(anOffset);
-  myGeom.myTextPosition = aCurPos;
+  anOffset = anOffset * myDrawer->DimensionAspect()->ArrowAspect()->Length()*(-10.);
+  aCurPos.Translate (anOffset);
+
   // Find attachment points
   if (!isFirstInfinite)
   {
-    if (myGeom.myTextPosition.Distance(aPoint11) > myGeom.myTextPosition.Distance(aPoint12))
+    if (aCurPos.Distance (aPoint11) > aCurPos.Distance (aPoint12))
       myFirstPoint = aPoint12;
     else
       myFirstPoint = aPoint11;
   }
   else
-    myFirstPoint = ElCLib::Value(ElCLib::Parameter(aLin1,myGeom.myTextPosition), aLin1);
+    myFirstPoint = ElCLib::Value (ElCLib::Parameter (aLin1, aCurPos), aLin1);
 
   if (!isSecondInfinite)
   {
-    if (myGeom.myTextPosition.Distance(aPoint21) > myGeom.myTextPosition.Distance(aPoint22))
+    if (aCurPos.Distance (aPoint21) > aCurPos.Distance (aPoint22))
       mySecondPoint = aPoint22;
     else
       mySecondPoint = aPoint21;
   }
   else
-    mySecondPoint = ElCLib::Value(ElCLib::Parameter(aLin2, myGeom.myTextPosition), aLin2);
+    mySecondPoint = ElCLib::Value (ElCLib::Parameter (aLin2, aCurPos), aLin2);
 
   return Standard_True;
 }
@@ -240,13 +240,13 @@ Standard_Boolean AIS_LengthDimension::initEdgeVertexLength (const TopoDS_Edge &
 
   if (!isInfinite)
   {
-    if (myGeom.myTextPosition.Distance(anEdgePoint1) > myGeom.myTextPosition.Distance(anEdgePoint2))
+    if (aCurPos.Distance (anEdgePoint1) > aCurPos.Distance (anEdgePoint2))
       mySecondPoint = anEdgePoint2;
     else
       mySecondPoint = anEdgePoint1;
   }
   else
-    mySecondPoint = ElCLib::Value(ElCLib::Parameter(aLin,myGeom.myTextPosition),aLin);
+    mySecondPoint = ElCLib::Value (ElCLib::Parameter (aLin, aCurPos), aLin);
   return Standard_True;
 }
 
@@ -326,8 +326,8 @@ Standard_Boolean AIS_LengthDimension::initEdgeFaceLength (const TopoDS_Edge& the
   else theDirAttach = gp::DZ ();
 
   gp_Vec aVector (theDirAttach);
-  aVector.Multiply (1.5 * myValue); 
-  myGeom.myTextPosition = mySecondPoint.Translated (aVector);
+  aVector.Multiply (1.5 * myValue);
+
   return Standard_True;
 }
 
@@ -395,9 +395,10 @@ Standard_Boolean AIS_LengthDimension::initTwoShapesPoints (const TopoDS_Shape& t
         }
         else // curvilinear faces
         {
-          AIS::ComputeLengthBetweenCurvilinearFaces (aFirstFace, aSecondFace, aFirstSurface, 
-                                                     aSecondSurface,Standard_True, myValue,
-                                                     myGeom.myTextPosition,myFirstPoint,mySecondPoint,aDirAttach);
+          AIS::ComputeLengthBetweenCurvilinearFaces (aFirstFace, aSecondFace, aFirstSurface,
+                                                     aSecondSurface, Standard_True, myValue,
+                                                     mySelectionGeom.TextPos, myFirstPoint,
+                                                     mySecondPoint, aDirAttach);
           isSuccess = Standard_True;
         }
       }
@@ -493,6 +494,9 @@ void AIS_LengthDimension::Compute (const Handle(PrsMgr_PresentationManager3d)& /
                                    const Handle(Prs3d_Presentation)& thePresentation,
                                    const Standard_Integer theMode)
 {
+  thePresentation->Clear();
+  mySelectionGeom.Clear (theMode);
+
   // Initialization of points, if they are not set
   if (!myIsInitialized)
   {
@@ -516,9 +520,7 @@ void AIS_LengthDimension::Compute (const Handle(PrsMgr_PresentationManager3d)& /
     return;
   }
 
-  thePresentation->Clear();
-
-  drawLinearDimension (thePresentation, (AIS_DimensionDisplayMode)theMode);
+  drawLinearDimension (thePresentation, theMode);
 }
 
 //=======================================================================
index 674566d..4988572 100644 (file)
@@ -60,7 +60,7 @@ class AIS_LengthDimension;
 
 DEFINE_STANDARD_HANDLE(AIS_LengthDimension,AIS_Dimension)
 
-//! A dimention  to display lengths. <br>
+//! A dimension  to display lengths. <br>
 //! These can be lengths along a face or edge, or <br>
 //! between two faces or two edges.
 class AIS_LengthDimension : public AIS_Dimension
index 06c7e07..b54771c 100755 (executable)
@@ -95,6 +95,7 @@ void AIS_RadiusDimension::Compute (const Handle(PrsMgr_PresentationManager3d)& /
                                    const Standard_Integer theMode)
 {
   thePresentation->Clear();
+  mySelectionGeom.Clear (theMode);
 
   Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
   Prs3d_Root::CurrentGroup (thePresentation)->SetPrimitivesAspect (aDimensionAspect->LineAspect()->Aspect());
@@ -117,7 +118,7 @@ void AIS_RadiusDimension::Compute (const Handle(PrsMgr_PresentationManager3d)& /
     countDefaultPlane();
   }
 
-  drawLinearDimension (thePresentation, (AIS_DimensionDisplayMode)theMode, Standard_True);
+  drawLinearDimension (thePresentation, theMode, Standard_True);
 }
 
 //=======================================================================
index ab0b04f..69a79f6 100644 (file)
@@ -48,6 +48,7 @@ Prs3d_DimensionAspect::Prs3d_DimensionAspect()
   myTextAspect->SetVerticalJustification (Graphic3d_VTA_CENTER);
   myArrowAspect = new Prs3d_ArrowAspect;
   myArrowAspect->SetColor (Quantity_NOC_LAWNGREEN);
+  myArrowAspect->SetAngle (M_PI * 20.0 / 180.0);
   myArrowAspect->SetLength (6.0);
   myExtensionSize = 6.0;
 }
index bf6f9a0..e0cbb64 100644 (file)
@@ -23,16 +23,24 @@ vpoint arrow_p2 50 0 0
 vpoint arrow_p3 100 0 0
 vpoint arrow_p4 150 0 0
 
-vpoint arrow_p5  0 0 50
-vpoint arrow_p6 10 0 50
+vpoint arrow_p5 100 0 50
+vpoint arrow_p6 127 0 50
 
-vpoint arrow_p7 100 0 50
-vpoint arrow_p8 127 0 50
+vpoint arrow_p7  0 0 50
+vpoint arrow_p8 10 0 50
 
+# test forced internal arrow orientation
 vdimension length name=arrow_d1 text=3d plane=zox label=hfit flyout=10.0 arrows=internal arrow_p1 arrow_p2
+
+# test forced external arrow orientation
 vdimension length name=arrow_d2 text=3d plane=zox label=hfit flyout=10.0 arrows=external arrow_p3 arrow_p4
-vdimension length name=arrow_d3 text=3d plane=zox label=hfit flyout=10.0 arrows=fit arrow_p5 arrow_p6
+
+# test that auto-fit for arrow places them externally for small geometry
+vdimension length name=arrow_d3 text=3d plane=zox label=hcenter flyout=10.0 arrows=fit arrow_p5 arrow_p6
+
+# test that auto-fit for text places the label externally for small geometry
 vdimension length name=arrow_d4 text=3d plane=zox label=hfit flyout=10.0 arrows=fit arrow_p7 arrow_p8
+
 vdisplay arrow_d1 arrow_d2 arrow_d3 arrow_d4
 vfit
 
index 98f0f79..a760b1c 100644 (file)
@@ -17,24 +17,28 @@ set vpos "above vcenter below"
 # create dimensions with different arrow orientation and fit algorithm
 # ---------------------------------------------------------------------
 
+# test forced internal arrow orientation
 vpoint  circle1_p1 0  0 30
 vpoint  circle1_p2 30 0  0
 vpoint  circle1_p3 60 0 30
 vcircle circle1 circle1_p1 circle1_p2 circle1_p3 0
 vdimension diameter name=diam1 text=3d plane=zox label=hfit flyout=0 arrows=internal circle1
 
+# test forced external arrow orientation
 vpoint  circle2_p1 100 0 30
 vpoint  circle2_p2 130 0  0
 vpoint  circle2_p3 160 0 30
 vcircle circle2 circle2_p1 circle2_p2 circle2_p3 0
 vdimension diameter name=diam2 text=3d plane=zox label=hfit flyout=0 arrows=external circle2
 
+# test that auto-fit for arrow places them externally for small geometry
 vpoint  circle3_p1 0  0 102
 vpoint  circle3_p2 22 0  80
 vpoint  circle3_p3 44 0 102
 vcircle circle3 circle3_p1 circle3_p2 circle3_p3 0
-vdimension diameter name=diam3 text=3d plane=zox label=hfit flyout=0 label=hfit arrows=fit circle3
+vdimension diameter name=diam3 text=3d plane=zox label=hcenter flyout=0 label=hfit arrows=fit circle3
 
+# test that auto-fit for text places the label externally for small geometry
 vpoint  circle4_p1 100 0 92
 vpoint  circle4_p2 112 0 80
 vpoint  circle4_p3 124 0 92
index c3c1766..0530d91 100644 (file)
@@ -17,24 +17,28 @@ set vpos "above vcenter below"
 # create dimensions with different arrow orientation and fit algorithm
 # ---------------------------------------------------------------------
 
+# test forced internal arrow orientation
 vpoint  circle1_p1 0  0 30
 vpoint  circle1_p2 30 0  0
 vpoint  circle1_p3 60 0 30
 vcircle circle1 circle1_p1 circle1_p2 circle1_p3 0
 vdimension radius name=rad1 text=3d plane=zox label=hfit flyout=0 arrows=internal circle1
 
-vpoint  circle2_p1 100 0 30
-vpoint  circle2_p2 130 0  0
-vpoint  circle2_p3 160 0 30
+# test forced external arrow orientation
+vpoint  circle2_p1 100 0 35
+vpoint  circle2_p2 135 0  0
+vpoint  circle2_p3 170 0 35
 vcircle circle2 circle2_p1 circle2_p2 circle2_p3 0
 vdimension radius name=rad2 text=3d plane=zox label=hfit flyout=0 arrows=external circle2
 
+# test that auto-fit for arrow places them externally for small geometry
 vpoint  circle3_p1 0  0 113
 vpoint  circle3_p2 33 0  80
 vpoint  circle3_p3 66 0 113
 vcircle circle3 circle3_p1 circle3_p2 circle3_p3 0
-vdimension radius name=rad3 text=3d plane=zox label=hfit flyout=0 arrows=fit circle3
+vdimension radius name=rad3 text=3d plane=zox label=hcenter flyout=0 arrows=fit circle3
 
+# test that auto-fit for text places the label externally for small geometry
 vpoint  circle4_p1 120 0 95
 vpoint  circle4_p2 135 0 80
 vpoint  circle4_p3 150 0 95
index 589ccfe..69721cb 100644 (file)
@@ -17,25 +17,29 @@ set vpos "above vcenter below"
 # create dimensions with different arrow orientation and fit algorithm
 # ---------------------------------------------------------------------
 
+# test forced internal arrow orientation
 vpoint  angle1_p1  0 0 40
 vpoint  angle1_p2  0 0  0
 vpoint  angle1_p3 40 0  0
 vdimension angle name=ang1 text=3d plane=zox label=hfit flyout=40.0 arrows=internal angle1_p1 angle1_p2 angle1_p3
 
+# test forced external arrow orientation
 vpoint  angle2_p1  80 0 40
 vpoint  angle2_p2  80 0  0
 vpoint  angle2_p3 120 0  0
 vdimension angle name=ang2 text=3d plane=zox label=hfit flyout=40.0 arrows=external angle2_p1 angle2_p2 angle2_p3
 
-vpoint  angle3_p1  0 0 115
+# test that auto-fit for arrow places them externally for small geometry
+vpoint  angle3_p1  0 0 100
 vpoint  angle3_p2  0 0  80
-vpoint  angle3_p3 35 0  80
-vdimension angle name=ang3 text=3d plane=zox label=hfit flyout=35.0 arrows=fit angle3_p1 angle3_p2 angle3_p3
-
-vpoint  angle4_p1  80 0 100
-vpoint  angle4_p2  80 0  80
-vpoint  angle4_p3 100 0  80
-vdimension angle name=ang4 text=3d plane=zox label=hfit flyout=20.0 arrows=fit angle4_p1 angle4_p2 angle4_p3
+vpoint  angle3_p3 20 0  80
+vdimension angle name=ang3 text=3d plane=zox label=hcenter flyout=20.0 arrows=fit angle3_p1 angle3_p2 angle3_p3
+
+# test that auto-fit for text places the label externally for small geometry
+vpoint  angle4_p1  85 0 100
+vpoint  angle4_p2  85 0  85
+vpoint  angle4_p3 100 0  85
+vdimension angle name=ang4 text=3d plane=zox label=hfit flyout=15.0 arrows=fit angle4_p1 angle4_p2 angle4_p3
 
 vdisplay ang1 ang2 ang3 ang4
 vfit
diff --git a/tests/bugs/vis/bug24389 b/tests/bugs/vis/bug24389
new file mode 100644 (file)
index 0000000..1e2b568
--- /dev/null
@@ -0,0 +1,251 @@
+puts "============"
+puts "CR24389"
+puts "============"
+puts ""
+#######################################################################
+#  Invalid hilight of AIS dimension line in local selection
+#######################################################################
+
+# ----------------------------------------------#
+#  Check highlight of length dimension elements #
+# ----------------------------------------------#
+
+vinit View1
+vtop
+
+set anImage1 $imagedir/${casename}_1.png
+set anImage2 $imagedir/${casename}_2.png
+set anImage3 $imagedir/${casename}_3.png
+
+# length
+
+vpoint len_p1  0 0 0
+vpoint len_p2 40 0 0
+verase len_p1 len_p2
+
+vdimension length name=len1 text=3d plane=xoy flyout=20 arrows=external label=left len_p1 len_p2
+vdimension length name=len2 text=3d plane=xoy flyout=-20 arrows=external label=right len_p1 len_p2
+
+vpoint len_p3  0 20 0
+vpoint len_p4 40 20 0
+verase len_p3 len_p4
+
+vdimension length name=len3 text=3d plane=xoy flyout=20 arrows=internal label=hcenter len_p3 len_p4
+vdisplay len1 len2 len3
+
+# diameter
+
+vpoint diam_p1  90 0   0
+vpoint diam_p2 120 0   0
+vpoint diam_p3 105 -15 0
+verase diam_p1 diam_p2 diam_p3
+vcircle diam_c1 diam_p1 diam_p2 diam_p3 0
+vdimension diameter name=diam1 text=3d plane=xoy arrows=external label=left diam_c1
+
+vpoint diam_p4  90 40 0
+vpoint diam_p5 120 40 0
+vpoint diam_p6 105 25 0
+verase diam_p4 diam_p5 diam_p6
+vcircle diam_c2 diam_p4 diam_p5 diam_p6 0
+vdimension diameter name=diam2 text=3d plane=xoy arrows=external label=right diam_c2
+
+vpoint diam_p7  80 -40 0
+vpoint diam_p8 120 -40 0
+vpoint diam_p9 100 -60 0
+verase diam_p7 diam_p8 diam_p9
+vcircle diam_c3 diam_p7 diam_p8 diam_p9 0
+vdimension diameter name=diam3 text=3d plane=xoy arrows=external label=hcenter flyout=30 diam_c3
+vdisplay diam1 diam2 diam3
+
+# radius
+
+vpoint rad_p1 140  -5 0
+vpoint rad_p2 180 -45 0
+vpoint rad_p3 220  -5 0
+verase rad_p1 rad_p2 rad_p3
+vcircle rad_c1 rad_p1 rad_p2 rad_p3 0
+vdimension radius name=rad1 text=3d plane=xoy arrows=internal label=hcenter flyout=0 rad_c1
+
+vpoint rad_p4 180 -70 0
+vpoint rad_p5 160 -90 0
+vpoint rad_p6 140 -70 0
+verase rad_p4 rad_p5 rad_p6
+vcircle rad_c2 rad_p4 rad_p5 rad_p6 0
+vdimension radius name=rad2 text=3d plane=xoy arrows=external label=left rad_c2
+vdisplay rad1 rad2
+
+# angles
+
+vpoint ang_p1 0  -50 0
+vpoint ang_p2 25 -75 0
+vpoint ang_p3 0  -100 0
+verase ang_p1 ang_p2 ang_p3
+vdimension angle name=ang1 text=3d plane=xoy arrows=internal label=hcenter flyout=35 ang_p1 ang_p2 ang_p3
+
+vpoint ang_p4   0 -120 0
+vpoint ang_p5  30 -80  0
+vpoint ang_p6  30 -120 0
+verase ang_p4 ang_p5 ang_p6
+vdimension angle name=ang2 text=3d plane=xoy arrows=external label=left flyout=55 ang_p4 ang_p5 ang_p6
+
+vpoint ang_p8  55 -120 0
+vpoint ang_p9  55 -80  0
+vpoint ang_p10 95 -120 0
+verase ang_p8 ang_p9 ang_p10
+vdimension angle name=ang3 text=3d plane=xoy arrows=external label=right flyout=55 ang_p8 ang_p9 ang_p10
+
+vdisplay ang1 ang2 ang3
+vpoint fit1 -75 0 0
+vpoint fit2 235 0 0
+vfit
+
+# ----------------------------------------------------------------------------- #
+#               Verify picking in neutral and local selections                  #
+# ----------------------------------------------------------------------------- #
+
+proc check_picking { pick check name } {
+  for {set i 0} {$i < [llength $pick]} {incr i} {
+  
+    set pick_x [lindex [lindex $pick $i] 0]
+    set pick_y [lindex [lindex $pick $i] 1]
+    set check_x [lindex $check 0]
+    set check_y [lindex $check 1]
+    
+    vmoveto $pick_x $pick_y
+    set res [checkcolor $check_x $check_y 0 1 1]
+    
+    if { $res != 1 } {
+      puts "Error : Highlighting of $name at pick coordinates ($pick_x, $pick_y) check coordinates ($check_x, $check_y)"
+    }
+  }
+}
+
+proc check_cross_picking { pick object name } {
+
+  vselmode 0 0
+
+  for {set i 1} {$i < 3} {incr i} {
+    
+    vselmode $object $i 1
+
+    for {set j 1} {$j < 3} {incr j} {
+
+      set pick_idx_i [expr "[llength $pick] - 2 + $i - 1"]
+      set pick_idx_j [expr "[llength $pick] - 2 + $j - 1"]
+
+      set pick_x [lindex [lindex $pick $pick_idx_i] 0]
+      set pick_y [lindex [lindex $pick $pick_idx_i] 1]
+      set check_x [lindex [lindex $pick $pick_idx_j] 0]
+      set check_y [lindex [lindex $pick $pick_idx_j] 1]
+      
+      vmoveto $pick_x $pick_y
+      
+      if {$i == $j} {
+        set res [checkcolor $check_x $check_y 0 1 1]
+        if { $res != 1 } {
+          puts "Error : No local hilighting of $name at pick coordinates ($pick_x, $pick_y) check coordinates ($check_x, $check_y)"
+        }
+      } else {
+        set res [checkcolor $check_x $check_y 0 0 0]
+        if { $res != 1 } {
+          puts "Error : Unwanted hilighting of $name at pick coordinates ($pick_x, $pick_y) check coordinates ($check_x, $check_y)"
+        }
+      }
+    }
+    vselmode $object $i 0
+  }
+  vselmode 0 0
+}
+
+# pick coord { [flyout], dimension line, text }
+
+# check sensitives "len1"
+set pick_coord { { 99 133 } { 106 124 } { 76 131 } }
+set check_coord { 125 124 }
+check_picking $pick_coord $check_coord "length dimension (len1)"
+check_cross_picking $pick_coord len1 "length dimension (len1)"
+
+# check sensitives "len2"
+set pick_coord { { 99 167 } { 127 176 } { 185 183 } }
+set check_coord { 112 176 }
+check_picking $pick_coord $check_coord "length dimension (len2)"
+check_cross_picking $pick_coord len2 "length dimension (len2)"
+
+# check sensitives "len3"
+set pick_coord { { 99 114 } { 110 98 } { 131 105 } }
+set check_coord { 152 109 }
+check_picking $pick_coord $check_coord "length dimension (len3)"
+check_cross_picking $pick_coord len3 "length dimension (len3)"
+
+# check sensitives "diam1"
+set pick_coord { { 247 150 } { 194 157 } }
+set check_coord { 236 150 }
+check_picking $pick_coord $check_coord "diameter dimension (diam1)"
+check_cross_picking $pick_coord diam1 "diameter dimension (diam1)"
+
+# check sensitives "diam2"
+set pick_coord { { 221 98 } { 305 105 } }
+set check_coord { 238 98 }
+check_picking $pick_coord $check_coord "diameter dimension (diam2)"
+check_cross_picking $pick_coord diam2 "diameter dimension (diam2)"
+
+# check sensitives "diam3"
+set pick_coord { { 204 225 } { 268 242 } { 243 249 } }
+set check_coord { 204 233 }
+check_picking $pick_coord $check_coord "diameter dimension (diam3)"
+check_cross_picking $pick_coord diam3 "diameter dimension (diam3)"
+
+# check sensitives "rad1"
+set pick_coord { { 287 157 } { 326 165 } }
+set check_coord { 287 157 }
+check_picking $pick_coord $check_coord "radius dimension (rad1)"
+check_cross_picking $pick_coord rad1 "radius dimension (rad1)"
+
+# check sensitives "rad2"
+set pick_coord { { 320 242 } { 383 249 } }
+set check_coord { 340 242 }
+check_picking $pick_coord $check_coord "radius dimension (rad2)"
+check_cross_picking $pick_coord rad2 "radius dimension (rad2)"
+
+# check sensitives "ang1"
+set pick_coord { { 112 268 } { 96 220 } { 80 250 } }
+set check_coord { 96 220 }
+check_picking $pick_coord $check_coord "angle dimension (ang1)"
+check_cross_picking $pick_coord ang1 "angle dimension (ang1)"
+
+# check sensitives "ang2"
+set pick_coord { { 139 301 } { 152 327 } { 65 297 } }
+set check_coord { 108 320 }
+check_picking $pick_coord $check_coord "angle dimension (ang2)"
+check_cross_picking $pick_coord ang2 "angle dimension (ang2)"
+
+# check sensitives "ang3"
+set pick_coord { { 171 304 } { 199 321 } { 252 285 } }
+set check_coord { 191 324 }
+check_picking $pick_coord $check_coord "angle dimension (ang3)"
+check_cross_picking $pick_coord ang3 "angle dimension (ang3)"
+
+# --------------------------------------------------- #
+#               Dump selected images                  #
+# --------------------------------------------------- #
+
+set xmin -500
+set xmax  500
+set ymin -500
+set ymax  500
+set shift 0
+
+vselmode 0 0
+vselect $xmin $ymin $xmax $ymax $shift
+vdump $anImage1
+
+vselect 0 0 0 0 0
+vselmode 1 1
+vselect $xmin $ymin $xmax $ymax $shift
+vdump $anImage2
+
+vselect 0 0 0 0 0
+vselmode 0 0
+vselmode 2 1
+vselect $xmin $ymin $xmax $ymax $shift
+vdump $anImage3