0024624: Lost word in license statement in source files
[occt.git] / src / AIS / AIS_AngleDimension.cxx
old mode 100755 (executable)
new mode 100644 (file)
index a274ef4..48b182a
@@ -1,22 +1,18 @@
 // Created on: 1996-12-05
 // Created by: Arnaud BOUZY/Odile Olivier
 // Copyright (c) 1996-1999 Matra Datavision
-// Copyright (c) 1999-2012 OPEN CASCADE SAS
+// Copyright (c) 1999-2014 OPEN CASCADE SAS
 //
-// The content of this file is subject to the Open CASCADE Technology Public
-// License Version 6.5 (the "License"). You may not use the content of this file
-// except in compliance with the License. Please obtain a copy of the License
-// at http://www.opencascade.org and read it completely before using this file.
+// This file is part of Open CASCADE Technology software library.
 //
-// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
-// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
 //
-// The Original Code and all software distributed under the License is
-// distributed on an "AS IS" basis, without warranty of any kind, and the
-// Initial Developer hereby disclaims all such warranties, including without
-// limitation, any warranties of merchantability, fitness for a particular
-// purpose or non-infringement. Please see the License for the specific terms
-// and conditions governing the rights and limitations under the License.
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
 
 #include <AIS_AngleDimension.hxx>
 
@@ -52,6 +48,7 @@
 #include <Select3D_SensitiveGroup.hxx>
 #include <Select3D_SensitiveSegment.hxx>
 #include <SelectMgr_Selection.hxx>
+#include <Standard_ProgramError.hxx>
 #include <UnitsAPI.hxx>
 
 IMPLEMENT_STANDARD_HANDLE (AIS_AngleDimension, AIS_Dimension)
@@ -156,7 +153,7 @@ void AIS_AngleDimension::SetMeasuredGeometry (const TopoDS_Edge& theFirstEdge,
 
   if (myIsValid && !myIsPlaneCustom)
   {
-    myPlane = aComputedPlane;
+    ComputePlane();
   }
 
   myIsValid &= CheckPlane (myPlane);
@@ -304,7 +301,7 @@ void AIS_AngleDimension::Init()
 //=======================================================================
 gp_Pnt AIS_AngleDimension::GetCenterOnArc (const gp_Pnt& theFirstAttach,
                                            const gp_Pnt& theSecondAttach,
-                                           const gp_Pnt& theCenter)
+                                           const gp_Pnt& theCenter) const
 {
   // construct plane where the circle and the arc are located
   gce_MakePln aConstructPlane (theFirstAttach, theSecondAttach, theCenter);
@@ -587,7 +584,7 @@ Standard_Real AIS_AngleDimension::ComputeValue() const
 
   Standard_Real anAngle = aVec2.AngleWithRef (aVec1, GetPlane().Axis().Direction());
 
-  return anAngle > 0.0 ? anAngle : (2.0 * M_PI - anAngle);
+  return anAngle > 0.0 ? anAngle : (2.0 * M_PI + anAngle);
 }
 
 //=======================================================================
@@ -623,31 +620,23 @@ void AIS_AngleDimension::Compute (const Handle(PrsMgr_PresentationManager3d)& /*
     aLabelWidth += aDimensionAspect->TextAspect()->Height() * THE_3D_TEXT_MARGIN * 2.0;
   }
 
-  gp_Pnt aFirstAttach = myCenterPoint.Translated (gp_Vec(myCenterPoint, myFirstPoint).Normalized() * GetFlyout());
-  gp_Pnt aSecondAttach = myCenterPoint.Translated (gp_Vec(myCenterPoint, mySecondPoint).Normalized() * GetFlyout());
+  // Get parameters from aspect or adjust it according with custom text position
+  Standard_Real anExtensionSize = aDimensionAspect->ExtensionSize();
+  Prs3d_DimensionTextHorizontalPosition aHorisontalTextPos = aDimensionAspect->TextHorizontalPosition();
 
-  // Handle user-defined and automatic arrow placement
-  bool isArrowsExternal = false;
-  switch (aDimensionAspect->ArrowOrientation())
+  if (IsTextPositionCustom())
   {
-    case Prs3d_DAO_External: isArrowsExternal = true; break;
-    case Prs3d_DAO_Internal: isArrowsExternal = false; break;
-    case Prs3d_DAO_Fit:
-    {
-      gp_Vec anAttachVector (aFirstAttach, aSecondAttach);
-      Standard_Real aDimensionWidth = anAttachVector.Magnitude();
+    AdjustParameters (myFixedTextPosition,anExtensionSize, aHorisontalTextPos);
+  }
 
-      // 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;
+  // Handle user-defined and automatic arrow placement
+  Standard_Boolean isArrowsExternal = Standard_False;
+  Standard_Integer aLabelPosition = LabelPosition_None;
 
-      Standard_Real anArrowsWidth   = (anArrowLength + anArrowMargin) * 2.0;
+  FitTextAlignment (aHorisontalTextPos, aLabelPosition, isArrowsExternal);
 
-      isArrowsExternal = aDimensionWidth < aLabelWidth + anArrowsWidth;
-      break;
-    }
-  }
+  gp_Pnt aFirstAttach = myCenterPoint.Translated (gp_Vec(myCenterPoint, myFirstPoint).Normalized() * GetFlyout());
+  gp_Pnt aSecondAttach = myCenterPoint.Translated (gp_Vec(myCenterPoint, mySecondPoint).Normalized() * GetFlyout());
 
   //Arrows positions and directions
   gp_Vec aWPDir = gp_Vec (GetPlane().Axis().Direction());
@@ -674,38 +663,9 @@ void AIS_AngleDimension::Compute (const Handle(PrsMgr_PresentationManager3d)& /*
   aFirstArrowEnd    = aFirstAttach.Translated (-aFirstArrowVec);
   aSecondArrowEnd   = aSecondAttach.Translated (-aSecondArrowVec);
 
-  Standard_Integer aLabelPosition = LabelPosition_None;
-
-  // Handle user-defined and automatic text placement
-  switch (aDimensionAspect->TextHorizontalPosition())
-  {
-    case Prs3d_DTHP_Left  : aLabelPosition |= LabelPosition_Left; break;
-    case Prs3d_DTHP_Right : aLabelPosition |= LabelPosition_Right; break;
-    case Prs3d_DTHP_Center: aLabelPosition |= LabelPosition_HCenter; break;
-    case Prs3d_DTHP_Fit:
-    {
-      gp_Vec anAttachVector (aFirstAttach, aSecondAttach);
-      Standard_Real aDimensionWidth = anAttachVector.Magnitude();
-      Standard_Real anArrowsWidth   = anArrowLength * 2.0;
-      Standard_Real aContentWidth   = isArrowsExternal ? aLabelWidth : aLabelWidth + anArrowsWidth;
-
-      aLabelPosition |= aDimensionWidth < aContentWidth ? LabelPosition_Left : LabelPosition_HCenter;
-      break;
-    }
-  }
-
-  switch (aDimensionAspect->TextVerticalPosition())
-  {
-    case Prs3d_DTVP_Above  : aLabelPosition |= LabelPosition_Above; break;
-    case Prs3d_DTVP_Below  : aLabelPosition |= LabelPosition_Below; break;
-    case Prs3d_DTVP_Center : aLabelPosition |= LabelPosition_VCenter; break;
-  }
-
   // Group1: stenciling text and the angle dimension arc
   Prs3d_Root::NewGroup (thePresentation);
 
-  Standard_Real anExtensionSize = aDimensionAspect->ExtensionSize();
-
   Standard_Integer aHPosition = aLabelPosition & LabelPosition_HMask;
 
   // draw text label
@@ -733,7 +693,8 @@ void AIS_AngleDimension::Compute (const Handle(PrsMgr_PresentationManager3d)& /*
       if (theMode == ComputeMode_All || theMode == ComputeMode_Text)
       {
         gp_Vec aDimensionDir (aFirstAttach, aSecondAttach);
-        gp_Pnt aTextPos = GetCenterOnArc (aFirstAttach, aSecondAttach, myCenterPoint);
+        gp_Pnt aTextPos = IsTextPositionCustom() ? myFixedTextPosition
+                                                : GetCenterOnArc (aFirstAttach, aSecondAttach, myCenterPoint);
         gp_Dir aTextDir = aDimensionDir;
 
         DrawText (thePresentation,
@@ -811,7 +772,7 @@ void AIS_AngleDimension::Compute (const Handle(PrsMgr_PresentationManager3d)& /*
     if (aHPosition != LabelPosition_Left)
     {
       DrawExtension (thePresentation,
-                     anExtensionSize,
+                     aDimensionAspect->ArrowTailSize(),
                      aFirstArrowEnd,
                      aFirstExtensionDir,
                      THE_EMPTY_LABEL_STRING,
@@ -823,7 +784,7 @@ void AIS_AngleDimension::Compute (const Handle(PrsMgr_PresentationManager3d)& /*
     if (aHPosition != LabelPosition_Right)
     {
       DrawExtension (thePresentation,
-                     anExtensionSize,
+                     aDimensionAspect->ArrowTailSize(),
                      aSecondArrowEnd,
                      aSecondExtensionDir,
                      THE_EMPTY_LABEL_STRING,
@@ -1188,3 +1149,272 @@ Standard_Boolean AIS_AngleDimension::IsValidPoints (const gp_Pnt& theFirstPoint,
       && gp_Vec (theCenterPoint, theFirstPoint).Angle (
            gp_Vec (theCenterPoint, theSecondPoint)) > Precision::Angular();
 }
+
+//=======================================================================
+//function : GetTextPosition
+//purpose  : 
+//=======================================================================
+const gp_Pnt AIS_AngleDimension::GetTextPosition() const
+{
+  if (!IsValid())
+  {
+    return gp::Origin();
+  }
+
+  if (IsTextPositionCustom())
+  {
+    return myFixedTextPosition;
+  }
+
+  // Counts text position according to the dimension parameters
+  gp_Pnt aTextPosition (gp::Origin());
+
+  Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
+
+  // Prepare label string and compute its geometrical width
+  Standard_Real aLabelWidth;
+  TCollection_ExtendedString aLabelString = GetValueString (aLabelWidth);
+
+  gp_Pnt aFirstAttach = myCenterPoint.Translated (gp_Vec(myCenterPoint, myFirstPoint).Normalized() * GetFlyout());
+  gp_Pnt aSecondAttach = myCenterPoint.Translated (gp_Vec(myCenterPoint, mySecondPoint).Normalized() * GetFlyout());
+
+  // Handle user-defined and automatic arrow placement
+  Standard_Boolean isArrowsExternal = Standard_False;
+  Standard_Integer aLabelPosition = LabelPosition_None;
+  FitTextAlignment (aDimensionAspect->TextHorizontalPosition(),
+                    aLabelPosition, isArrowsExternal);
+
+  // Get text position
+  switch (aLabelPosition & LabelPosition_HMask)
+  {
+  case LabelPosition_HCenter:
+    {
+      aTextPosition = GetCenterOnArc (aFirstAttach, aSecondAttach, myCenterPoint);
+    }
+    break;
+  case LabelPosition_Left:
+    {
+      gp_Dir aPlaneNormal = gp_Vec (aFirstAttach, aSecondAttach) ^ gp_Vec (myCenterPoint, aFirstAttach);
+      gp_Dir anExtensionDir = aPlaneNormal ^ gp_Vec (myCenterPoint, aFirstAttach);
+      Standard_Real anExtensionSize = aDimensionAspect->ExtensionSize();
+      Standard_Real anOffset = isArrowsExternal
+          ? anExtensionSize + aDimensionAspect->ArrowAspect()->Length()
+          : anExtensionSize;
+      gp_Vec anExtensionVec  = gp_Vec (anExtensionDir) * -anOffset;
+      aTextPosition = aFirstAttach.Translated (anExtensionVec);
+    }
+    break;
+  case LabelPosition_Right:
+    {
+      gp_Dir aPlaneNormal = gp_Vec (aFirstAttach, aSecondAttach) ^ gp_Vec (myCenterPoint, aFirstAttach);
+      gp_Dir anExtensionDir = aPlaneNormal ^ gp_Vec (myCenterPoint, aSecondAttach);
+      Standard_Real anExtensionSize = aDimensionAspect->ExtensionSize();
+      Standard_Real anOffset = isArrowsExternal
+          ? anExtensionSize + aDimensionAspect->ArrowAspect()->Length()
+          : anExtensionSize;
+      gp_Vec anExtensionVec  = gp_Vec (anExtensionDir) * anOffset;
+      aTextPosition = aSecondAttach.Translated (anExtensionVec);
+    }
+    break;
+  }
+
+  return aTextPosition;
+}
+
+//=======================================================================
+//function : SetTextPosition
+//purpose  : 
+//=======================================================================
+void AIS_AngleDimension::SetTextPosition (const gp_Pnt& theTextPos)
+{
+  if (!IsValid())
+  {
+    return;
+  }
+
+  // The text position point for angle dimension should belong to the working plane.
+  if (!GetPlane().Contains (theTextPos, Precision::Confusion()))
+  {
+    Standard_ProgramError::Raise ("The text position point for angle dimension doesn't belong to the working plane.");
+  }
+
+  myIsTextPositionFixed = Standard_True;
+  myFixedTextPosition = theTextPos;
+}
+
+//=======================================================================
+//function : AdjustAspectParameters
+//purpose  : 
+//=======================================================================
+void AIS_AngleDimension::AdjustParameters (const gp_Pnt& theTextPos,
+                                           Standard_Real& theExtensionSize,
+                                           Prs3d_DimensionTextHorizontalPosition& theAlignment)
+{
+  Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
+  Standard_Real anArrowLength = aDimensionAspect->ArrowAspect()->Length();
+
+  // Compute flyout direction vector.
+  gp_Dir aPlaneNormal = GetPlane().Axis().Direction();
+  gp_Dir aTargetPointsDir = gce_MakeDir (myFirstPoint, mySecondPoint);
+
+  // Build circle with radius that is equal to distance from text position to the center point.
+  Standard_Real aRadius = gp_Vec (myCenterPoint, theTextPos).Magnitude();
+
+  // Set attach points in positive direction of the flyout.
+  gp_Pnt aFirstAttach = myCenterPoint.Translated (gp_Vec (myCenterPoint, myFirstPoint).Normalized() * aRadius);
+  gp_Pnt aSecondAttach = myCenterPoint.Translated (gp_Vec (myCenterPoint, mySecondPoint).Normalized() * aRadius);
+
+  gce_MakeCirc aConstructCircle (myCenterPoint, GetPlane(), aRadius);
+  if (!aConstructCircle.IsDone())
+  {
+    return;
+  }
+  gp_Circ aCircle = aConstructCircle.Value();
+
+  // Default values
+  theExtensionSize = aDimensionAspect->ArrowAspect()->Length();
+  theAlignment = Prs3d_DTHP_Center;
+
+  Standard_Real aParamBeg = ElCLib::Parameter (aCircle, aFirstAttach);
+  Standard_Real aParamEnd = ElCLib::Parameter (aCircle, aSecondAttach);
+  if (aParamEnd < aParamBeg)
+  {
+    Standard_Real aParam = aParamEnd;
+    aParamEnd = aParamBeg;
+    aParamBeg = aParam;
+  }
+
+  ElCLib::AdjustPeriodic (0.0, M_PI * 2, Precision::PConfusion(), aParamBeg, aParamEnd);
+  Standard_Real aTextPar = ElCLib::Parameter (aCircle , theTextPos);
+
+  // Horizontal center
+  if (aTextPar > aParamBeg && aTextPar < aParamEnd)
+  {
+    myFlyout = aRadius;
+
+    SetToUpdate();
+    return;
+  }
+
+  aParamBeg += M_PI;
+  aParamEnd += M_PI;
+  ElCLib::AdjustPeriodic (0.0, M_PI * 2, Precision::PConfusion(), aParamBeg, aParamEnd);
+
+  if (aTextPar > aParamBeg  && aTextPar < aParamEnd)
+  {
+    myFlyout = -aRadius;
+
+    SetToUpdate();
+    return;
+  }
+
+  // Text on the extensions
+  gp_Lin aFirstLine = gce_MakeLin (myCenterPoint, myFirstPoint);
+  gp_Lin aSecondLine = gce_MakeLin (myCenterPoint, mySecondPoint);
+  gp_Pnt aFirstTextProj = AIS::Nearest (aFirstLine, theTextPos);
+  gp_Pnt aSecondTextProj = AIS::Nearest (aSecondLine, theTextPos);
+  Standard_Real aFirstDist = aFirstTextProj.Distance (theTextPos);
+  Standard_Real aSecondDist = aSecondTextProj.Distance (theTextPos);
+
+  if (aFirstDist <= aSecondDist)
+  {
+    aRadius = myCenterPoint.Distance (aFirstTextProj);
+    Standard_Real aNewExtensionSize = aFirstDist - anArrowLength;
+    theExtensionSize = aNewExtensionSize < 0.0 ? 0.0 : aNewExtensionSize;
+
+    theAlignment = Prs3d_DTHP_Left;
+
+    gp_Vec aPosFlyoutDir = gp_Vec (myCenterPoint, myFirstPoint).Normalized().Scaled (aRadius);
+
+    myFlyout = aFirstTextProj.Distance (myCenterPoint.Translated (aPosFlyoutDir)) > Precision::Confusion()
+                ? -aRadius : aRadius;
+  }
+  else
+  {
+    aRadius = myCenterPoint.Distance (aSecondTextProj);
+
+    Standard_Real aNewExtensionSize = aSecondDist - anArrowLength;
+
+    theExtensionSize = aNewExtensionSize < 0.0 ? 0.0 : aNewExtensionSize;
+
+    theAlignment = Prs3d_DTHP_Right;
+
+    gp_Vec aPosFlyoutDir = gp_Vec (myCenterPoint, mySecondPoint).Normalized().Scaled (aRadius);
+
+    myFlyout = aSecondTextProj.Distance (myCenterPoint.Translated (aPosFlyoutDir)) > Precision::Confusion()
+                ? -aRadius : aRadius;
+  }
+}
+
+//=======================================================================
+//function : FitTextAlignment
+//purpose  : 
+//=======================================================================
+void AIS_AngleDimension::FitTextAlignment (const Prs3d_DimensionTextHorizontalPosition& theHorizontalTextPos,
+                                           Standard_Integer& theLabelPosition,
+                                           Standard_Boolean& theIsArrowsExternal) const
+{
+  Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
+
+  Quantity_Length anArrowLength = aDimensionAspect->ArrowAspect()->Length();
+
+  // Prepare label string and compute its geometrical width
+  Standard_Real aLabelWidth;
+  TCollection_ExtendedString aLabelString = GetValueString (aLabelWidth);
+
+  // add margins to label width
+  if (aDimensionAspect->IsText3d())
+  {
+    aLabelWidth += aDimensionAspect->TextAspect()->Height() * THE_3D_TEXT_MARGIN * 2.0;
+  }
+
+  gp_Pnt aFirstAttach = myCenterPoint.Translated (gp_Vec (myCenterPoint, myFirstPoint).Normalized() * GetFlyout());
+  gp_Pnt aSecondAttach = myCenterPoint.Translated (gp_Vec (myCenterPoint, mySecondPoint).Normalized() * GetFlyout());
+
+  // Handle user-defined and automatic arrow placement
+  switch (aDimensionAspect->ArrowOrientation())
+  {
+    case Prs3d_DAO_External: theIsArrowsExternal = true; break;
+    case Prs3d_DAO_Internal: theIsArrowsExternal = false; break;
+    case Prs3d_DAO_Fit:
+    {
+      gp_Vec anAttachVector (aFirstAttach, aSecondAttach);
+      Standard_Real aDimensionWidth = anAttachVector.Magnitude();
+
+      // 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;
+
+      theIsArrowsExternal = aDimensionWidth < aLabelWidth + anArrowsWidth;
+      break;
+    }
+  }
+
+  // Handle user-defined and automatic text placement
+  switch (theHorizontalTextPos)
+  {
+    case Prs3d_DTHP_Left  : theLabelPosition |= LabelPosition_Left; break;
+    case Prs3d_DTHP_Right : theLabelPosition |= LabelPosition_Right; break;
+    case Prs3d_DTHP_Center: theLabelPosition |= LabelPosition_HCenter; break;
+    case Prs3d_DTHP_Fit:
+    {
+      gp_Vec anAttachVector (aFirstAttach, aSecondAttach);
+      Standard_Real aDimensionWidth = anAttachVector.Magnitude();
+      Standard_Real anArrowsWidth   = anArrowLength * 2.0;
+      Standard_Real aContentWidth   = theIsArrowsExternal ? aLabelWidth : aLabelWidth + anArrowsWidth;
+
+      theLabelPosition |= aDimensionWidth < aContentWidth ? LabelPosition_Left : LabelPosition_HCenter;
+      break;
+    }
+  }
+
+  switch (aDimensionAspect->TextVerticalPosition())
+  {
+    case Prs3d_DTVP_Above  : theLabelPosition |= LabelPosition_Above; break;
+    case Prs3d_DTVP_Below  : theLabelPosition |= LabelPosition_Below; break;
+    case Prs3d_DTVP_Center : theLabelPosition |= LabelPosition_VCenter; break;
+  }
+}