// 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>
#include <AIS.hxx>
-#include <AIS_Dimension.hxx>
-#include <AIS_DimensionOwner.hxx>
-#include <AIS_Drawer.hxx>
-#include <BRep_Tool.hxx>
#include <BRepBuilderAPI_MakeFace.hxx>
#include <BRepAdaptor_Curve.hxx>
#include <BRepAdaptor_Surface.hxx>
#include <BRepLib_MakeVertex.hxx>
-
-#include <DsgPrs.hxx>
-#include <DsgPrs_AnglePresentation.hxx>
-
+#include <BRep_Tool.hxx>
#include <ElCLib.hxx>
-#include <ElSLib.hxx>
-
-#include <GC_MakeCircle.hxx>
-#include <GC_MakeConicalSurface.hxx>
-#include <gce_MakeLin.hxx>
+#include <GCPnts_UniformAbscissa.hxx>
+#include <GC_MakeArcOfCircle.hxx>
#include <gce_MakeLin2d.hxx>
-#include <gce_MakePln.hxx>
+#include <gce_MakeLin.hxx>
#include <gce_MakeCirc.hxx>
#include <gce_MakeCone.hxx>
-#include <Geom2d_Circle.hxx>
-#include <Geom2d_Curve.hxx>
-#include <Geom2d_Line.hxx>
-#include <Geom2dAPI_ExtremaCurveCurve.hxx>
-#include <GeomAPI.hxx>
+#include <gce_MakePln.hxx>
+#include <gce_MakeDir.hxx>
#include <Geom_Circle.hxx>
-#include <Geom_Line.hxx>
-#include <Geom_Plane.hxx>
#include <Geom_TrimmedCurve.hxx>
-#include <Geom_Surface.hxx>
-#include <Geom_CylindricalSurface.hxx>
#include <Geom_ConicalSurface.hxx>
#include <Geom_SurfaceOfRevolution.hxx>
-#include <Geom_SurfaceOfLinearExtrusion.hxx>
#include <Geom_OffsetSurface.hxx>
-#include <GeomAPI_ExtremaCurveCurve.hxx>
#include <Graphic3d_ArrayOfSegments.hxx>
-#include <Graphic3d_AspectLine3d.hxx>
-#include <gp.hxx>
-#include <gp_Ax1.hxx>
-#include <gp_Lin.hxx>
-#include <gp_Cone.hxx>
-#include <gp_Pln.hxx>
-#include <gp_Pnt.hxx>
-#include <gp_Pnt2d.hxx>
-#include <gp_Vec.hxx>
-#include <gp_XYZ.hxx>
#include <Graphic3d_Group.hxx>
-#include <Graphic3d_ArrayOfPrimitives.hxx>
#include <Graphic3d_ArrayOfPolylines.hxx>
-
#include <IntAna2d_AnaIntersection.hxx>
-#include <IntAna2d_IntPoint.hxx>
-#include <IntAna_QuadQuadGeo.hxx>
-#include <IntAna_ResultType.hxx>
-#include <Poly_Polygon3D.hxx>
-#include <Precision.hxx>
#include <ProjLib.hxx>
-#include <Prs3d_ArrowAspect.hxx>
-#include <Prs3d_DimensionAspect.hxx>
-#include <Prs3d_Drawer.hxx>
#include <Prs3d_Root.hxx>
+#include <Prs3d_ShadingAspect.hxx>
#include <PrsMgr_PresentationManager3d.hxx>
-#include <Select3D_SensitiveCurve.hxx>
+#include <Select3D_SensitiveGroup.hxx>
#include <Select3D_SensitiveSegment.hxx>
-#include <Select3D_SensitiveBox.hxx>
-#include <SelectMgr_EntityOwner.hxx>
#include <SelectMgr_Selection.hxx>
-#include <Standard_NotImplemented.hxx>
-#include <Standard_Type.hxx>
-#include <Standard_Macro.hxx>
-#include <Standard_DefineHandle.hxx>
-
-#include <TColStd_Array1OfReal.hxx>
-#include <TopExp.hxx>
-#include <TopExp_Explorer.hxx>
-#include <TopoDS.hxx>
-#include <TopoDS_Shape.hxx>
-#include <TopoDS_Vertex.hxx>
+#include <Standard_ProgramError.hxx>
#include <UnitsAPI.hxx>
+#include <Geom_Line.hxx>
+#include <Geom_Plane.hxx>
-IMPLEMENT_STANDARD_HANDLE (AIS_AngleDimension, AIS_Dimension)
-IMPLEMENT_STANDARD_RTTIEXT (AIS_AngleDimension, AIS_Dimension)
-//=======================================================================
-//function : init
-//purpose : Private constructor for default initialization
-//=======================================================================
+IMPLEMENT_STANDARD_RTTIEXT(AIS_AngleDimension,AIS_Dimension)
-void AIS_AngleDimension::init()
+namespace
{
- // Default values of units
- UnitsAPI::SetLocalSystem (UnitsAPI_SI);
- SetUnitsQuantity ("PLANE ANGLE");
- SetModelUnits ("rad");
- SetDisplayUnits ("deg");
- SetSpecialSymbol (0x00B0);
- SetDisplaySpecialSymbol (AIS_DSS_After);
- MakeUnitsDisplayed (Standard_False);
+ 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;
+
+ //! Returns true if the given points lie on a same line.
+ static Standard_Boolean isSameLine (const gp_Pnt& theFirstPoint,
+ const gp_Pnt& theCenterPoint,
+ const gp_Pnt& theSecondPoint)
+ {
+ gp_Vec aVec1 (theFirstPoint, theCenterPoint);
+ gp_Vec aVec2 (theCenterPoint, theSecondPoint);
+
+ return aVec1.IsParallel (aVec2, Precision::Angular());
+ }
}
//=======================================================================
//function : Constructor
-//purpose : Two edges dimension
+//purpose :
//=======================================================================
-
AIS_AngleDimension::AIS_AngleDimension (const TopoDS_Edge& theFirstEdge,
const TopoDS_Edge& theSecondEdge)
-: AIS_Dimension(),
- myIsFlyoutLines (Standard_True),
- myFlyout (15.0)
+: AIS_Dimension (AIS_KOD_PLANEANGLE)
{
- init();
- myShapesNumber = 2;
- SetKindOfDimension (AIS_KOD_PLANEANGLE);
- myFirstShape = theFirstEdge;
- mySecondShape = theSecondEdge;
+ Init();
+ SetMeasuredGeometry (theFirstEdge, theSecondEdge);
}
//=======================================================================
//function : Constructor
-//purpose : Two edges dimension
-// <thePlane> is used in case of Angle=PI
+//purpose :
//=======================================================================
+AIS_AngleDimension::AIS_AngleDimension (const gp_Pnt& theFirstPoint,
+ const gp_Pnt& theSecondPoint,
+ const gp_Pnt& theThirdPoint)
+: AIS_Dimension (AIS_KOD_PLANEANGLE)
+{
+ Init();
+ SetMeasuredGeometry (theFirstPoint, theSecondPoint, theThirdPoint);
+}
-AIS_AngleDimension::AIS_AngleDimension (const TopoDS_Edge& theFirstEdge,
- const TopoDS_Edge& theSecondEdge,
- const gp_Pln& thePlane)
-: AIS_Dimension(),
- myIsFlyoutLines (Standard_True),
- myFlyout (15.0)
+//=======================================================================
+//function : Constructor
+//purpose :
+//=======================================================================
+AIS_AngleDimension::AIS_AngleDimension (const TopoDS_Vertex& theFirstVertex,
+ const TopoDS_Vertex& theSecondVertex,
+ const TopoDS_Vertex& theThirdVertex)
+: AIS_Dimension (AIS_KOD_PLANEANGLE)
{
- init();
- myShapesNumber = 2;
- SetKindOfDimension (AIS_KOD_PLANEANGLE);
- myFirstShape = theFirstEdge;
- mySecondShape = theSecondEdge;
- SetWorkingPlane (thePlane);
+ Init();
+ SetMeasuredGeometry (theFirstVertex, theSecondVertex, theThirdVertex);
}
//=======================================================================
//function : Constructor
-//purpose : Two edges dimension with aspect
-// <thePlane> is used in case of Angle=PI
+//purpose :
//=======================================================================
+AIS_AngleDimension::AIS_AngleDimension (const TopoDS_Face& theCone)
+: AIS_Dimension (AIS_KOD_PLANEANGLE)
+{
+ Init();
+ SetMeasuredGeometry (theCone);
+}
-AIS_AngleDimension::AIS_AngleDimension (const TopoDS_Edge& theFirstEdge,
- const TopoDS_Edge& theSecondEdge,
- const gp_Pln& thePlane,
- const Handle(Prs3d_DimensionAspect)& theDimensionAspect,
- const Standard_Real theExtensionSize)
-: AIS_Dimension (theDimensionAspect,theExtensionSize),
- myIsFlyoutLines (Standard_True),
- myFlyout (15.0)
+//=======================================================================
+//function : Constructor
+//purpose :
+//=======================================================================
+AIS_AngleDimension::AIS_AngleDimension (const TopoDS_Face& theFirstFace,
+ const TopoDS_Face& theSecondFace)
+: AIS_Dimension (AIS_KOD_PLANEANGLE)
{
- myShapesNumber = 2;
- SetKindOfDimension (AIS_KOD_PLANEANGLE);
- myFirstShape = theFirstEdge;
- mySecondShape = theSecondEdge;
- SetWorkingPlane (thePlane);
+ Init();
+ SetMeasuredGeometry (theFirstFace, theSecondFace);
}
//=======================================================================
//function : Constructor
-//purpose : Three points dimension
+//purpose :
//=======================================================================
+AIS_AngleDimension::AIS_AngleDimension (const TopoDS_Face& theFirstFace,
+ const TopoDS_Face& theSecondFace,
+ const gp_Pnt& thePoint)
+: AIS_Dimension (AIS_KOD_PLANEANGLE)
+{
+ Init();
+ SetMeasuredGeometry (theFirstFace, theSecondFace, thePoint);
+}
-AIS_AngleDimension::AIS_AngleDimension (const gp_Pnt& theFirstPoint,
- const gp_Pnt& theSecondPoint,
- const gp_Pnt& theThirdPoint)
-: AIS_Dimension(),
- myIsFlyoutLines (Standard_True),
- myFlyout (15.0)
+//=======================================================================
+//function : SetMeasuredGeometry
+//purpose :
+//=======================================================================
+void AIS_AngleDimension::SetMeasuredGeometry (const TopoDS_Edge& theFirstEdge,
+ const TopoDS_Edge& theSecondEdge)
+{
+ gp_Pln aComputedPlane;
+
+ myFirstShape = theFirstEdge;
+ mySecondShape = theSecondEdge;
+ myThirdShape = TopoDS_Shape();
+ myGeometryType = GeometryType_Edges;
+ myIsGeometryValid = InitTwoEdgesAngle (aComputedPlane);
+
+ if (myIsGeometryValid && !myIsPlaneCustom)
+ {
+ myPlane = aComputedPlane;
+ }
+
+ SetToUpdate();
+}
+
+//=======================================================================
+//function : SetMeasuredGeometry
+//purpose :
+//=======================================================================
+void AIS_AngleDimension::SetMeasuredGeometry (const gp_Pnt& theFirstPoint,
+ const gp_Pnt& theSecondPoint,
+ const gp_Pnt& theThirdPoint)
{
- init();
- myIsInitialized = Standard_True;
- SetKindOfDimension (AIS_KOD_PLANEANGLE);
- myFirstPoint = theFirstPoint;
- myCenter = theSecondPoint;
- mySecondPoint = theThirdPoint;
- myShapesNumber = 3;
+ myFirstPoint = theFirstPoint;
+ myCenterPoint = theSecondPoint;
+ mySecondPoint = theThirdPoint;
+ myFirstShape = BRepLib_MakeVertex (myFirstPoint);
+ mySecondShape = BRepLib_MakeVertex (myCenterPoint);
+ myThirdShape = BRepLib_MakeVertex (mySecondPoint);
+ myGeometryType = GeometryType_Points;
+ myIsGeometryValid = IsValidPoints (myFirstPoint, myCenterPoint, mySecondPoint);
+
+ Standard_Boolean anIsSameLine = isSameLine (myFirstPoint, myCenterPoint, mySecondPoint);
+ if (myIsGeometryValid && !myIsPlaneCustom && !anIsSameLine)
+ {
+ ComputePlane();
+ }
+
+ SetToUpdate();
}
//=======================================================================
-//function : Constructor
-//purpose : Three points dimension
+//function : SetMeasuredGeometry
+//purpose :
//=======================================================================
+void AIS_AngleDimension::SetMeasuredGeometry (const TopoDS_Vertex& theFirstVertex,
+ const TopoDS_Vertex& theSecondVertex,
+ const TopoDS_Vertex& theThirdVertex)
+{
+ myFirstShape = theFirstVertex;
+ mySecondShape = theSecondVertex;
+ myThirdShape = theThirdVertex;
+ myFirstPoint = BRep_Tool::Pnt (theFirstVertex);
+ myCenterPoint = BRep_Tool::Pnt (theSecondVertex);
+ mySecondPoint = BRep_Tool::Pnt (theThirdVertex);
+ myGeometryType = GeometryType_Points;
+ myIsGeometryValid = IsValidPoints (myFirstPoint, myCenterPoint, mySecondPoint);
+
+ Standard_Boolean anIsSameLine = isSameLine (myFirstPoint, myCenterPoint, mySecondPoint);
+ if (myIsGeometryValid && !myIsPlaneCustom && !anIsSameLine)
+ {
+ ComputePlane();
+ }
-AIS_AngleDimension::AIS_AngleDimension (const gp_Pnt& theFirstPoint,
- const gp_Pnt& theSecondPoint,
- const gp_Pnt& theThirdPoint,
- const Handle(Prs3d_DimensionAspect)& theDimensionAspect,
- const Standard_Real theExtensionSize)
-: AIS_Dimension (theDimensionAspect,theExtensionSize),
- myIsFlyoutLines (Standard_True),
- myFlyout (15.0)
+ SetToUpdate();
+}
+
+//=======================================================================
+//function : SetMeasuredGeometry
+//purpose :
+//=======================================================================
+void AIS_AngleDimension::SetMeasuredGeometry (const TopoDS_Face& theCone)
{
- myIsInitialized = Standard_True;
- SetKindOfDimension (AIS_KOD_PLANEANGLE);
- myFirstPoint = theFirstPoint;
- myCenter = theSecondPoint;
- mySecondPoint = theThirdPoint;
- myShapesNumber =3;
+ myFirstShape = theCone;
+ mySecondShape = TopoDS_Shape();
+ myThirdShape = TopoDS_Shape();
+ myGeometryType = GeometryType_Face;
+ myIsGeometryValid = InitConeAngle();
+
+ if (myIsGeometryValid && !myIsPlaneCustom)
+ {
+ ComputePlane();
+ }
+
+ SetToUpdate();
}
//=======================================================================
-//function : Constructor
-//purpose : Cone dimension
+//function : SetMeasuredGeometry
+//purpose :
+//=======================================================================
+void AIS_AngleDimension::SetMeasuredGeometry (const TopoDS_Face& theFirstFace,
+ const TopoDS_Face& theSecondFace)
+{
+ myFirstShape = theFirstFace;
+ mySecondShape = theSecondFace;
+ myThirdShape = TopoDS_Shape();
+ myGeometryType = GeometryType_Faces;
+ myIsGeometryValid = InitTwoFacesAngle();
+
+ if (myIsGeometryValid && !myIsPlaneCustom)
+ {
+ ComputePlane();
+ }
+
+ SetToUpdate();
+}
+
+//=======================================================================
+//function : SetMeasuredGeometry
+//purpose :
+//=======================================================================
+void AIS_AngleDimension::SetMeasuredGeometry (const TopoDS_Face& theFirstFace,
+ const TopoDS_Face& theSecondFace,
+ const gp_Pnt& thePoint)
+{
+ myFirstShape = theFirstFace;
+ mySecondShape = theSecondFace;
+ myThirdShape = TopoDS_Shape();
+ myGeometryType = GeometryType_Faces;
+ myIsGeometryValid = InitTwoFacesAngle (thePoint);
+
+ if (myIsGeometryValid && !myIsPlaneCustom)
+ {
+ ComputePlane();
+ }
+
+ SetToUpdate();
+}
+
+//=======================================================================
+//function : Init
+//purpose :
+//=======================================================================
+void AIS_AngleDimension::Init()
+{
+ SetType (AIS_TOA_Interior);
+ SetArrowsVisibility (AIS_TOAV_Both);
+ SetSpecialSymbol (THE_DEGREE_SYMBOL);
+ SetDisplaySpecialSymbol (AIS_DSS_After);
+ SetFlyout (15.0);
+}
+
+//=======================================================================
+//function: GetCenterOnArc
+//purpose :
+//=======================================================================
+gp_Pnt AIS_AngleDimension::GetCenterOnArc (const gp_Pnt& theFirstAttach,
+ const gp_Pnt& theSecondAttach,
+ const gp_Pnt& theCenter) const
+{
+ // construct plane where the circle and the arc are located
+ gce_MakePln aConstructPlane (theFirstAttach, theSecondAttach, theCenter);
+ if (!aConstructPlane.IsDone())
+ {
+ return gp::Origin();
+ }
+
+ gp_Pln aPlane = aConstructPlane.Value();
+ // to have an exterior angle presentation, a plane for further constructed circle should be reversed
+ if (myType == AIS_TOA_Exterior)
+ {
+ gp_Ax1 anAxis = aPlane.Axis();
+ gp_Dir aDir = anAxis.Direction();
+ aDir.Reverse();
+ aPlane.SetAxis(gp_Ax1(anAxis.Location(), aDir));
+ }
+
+ Standard_Real aRadius = theFirstAttach.Distance (theCenter);
+
+ // construct circle forming the arc
+ gce_MakeCirc aConstructCircle (theCenter, aPlane, aRadius);
+ if (!aConstructCircle.IsDone())
+ {
+ return gp::Origin();
+ }
+
+ gp_Circ aCircle = aConstructCircle.Value();
+
+ // 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 (0.0, M_PI * 2, Precision::PConfusion(), aParamBeg, aParamEnd);
+
+ return ElCLib::Value ((aParamBeg + aParamEnd) * 0.5, aCircle);
+}
+
+//=======================================================================
+//function : GetNormalForMinAngle
+//purpose :
+//=======================================================================
+gp_Dir AIS_AngleDimension::GetNormalForMinAngle() const
+{
+ const gp_Dir& aNormal = myPlane.Axis().Direction();
+ gp_Dir aFirst (gp_Vec (myCenterPoint, myFirstPoint) );
+ gp_Dir aSecond (gp_Vec (myCenterPoint, mySecondPoint) );
+
+ return aFirst.AngleWithRef (aSecond, aNormal) < 0.0
+ ? aNormal.Reversed()
+ : aNormal;
+}
+
+//=======================================================================
+//function : DrawArc
+//purpose : draws the arc between two attach points
+//=======================================================================
+void AIS_AngleDimension::DrawArc (const Handle(Prs3d_Presentation)& thePresentation,
+ const gp_Pnt& theFirstAttach,
+ const gp_Pnt& theSecondAttach,
+ const gp_Pnt& theCenter,
+ const Standard_Real theRadius,
+ const Standard_Integer theMode)
+{
+ gp_Pln aPlane (myCenterPoint, GetNormalForMinAngle());
+
+ // to have an exterior angle presentation, a plane for further constructed circle should be reversed
+ if (myType == AIS_TOA_Exterior)
+ {
+ gp_Ax1 anAxis = aPlane.Axis();
+ gp_Dir aDir = anAxis.Direction();
+ aDir.Reverse();
+ aPlane.SetAxis(gp_Ax1(anAxis.Location(), aDir));
+ }
+
+ // construct circle forming the arc
+ gce_MakeCirc aConstructCircle (theCenter, aPlane, theRadius);
+ if (!aConstructCircle.IsDone())
+ {
+ return;
+ }
+
+ gp_Circ aCircle = aConstructCircle.Value();
+
+ // 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());
+
+ // compute number of discretization elements in old-fanshioned way
+ gp_Vec aCenterToFirstVec (theCenter, theFirstAttach);
+ gp_Vec aCenterToSecondVec (theCenter, theSecondAttach);
+ Standard_Real anAngle = aCenterToFirstVec.Angle (aCenterToSecondVec);
+ if (myType == AIS_TOA_Exterior)
+ anAngle = 2.0 * M_PI - anAngle;
+ // it sets 50 points on PI, and a part of points if angle is less
+ const Standard_Integer aNbPoints = Max (4, Standard_Integer (50.0 * anAngle / M_PI));
+
+ GCPnts_UniformAbscissa aMakePnts (anArcAdaptor, aNbPoints);
+ if (!aMakePnts.IsDone())
+ {
+ return;
+ }
+
+ // init data arrays for graphical and selection primitives
+ Handle(Graphic3d_ArrayOfPolylines) aPrimSegments = new Graphic3d_ArrayOfPolylines (aNbPoints);
+
+ SelectionGeometry::Curve& aSensitiveCurve = mySelectionGeom.NewCurve();
+
+ // 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 == ComputeMode_All)
+ {
+ Prs3d_Root::CurrentGroup (thePresentation)->SetStencilTestOptions (Standard_False);
+ }
+}
+
+//=======================================================================
+//function: DrawArcWithText
+//purpose :
//=======================================================================
+void AIS_AngleDimension::DrawArcWithText (const Handle(Prs3d_Presentation)& thePresentation,
+ const gp_Pnt& theFirstAttach,
+ const gp_Pnt& theSecondAttach,
+ const gp_Pnt& theCenter,
+ const TCollection_ExtendedString& theText,
+ const Standard_Real theTextWidth,
+ const Standard_Integer theMode,
+ const Standard_Integer theLabelPosition)
+{
+ gp_Pln aPlane (myCenterPoint, GetNormalForMinAngle());
+
+ Standard_Real aRadius = theFirstAttach.Distance (myCenterPoint);
+
+ // construct circle forming the arc
+ gce_MakeCirc aConstructCircle (theCenter, aPlane, aRadius);
+ if (!aConstructCircle.IsDone())
+ {
+ return;
+ }
+
+ gp_Circ aCircle = aConstructCircle.Value();
+
+ // 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 (0.0, M_PI * 2, Precision::PConfusion(), aParamBeg, aParamEnd);
+
+ // middle point of arc parameter on circle
+ Standard_Real aParamMid = (aParamBeg + aParamEnd) * 0.5;
+
+ // add text graphical primitives
+ if (theMode == ComputeMode_All || theMode == ComputeMode_Text)
+ {
+ gp_Pnt aTextPos = ElCLib::Value (aParamMid, aCircle);
+ gp_Dir aTextDir = gce_MakeDir (theFirstAttach, theSecondAttach);
+
+ // Drawing text
+ drawText (thePresentation,
+ aTextPos,
+ aTextDir,
+ theText,
+ theLabelPosition);
+ }
+
+ if (theMode != ComputeMode_All && theMode != ComputeMode_Line)
+ {
+ return;
+ }
+
+ Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
+
+ Standard_Boolean isLineBreak = aDimensionAspect->TextVerticalPosition() == Prs3d_DTVP_Center
+ && aDimensionAspect->IsText3d();
+
+ if (isLineBreak)
+ {
+ // compute gap for label as parameteric size of sector on circle segment
+ Standard_Real aSectorOfText = theTextWidth / aRadius;
+ Standard_Real aTextBegin = aParamMid - aSectorOfText * 0.5;
+ Standard_Real aTextEnd = aParamMid + aSectorOfText * 0.5;
+ gp_Pnt aTextPntBeg = ElCLib::Value (aTextBegin, aCircle);
+ gp_Pnt aTextPntEnd = ElCLib::Value (aTextEnd, aCircle);
+
+ // Drawing arcs
+ if (aTextBegin > aParamBeg)
+ {
+ DrawArc (thePresentation, theFirstAttach, aTextPntBeg, theCenter, aRadius, theMode);
+ }
+ if (aTextEnd < aParamEnd)
+ {
+ DrawArc (thePresentation, aTextPntEnd, theSecondAttach, theCenter, aRadius, theMode);
+ }
+ }
+ else
+ {
+ DrawArc (thePresentation, theFirstAttach, theSecondAttach, theCenter, aRadius, theMode);
+ }
+}
+
+//=======================================================================
+//function : CheckPlane
+//purpose :
+//=======================================================================
+Standard_Boolean AIS_AngleDimension::CheckPlane (const gp_Pln& thePlane)const
+{
+ if (!thePlane.Contains (myFirstPoint, Precision::Confusion()) &&
+ !thePlane.Contains (mySecondPoint, Precision::Confusion()) &&
+ !thePlane.Contains (myCenterPoint, Precision::Confusion()))
+ {
+ return Standard_False;
+ }
+
+ return Standard_True;
+}
+
+//=======================================================================
+//function : ComputePlane
+//purpose :
+//=======================================================================
+void AIS_AngleDimension::ComputePlane()
+{
+ if (!myIsGeometryValid)
+ {
+ return;
+ }
+
+ // Compute working plane so that Y axis is codirectional
+ // with Y axis of text coordinate system (necessary for text alignment)
+ gp_Vec aFirstVec = gp_Vec (myCenterPoint, myFirstPoint);
+ gp_Vec aSecondVec = gp_Vec (myCenterPoint, mySecondPoint);
+ gp_Vec aDirectionN = aSecondVec ^ aFirstVec;
+ gp_Vec aDirectionY = aFirstVec + aSecondVec;
+ gp_Vec aDirectionX = aDirectionY ^ aDirectionN;
+
+ myPlane = gp_Pln (gp_Ax3 (myCenterPoint, gp_Dir (aDirectionN), gp_Dir (aDirectionX)));
+}
+
+//=======================================================================
+//function : GetModelUnits
+//purpose :
+//=======================================================================
+const TCollection_AsciiString& AIS_AngleDimension::GetModelUnits() const
+{
+ return myDrawer->DimAngleModelUnits();
+}
+
+//=======================================================================
+//function : GetDisplayUnits
+//purpose :
+//=======================================================================
+const TCollection_AsciiString& AIS_AngleDimension::GetDisplayUnits() const
+{
+ return myDrawer->DimAngleDisplayUnits();
+}
+
+//=======================================================================
+//function : SetModelUnits
+//purpose :
+//=======================================================================
+void AIS_AngleDimension::SetModelUnits (const TCollection_AsciiString& theUnits)
+{
+ myDrawer->SetDimAngleModelUnits (theUnits);
+}
+
+//=======================================================================
+//function : SetDisplayUnits
+//purpose :
+//=======================================================================
+void AIS_AngleDimension::SetDisplayUnits (const TCollection_AsciiString& theUnits)
+{
+ myDrawer->SetDimAngleDisplayUnits (theUnits);
+}
+
+//=======================================================================
+//function : ComputeValue
+//purpose :
+//=======================================================================
+Standard_Real AIS_AngleDimension::ComputeValue() const
+{
+ if (!IsValid())
+ {
+ return 0.0;
+ }
+
+ gp_Vec aVec1 (myCenterPoint, myFirstPoint);
+ gp_Vec aVec2 (myCenterPoint, mySecondPoint);
+
+ Standard_Real anAngle = aVec1.AngleWithRef (aVec2, GetNormalForMinAngle());
+
+ return anAngle > 0.0 ? anAngle : (2.0 * M_PI + anAngle);
+}
+
+//=======================================================================
+//function : Compute
+//purpose : Having three gp_Pnt points compute presentation
+//=======================================================================
+void AIS_AngleDimension::Compute (const Handle(PrsMgr_PresentationManager3d)& /*thePM*/,
+ const Handle(Prs3d_Presentation)& thePresentation,
+ const Standard_Integer theMode)
+{
+ mySelectionGeom.Clear (theMode);
+
+ if (!IsValid())
+ {
+ return;
+ }
+
+ // Parameters for presentation
+ Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
+
+ Prs3d_Root::CurrentGroup(thePresentation)->SetPrimitivesAspect (aDimensionAspect->LineAspect()->Aspect());
+
+ Standard_Real 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;
+ }
+
+ // Get parameters from aspect or adjust it according with custom text position
+ Standard_Real anExtensionSize = aDimensionAspect->ExtensionSize();
+ Prs3d_DimensionTextHorizontalPosition aHorisontalTextPos = aDimensionAspect->TextHorizontalPosition();
+
+ if (IsTextPositionCustom())
+ {
+ AdjustParameters (myFixedTextPosition,anExtensionSize, aHorisontalTextPos, myFlyout);
+ }
+
+ // Handle user-defined and automatic arrow placement
+ Standard_Boolean isArrowsExternal = Standard_False;
+ Standard_Integer aLabelPosition = LabelPosition_None;
+
+ FitTextAlignment (aHorisontalTextPos, aLabelPosition, isArrowsExternal);
+
+ 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 aWorkingPlaneDir (GetNormalForMinAngle());
+
+ gp_Dir aFirstExtensionDir = aWorkingPlaneDir.Reversed() ^ gp_Vec (myCenterPoint, aFirstAttach);
+ gp_Dir aSecondExtensionDir = aWorkingPlaneDir ^ gp_Vec (myCenterPoint, aSecondAttach);
+
+ gp_Vec aFirstArrowVec = gp_Vec (aFirstExtensionDir) * anArrowLength;
+ gp_Vec aSecondArrowVec = gp_Vec (aSecondExtensionDir) * anArrowLength;
+
+ if (isArrowsExternal)
+ {
+ aFirstArrowVec.Reverse();
+ aSecondArrowVec.Reverse();
+ }
+
+ gp_Pnt aFirstArrowBegin (0.0, 0.0, 0.0);
+ gp_Pnt aFirstArrowEnd (0.0, 0.0, 0.0);
+ gp_Pnt aSecondArrowBegin (0.0, 0.0, 0.0);
+ gp_Pnt aSecondArrowEnd (0.0, 0.0, 0.0);
+
+ aFirstArrowBegin = aFirstAttach;
+ aSecondArrowBegin = aSecondAttach;
+ aFirstArrowEnd = aFirstAttach.Translated (-aFirstArrowVec);
+ aSecondArrowEnd = aSecondAttach.Translated (-aSecondArrowVec);
+
+ // Group1: stenciling text and the angle dimension arc
+ Prs3d_Root::NewGroup (thePresentation);
+
+ Standard_Integer aHPosition = aLabelPosition & LabelPosition_HMask;
+
+ // draw text label
+ switch (aHPosition)
+ {
+ case LabelPosition_HCenter :
+ {
+ Standard_Boolean isLineBreak = aDimensionAspect->TextVerticalPosition() == Prs3d_DTVP_Center
+ && aDimensionAspect->IsText3d();
+
+ if (isLineBreak)
+ {
+ DrawArcWithText (thePresentation,
+ aFirstAttach,
+ aSecondAttach,
+ myCenterPoint,
+ aLabelString,
+ aLabelWidth,
+ theMode,
+ aLabelPosition);
+ break;
+ }
+
+ // compute text primitives
+ if (theMode == ComputeMode_All || theMode == ComputeMode_Text)
+ {
+ gp_Vec aDimensionDir (aFirstAttach, aSecondAttach);
+ gp_Pnt aTextPos = IsTextPositionCustom() ? myFixedTextPosition
+ : GetCenterOnArc (aFirstAttach, aSecondAttach, myCenterPoint);
+ gp_Dir aTextDir = aDimensionDir;
+
+ drawText (thePresentation,
+ aTextPos,
+ aTextDir,
+ aLabelString,
+ aLabelPosition);
+ }
+
+ if (theMode == ComputeMode_All || theMode == ComputeMode_Line)
+ {
+ DrawArc (thePresentation,
+ (isArrowsExternal || !isArrowVisible(AIS_TOAV_First)) ? aFirstAttach : aFirstArrowEnd,
+ (isArrowsExternal || !isArrowVisible(AIS_TOAV_Second)) ? aSecondAttach : aSecondArrowEnd,
+ myCenterPoint,
+ Abs (GetFlyout()),
+ theMode);
+ }
+ }
+ break;
+
+ case LabelPosition_Left :
+ {
+ DrawExtension (thePresentation,
+ anExtensionSize,
+ (isArrowsExternal && isArrowVisible(AIS_TOAV_First)) ? aFirstArrowEnd : aFirstAttach,
+ aFirstExtensionDir,
+ aLabelString,
+ aLabelWidth,
+ theMode,
+ aLabelPosition);
+ }
+ break;
+
+ case LabelPosition_Right :
+ {
+ DrawExtension (thePresentation,
+ anExtensionSize,
+ (isArrowsExternal && isArrowVisible(AIS_TOAV_Second)) ? aSecondArrowEnd : aSecondAttach,
+ aSecondExtensionDir,
+ aLabelString,
+ aLabelWidth,
+ theMode,
+ aLabelPosition);
+ }
+ break;
+ }
+
+ // dimension arc without text
+ if ((theMode == ComputeMode_All || theMode == ComputeMode_Line) && aHPosition != LabelPosition_HCenter)
+ {
+ Prs3d_Root::NewGroup (thePresentation);
+
+ DrawArc (thePresentation,
+ (isArrowsExternal || !isArrowVisible(AIS_TOAV_First)) ? aFirstAttach : aFirstArrowEnd,
+ (isArrowsExternal || !isArrowVisible(AIS_TOAV_Second)) ? aSecondAttach : aSecondArrowEnd,
+ myCenterPoint,
+ Abs(GetFlyout ()),
+ theMode);
+ }
+
+ // arrows and arrow extensions
+ if (theMode == ComputeMode_All || theMode == ComputeMode_Line)
+ {
+ Prs3d_Root::NewGroup (thePresentation);
+
+ if (isArrowVisible(AIS_TOAV_First))
+ DrawArrow (thePresentation, aFirstArrowBegin, gp_Dir (aFirstArrowVec));
+ if (isArrowVisible(AIS_TOAV_Second))
+ DrawArrow (thePresentation, aSecondArrowBegin, gp_Dir (aSecondArrowVec));
+ }
+
+ if ((theMode == ComputeMode_All || theMode == ComputeMode_Line) && isArrowsExternal)
+ {
+ Prs3d_Root::NewGroup (thePresentation);
+
+ if (aHPosition != LabelPosition_Left && isArrowVisible(AIS_TOAV_First))
+ {
+ DrawExtension (thePresentation,
+ aDimensionAspect->ArrowTailSize(),
+ aFirstArrowEnd,
+ aFirstExtensionDir,
+ THE_EMPTY_LABEL_STRING,
+ THE_EMPTY_LABEL_WIDTH,
+ theMode,
+ LabelPosition_None);
+ }
+
+ if (aHPosition != LabelPosition_Right && isArrowVisible(AIS_TOAV_Second))
+ {
+ DrawExtension (thePresentation,
+ aDimensionAspect->ArrowTailSize(),
+ aSecondArrowEnd,
+ aSecondExtensionDir,
+ THE_EMPTY_LABEL_STRING,
+ THE_EMPTY_LABEL_WIDTH,
+ theMode,
+ LabelPosition_None);
+ }
+ }
+
+ // flyouts
+ if (theMode == ComputeMode_All)
+ {
+ Prs3d_Root::NewGroup (thePresentation);
+
+ Handle(Graphic3d_ArrayOfSegments) aPrimSegments = new Graphic3d_ArrayOfSegments (4);
+ aPrimSegments->AddVertex (myCenterPoint);
+ aPrimSegments->AddVertex (aFirstAttach);
+ aPrimSegments->AddVertex (myCenterPoint);
+ aPrimSegments->AddVertex (aSecondAttach);
+
+ Handle(Graphic3d_AspectLine3d) aFlyoutStyle = myDrawer->DimensionAspect()->LineAspect()->Aspect();
+ Prs3d_Root::CurrentGroup (thePresentation)->SetPrimitivesAspect (aFlyoutStyle);
+ Prs3d_Root::CurrentGroup (thePresentation)->AddPrimitiveArray (aPrimSegments);
+ }
+
+ mySelectionGeom.IsComputed = Standard_True;
+}
+
+//=======================================================================
+//function : ComputeFlyoutSelection
+//purpose : computes selection for flyouts
+//=======================================================================
+void AIS_AngleDimension::ComputeFlyoutSelection (const Handle(SelectMgr_Selection)& theSelection,
+ const Handle(SelectMgr_EntityOwner)& theOwner)
+{
+ gp_Pnt aFirstAttach = myCenterPoint.Translated (gp_Vec (myCenterPoint, myFirstPoint).Normalized() * GetFlyout());
+ gp_Pnt aSecondAttach = myCenterPoint.Translated (gp_Vec (myCenterPoint, mySecondPoint).Normalized() * GetFlyout());
+
+ Handle(Select3D_SensitiveGroup) aSensitiveEntity = new Select3D_SensitiveGroup (theOwner);
+ aSensitiveEntity->Add (new Select3D_SensitiveSegment (theOwner, myCenterPoint, aFirstAttach));
+ aSensitiveEntity->Add (new Select3D_SensitiveSegment (theOwner, myCenterPoint, aSecondAttach));
+
+ theSelection->Add (aSensitiveEntity);
+}
+
+//=======================================================================
+//function : InitTwoEdgesAngle
+//purpose :
+//=======================================================================
+Standard_Boolean AIS_AngleDimension::InitTwoEdgesAngle (gp_Pln& theComputedPlane)
+{
+ TopoDS_Edge aFirstEdge = TopoDS::Edge (myFirstShape);
+ TopoDS_Edge aSecondEdge = TopoDS::Edge (mySecondShape);
+
+ BRepAdaptor_Curve aMakeFirstLine (aFirstEdge);
+ BRepAdaptor_Curve aMakeSecondLine (aSecondEdge);
+
+ if (aMakeFirstLine.GetType() != GeomAbs_Line || aMakeSecondLine.GetType() != GeomAbs_Line)
+ {
+ return Standard_False;
+ }
+
+ Handle(Geom_Line) aFirstLine = new Geom_Line (aMakeFirstLine.Line());
+ Handle(Geom_Line) aSecondLine = new Geom_Line (aMakeSecondLine.Line());
+
+ gp_Lin aFirstLin = aFirstLine->Lin();
+ gp_Lin aSecondLin = aSecondLine->Lin();
+
+ Standard_Boolean isParallelLines = aFirstLin.Direction().IsParallel (aSecondLin.Direction(), Precision::Angular());
+
+ theComputedPlane = isParallelLines ? gp_Pln(gp::XOY())
+ : gp_Pln (aSecondLin.Location(), gp_Vec (aFirstLin.Direction()) ^ gp_Vec (aSecondLin.Direction()));
+
+ // Compute geometry for this plane and edges
+ Standard_Boolean isInfinite1,isInfinite2;
+ gp_Pnt aFirstPoint1, aLastPoint1, aFirstPoint2, aLastPoint2;
+ Handle(Geom_Curve) aFirstCurve = aFirstLine, aSecondCurve = aSecondLine;
+ if (!AIS::ComputeGeometry (aFirstEdge, aSecondEdge,
+ aFirstCurve, aSecondCurve,
+ aFirstPoint1, aLastPoint1,
+ aFirstPoint2, aLastPoint2,
+ isInfinite1, isInfinite2))
+ {
+ return Standard_False;
+ }
+
+ Standard_Boolean isSameLines = aFirstLin.Direction().IsEqual (aSecondLin.Direction(), Precision::Angular())
+ && aFirstLin.Location().IsEqual (aSecondLin.Location(),Precision::Confusion());
+
+ // It can be the same gp_Lin geometry but the different begin and end parameters
+ Standard_Boolean isSameEdges =
+ (aFirstPoint1.IsEqual (aFirstPoint2, Precision::Confusion()) && aLastPoint1.IsEqual (aLastPoint2, Precision::Confusion()))
+ || (aFirstPoint1.IsEqual (aLastPoint2, Precision::Confusion()) && aLastPoint1.IsEqual (aFirstPoint2, Precision::Confusion()));
+
+ if (isParallelLines)
+ {
+ // Zero angle, it could not handle this geometry
+ if (isSameLines && isSameEdges)
+ {
+ return Standard_False;
+ }
+
+ // Handle the case of Pi angle
+ const Standard_Real aParam11 = ElCLib::Parameter (aFirstLin, aFirstPoint1);
+ const Standard_Real aParam12 = ElCLib::Parameter (aFirstLin, aLastPoint1);
+ const Standard_Real aParam21 = ElCLib::Parameter (aFirstLin, aFirstPoint2);
+ const Standard_Real aParam22 = ElCLib::Parameter (aFirstLin, aLastPoint2);
+ myCenterPoint = ElCLib::Value ( (Min (aParam11, aParam12) + Max (aParam21, aParam22)) * 0.5, aFirstLin);
+ myFirstPoint = myCenterPoint.Translated (gp_Vec (aFirstLin.Direction()) * Abs (GetFlyout()));
+ mySecondPoint = myCenterPoint.XYZ() + (aFirstLin.Direction().IsEqual (aSecondLin.Direction(), Precision::Angular())
+ ? aFirstLin.Direction().Reversed().XYZ() * Abs (GetFlyout())
+ : aSecondLin.Direction().XYZ() * Abs (GetFlyout()));
+ }
+ else
+ {
+ // Find intersection
+ gp_Lin2d aFirstLin2d = ProjLib::Project (theComputedPlane, aFirstLin);
+ gp_Lin2d aSecondLin2d = ProjLib::Project (theComputedPlane, aSecondLin);
+
+ IntAna2d_AnaIntersection anInt2d (aFirstLin2d, aSecondLin2d);
+ gp_Pnt2d anIntersectPoint;
+ if (!anInt2d.IsDone() || anInt2d.IsEmpty())
+ {
+ return Standard_False;
+ }
+
+ anIntersectPoint = gp_Pnt2d (anInt2d.Point(1).Value());
+ myCenterPoint = ElCLib::To3d (theComputedPlane.Position().Ax2(), anIntersectPoint);
+
+ if (isInfinite1 || isInfinite2)
+ {
+ myFirstPoint = myCenterPoint.Translated (gp_Vec (aFirstLin.Direction()) * Abs (GetFlyout()));
+ mySecondPoint = myCenterPoint.Translated (gp_Vec (aSecondLin.Direction()) * Abs (GetFlyout()));
+
+ return IsValidPoints (myFirstPoint, myCenterPoint, mySecondPoint);
+ }
+
+ // |
+ // | <- dimension should be here
+ // *----
+ myFirstPoint = myCenterPoint.Distance (aFirstPoint1) > myCenterPoint.Distance (aLastPoint1)
+ ? aFirstPoint1
+ : aLastPoint1;
+
+ mySecondPoint = myCenterPoint.Distance (aFirstPoint2) > myCenterPoint.Distance (aLastPoint2)
+ ? aFirstPoint2
+ : aLastPoint2;
+ }
+
+ return IsValidPoints (myFirstPoint, myCenterPoint, mySecondPoint);
+}
+
+//=======================================================================
+//function : InitTwoFacesAngle
+//purpose : initialization of angle dimension between two faces
+//=======================================================================
+Standard_Boolean AIS_AngleDimension::InitTwoFacesAngle()
+{
+ TopoDS_Face aFirstFace = TopoDS::Face (myFirstShape);
+ TopoDS_Face aSecondFace = TopoDS::Face (mySecondShape);
+
+ gp_Dir aFirstDir, aSecondDir;
+ gp_Pln aFirstPln, aSecondPln;
+ Handle(Geom_Surface) aFirstBasisSurf, aSecondBasisSurf;
+ AIS_KindOfSurface aFirstSurfType, aSecondSurfType;
+ Standard_Real aFirstOffset, aSecondOffset;
+
+ AIS::GetPlaneFromFace (aFirstFace, aFirstPln,
+ aFirstBasisSurf,aFirstSurfType,aFirstOffset);
-AIS_AngleDimension::AIS_AngleDimension (const TopoDS_Face& theCone)
-: AIS_Dimension(),
- myIsFlyoutLines (Standard_True),
- myFlyout (15.0)
-{
- init();
- myIsInitialized = Standard_False;
- SetKindOfDimension (AIS_KOD_PLANEANGLE);
- myFirstShape = theCone;
- myShapesNumber = 1;
+ AIS::GetPlaneFromFace (aSecondFace, aSecondPln,
+ aSecondBasisSurf, aSecondSurfType, aSecondOffset);
+
+ if (aFirstSurfType == AIS_KOS_Plane && aSecondSurfType == AIS_KOS_Plane)
+ {
+ //Planar faces angle
+ Handle(Geom_Plane) aFirstPlane = Handle(Geom_Plane)::DownCast (aFirstBasisSurf);
+ Handle(Geom_Plane) aSecondPlane = Handle(Geom_Plane)::DownCast (aSecondBasisSurf);
+ return AIS::InitAngleBetweenPlanarFaces (aFirstFace,
+ aSecondFace,
+ myCenterPoint,
+ myFirstPoint,
+ mySecondPoint)
+ && IsValidPoints (myFirstPoint,
+ myCenterPoint,
+ mySecondPoint);
+ }
+ else
+ {
+ // Curvilinear faces angle
+ return AIS::InitAngleBetweenCurvilinearFaces (aFirstFace,
+ aSecondFace,
+ aFirstSurfType,
+ aSecondSurfType,
+ myCenterPoint,
+ myFirstPoint,
+ mySecondPoint)
+ && IsValidPoints (myFirstPoint,
+ myCenterPoint,
+ mySecondPoint);
+ }
}
//=======================================================================
-//function : Constructor
-//purpose : Two faces dimension
+//function : InitTwoFacesAngle
+//purpose : initialization of angle dimension between two faces
//=======================================================================
-
-AIS_AngleDimension::AIS_AngleDimension (const TopoDS_Face& theFirstFace,
- const TopoDS_Face& theSecondFace,
- const gp_Ax1& theAxis)
-: AIS_Dimension(),
- myIsFlyoutLines (Standard_True),
- myFlyout (15.0)
+Standard_Boolean AIS_AngleDimension::InitTwoFacesAngle (const gp_Pnt thePointOnFirstFace)
{
- init();
- myIsInitialized = Standard_False;
- SetKindOfDimension (AIS_KOD_PLANEANGLE);
- myFirstShape = theFirstFace;
- mySecondShape = theSecondFace;
- myShapesNumber = 2;
- gp_Pln aPlane;
- aPlane.SetAxis (theAxis);
- SetWorkingPlane (aPlane);
-}
+ TopoDS_Face aFirstFace = TopoDS::Face (myFirstShape);
+ TopoDS_Face aSecondFace = TopoDS::Face (mySecondShape);
-//=======================================================================
-//function : SetFirstShape
-//purpose :
-//=======================================================================
+ gp_Dir aFirstDir, aSecondDir;
+ gp_Pln aFirstPln, aSecondPln;
+ Handle(Geom_Surface) aFirstBasisSurf, aSecondBasisSurf;
+ AIS_KindOfSurface aFirstSurfType, aSecondSurfType;
+ Standard_Real aFirstOffset, aSecondOffset;
-void AIS_AngleDimension::SetFirstShape (const TopoDS_Shape& theShape,
- const Standard_Boolean isSingleShape /*= Standard_False*/)
-{
- AIS_Dimension::SetFirstShape (theShape);
- if (isSingleShape)
- myShapesNumber = 1;
-}
+ AIS::GetPlaneFromFace (aFirstFace, aFirstPln,
+ aFirstBasisSurf,aFirstSurfType,aFirstOffset);
-//=======================================================================
-//function : aboveInBelowCone
-//purpose : Returns 1 if <theC> center is above of <theCMin> center;
-// 0 if <theC> center is between <theCMin> and
-// <theCMax> centers;
-// -1 if <theC> center is below <theCMax> center.
-//=======================================================================
+ AIS::GetPlaneFromFace (aSecondFace, aSecondPln,
+ aSecondBasisSurf, aSecondSurfType, aSecondOffset);
-Standard_Integer AIS_AngleDimension::aboveInBelowCone (const gp_Circ &theCMax,
- const gp_Circ &theCMin,
- const gp_Circ &theC)
-{
- const Standard_Real aD = theCMax.Location().Distance (theCMin.Location());
- const Standard_Real aD1 = theCMax.Location().Distance (theC.Location());
- const Standard_Real aD2 = theCMin.Location().Distance (theC.Location());
-
- if (aD >= aD1 && aD >= aD2) return 0;
- if (aD < aD2 && aD1 < aD2) return -1;
- if (aD < aD1 && aD2 < aD1) return 1;
- return 0;
+ myFirstPoint = thePointOnFirstFace;
+ if (aFirstSurfType == AIS_KOS_Plane && aSecondSurfType == AIS_KOS_Plane)
+ {
+ //Planar faces angle
+ Handle(Geom_Plane) aFirstPlane = Handle(Geom_Plane)::DownCast (aFirstBasisSurf);
+ Handle(Geom_Plane) aSecondPlane = Handle(Geom_Plane)::DownCast (aSecondBasisSurf);
+ return AIS::InitAngleBetweenPlanarFaces (aFirstFace,
+ aSecondFace,
+ myCenterPoint,
+ myFirstPoint,
+ mySecondPoint,
+ Standard_True)
+ && IsValidPoints (myFirstPoint,
+ myCenterPoint,
+ mySecondPoint);
+ }
+ else
+ {
+ // Curvilinear faces angle
+ return AIS::InitAngleBetweenCurvilinearFaces (aFirstFace,
+ aSecondFace,
+ aFirstSurfType,
+ aSecondSurfType,
+ myCenterPoint,
+ myFirstPoint,
+ mySecondPoint,
+ Standard_True)
+ && IsValidPoints (myFirstPoint,
+ myCenterPoint,
+ mySecondPoint);
+ }
}
//=======================================================================
-//function : initConeAngle
+//function : InitConeAngle
//purpose : initialization of the cone angle
//=======================================================================
-
-Standard_Boolean AIS_AngleDimension::initConeAngle (const TopoDS_Face& theCone)
+Standard_Boolean AIS_AngleDimension::InitConeAngle()
{
- if (theCone.IsNull ())
+ if (myFirstShape.IsNull())
+ {
return Standard_False;
+ }
+ TopoDS_Face aConeShape = TopoDS::Face (myFirstShape);
gp_Pln aPln;
gp_Cone aCone;
gp_Circ aCircle;
Handle(Geom_ConicalSurface) aConicalSurf;
Handle(Geom_SurfaceOfRevolution) aRevSurf;
Handle(Geom_Line) aLine;
- BRepAdaptor_Surface aConeAdaptor (theCone);
+ BRepAdaptor_Surface aConeAdaptor (aConeShape);
TopoDS_Face aFace;
AIS_KindOfSurface aSurfType;
Standard_Real anOffset = 0.;
Standard_Real aMaxV = aConeAdaptor.FirstVParameter();
Standard_Real aMinV = aConeAdaptor.LastVParameter();
- AIS::GetPlaneFromFace(theCone, aPln, aSurf, aSurfType, anOffset);
+ AIS::GetPlaneFromFace (aConeShape, aPln, aSurf, aSurfType, anOffset);
if (aSurfType == AIS_KOS_Revolution)
{
gce_MakeCone aMkCone (aRevSurf->Axis(), aFirst1, aLast1);
aCone = aMkCone.Value();
- myCenter = aCone.Apex();
+ myCenterPoint = aCone.Apex();
}
else
{
}
aCone = aConeAdaptor.Cone();
aConicalSurf = Handle(Geom_ConicalSurface)::DownCast (aSurf);
- myCenter = aConicalSurf->Apex();
+ myCenterPoint = aConicalSurf->Apex();
}
// A circle where the angle is drawn
aCurve = aSurf->VIso(aMinV);
gp_Circ aCircVmin = Handle(Geom_Circle)::DownCast(aCurve)->Circ();
-
if (aCircVmax.Radius() < aCircVmin.Radius())
{
gp_Circ aTmpCirc = aCircVmax;
}
//=======================================================================
-//function : initTwoFacesAngle
-//purpose : initialization of angle dimension between two faces
-//=======================================================================
-
-Standard_Boolean AIS_AngleDimension::initTwoFacesAngle ()
-{
- TopoDS_Face aFirstFace = TopoDS::Face (myFirstShape);
- TopoDS_Face aSecondFace = TopoDS::Face (mySecondShape);
- gp_Dir aFirstDir, aSecondDir;
- gp_Pln aFirstPlane, aSecondPlane;
- Handle(Geom_Surface) aFirstBasisSurf, aSecondBasisSurf;
- AIS_KindOfSurface aFirstSurfType, aSecondSurfType;
- Standard_Real aFirstOffset, aSecondOffset;
-
- AIS::GetPlaneFromFace (aFirstFace, aFirstPlane,
- aFirstBasisSurf,aFirstSurfType,aFirstOffset);
- AIS::GetPlaneFromFace (aSecondFace, aSecondPlane,
- aSecondBasisSurf, aSecondSurfType, aSecondOffset);
-
- if (aFirstSurfType == AIS_KOS_Plane)
- {
- //Planar faces angle
- AIS::ComputeAngleBetweenPlanarFaces (aFirstFace,
- aSecondFace,
- aSecondBasisSurf,
- GetWorkingPlane().Axis(),
- myValue,
- Standard_True,
- myGeom.myTextPosition,
- myCenter,
- myFirstPoint,
- mySecondPoint,
- aFirstDir,
- aSecondDir);
- }
- else
- {
- // Curvilinear faces angle
- Handle(Geom_Plane) aPlane = new Geom_Plane (GetWorkingPlane());
- AIS::ComputeAngleBetweenCurvilinearFaces (aFirstFace,
- aSecondFace,
- aFirstBasisSurf,
- aSecondBasisSurf,
- aFirstSurfType,
- aSecondSurfType,
- GetWorkingPlane().Axis(),
- myValue,
- Standard_True,
- myGeom.myTextPosition,
- myCenter,
- myFirstPoint,
- mySecondPoint,
- aFirstDir,
- aSecondDir,
- aPlane);
- SetWorkingPlane (aPlane->Pln());
- }
- return Standard_True;
-}
-
-//=======================================================================
-//function : SetFlyout
-//purpose :
-//=======================================================================
-
-void AIS_AngleDimension::SetFlyout (const Standard_Real theFlyout)
-{
- myFlyout = theFlyout;
-}
-
-//=======================================================================
-//function : GetFlyout
+//function : IsValidPoints
//purpose :
//=======================================================================
-
-Standard_Real AIS_AngleDimension::GetFlyout () const
+Standard_Boolean AIS_AngleDimension::IsValidPoints (const gp_Pnt& theFirstPoint,
+ const gp_Pnt& theCenterPoint,
+ const gp_Pnt& theSecondPoint) const
{
- return myFlyout;
+ return theFirstPoint.Distance (theCenterPoint) > Precision::Confusion()
+ && theSecondPoint.Distance (theCenterPoint) > Precision::Confusion()
+ && gp_Vec (theCenterPoint, theFirstPoint).Angle (
+ gp_Vec (theCenterPoint, theSecondPoint)) > Precision::Angular();
}
//=======================================================================
-//function : countDefaultPlane
-//purpose :
+//function : isArrowVisible
+//purpose : compares given and internal arrows types, returns true if the the type should be shown
//=======================================================================
-
-void AIS_AngleDimension::countDefaultPlane ()
+Standard_Boolean AIS_AngleDimension::isArrowVisible(const AIS_TypeOfAngleArrowVisibility& theArrowType) const
{
- if (!myIsInitialized)
- return;
- // Compute normal of the default plane.
- gp_Vec aVec1(myCenter, myFirstPoint),
- aVec2(myCenter, mySecondPoint);
- myDefaultPlane = gp_Pln(myCenter, aVec1^aVec2);
- // Set computed value to <myWorkingPlane>
- ResetWorkingPlane ();
+ switch (theArrowType)
+ {
+ case AIS_TOAV_Both:
+ return myArrowsVisibility == AIS_TOAV_Both;
+ case AIS_TOAV_First:
+ return myArrowsVisibility == AIS_TOAV_Both || myArrowsVisibility == AIS_TOAV_First;
+ case AIS_TOAV_Second:
+ return myArrowsVisibility == AIS_TOAV_Both || myArrowsVisibility == AIS_TOAV_Second;
+ case AIS_TOAV_None:
+ return false;
+ }
+ return false;
}
//=======================================================================
-//function : computeValue
+//function : GetTextPosition
//purpose :
//=======================================================================
-
-void AIS_AngleDimension::computeValue ()
-{
- gp_Vec aVec1 (myCenter, myFirstPoint),
- aVec2 (myCenter, mySecondPoint);
- myValue = aVec1.Angle (aVec2);
- // To model units
- AIS_Dimension::computeValue();
-}
-
-//=======================================================================
-//function : initTwoEdgesAngle
-//purpose : Fill gp_Pnt fields for further presentation computation
-// If intersection between two edges doesn't exist
-// <myIsInitialized> is set to false
-//=======================================================================
-
-Standard_Boolean AIS_AngleDimension::initTwoEdgesAngle ()
+const gp_Pnt AIS_AngleDimension::GetTextPosition() const
{
- // Data initialization
- TopoDS_Edge aFirstEdge = TopoDS::Edge (myFirstShape);
- TopoDS_Edge aSecondEdge = TopoDS::Edge (mySecondShape);
- BRepAdaptor_Curve aMakeFirstLine (aFirstEdge);
- BRepAdaptor_Curve aMakeSecondLine (aSecondEdge);
-
- if (aMakeFirstLine.GetType() != GeomAbs_Line || aMakeSecondLine.GetType() != GeomAbs_Line)
- {
- return Standard_False;
- }
-
- Handle(Geom_Line) aFirstLine = new Geom_Line (aMakeFirstLine.Line());
- Handle(Geom_Line) aSecondLine = new Geom_Line (aMakeSecondLine.Line());
-
- gp_Lin aFirstLin = aFirstLine->Lin ();
- gp_Lin aSecondLin = aSecondLine->Lin ();
- gp_Lin2d aFirstLin2d, aSecondLin2d;
- Standard_Boolean isParallelLines = aFirstLin.Direction().IsParallel (aSecondLin.Direction(), Precision::Angular());
- Standard_Boolean isSameLines = isParallelLines && aFirstLin.Distance (aSecondLin.Location()) <= Precision::Confusion();
- // In case where we can't compute plane automatically
- if ((isParallelLines || isSameLines) && !myIsWorkingPlaneCustom)
- {
- return Standard_False;
- }
-
- gp_Pln aPlane;
-
- /// PART 1 is for automatic plane computation from two edges if it is possible
- // Build plane
- if (!myIsWorkingPlaneCustom)
+ if (!IsValid())
{
- gp_Pnt aPoint = aFirstLine->Value (0.);
- gp_Dir aNormal = isParallelLines
- ? gp_Vec(aSecondLin.Normal (aPoint).Direction()) ^ gp_Vec (aSecondLin.Direction())
- : gp_Vec (aFirstLin.Direction()) ^ gp_Vec (aSecondLin.Direction());
- aPlane = gp_Pln (aPoint, aNormal);
- resetWorkingPlane (aPlane);
- }
- else
- {
- aPlane = GetWorkingPlane();
+ return gp::Origin();
}
- // Compute geometry for this plane and edges
- Standard_Boolean isInfinite1,isInfinite2;
- gp_Pnt aFirstPoint1, aLastPoint1, aFirstPoint2, aLastPoint2;
- Standard_Integer anExtIndex = -1;
- Handle(Geom_Curve) anExtCurve;
- Handle(Geom_Plane) aGeomPlane = new Geom_Plane (aPlane);
- if (!AIS::ComputeGeometry (aFirstEdge, aSecondEdge,
- anExtIndex,
- aFirstLine, aSecondLine,
- aFirstPoint1, aLastPoint1,
- aFirstPoint2, aLastPoint2,
- anExtCurve,
- isInfinite1, isInfinite2,
- aGeomPlane))
+ if (IsTextPositionCustom())
{
- return Standard_False;
+ return myFixedTextPosition;
}
- // Check if both edges are on this plane
- if (!anExtCurve.IsNull())
- {
- if (anExtIndex == 1) // First curve is out of the plane
- {
- // Project curve on the plane
- if (myIsWorkingPlaneCustom)
- {
- aFirstLin2d = ProjLib::Project (aPlane, aFirstLin);
- aFirstLin = ElCLib::To3d (aPlane.Position().Ax2(), aFirstLin2d);
- }
- else
- {
- aFirstLin.Translate (gp_Vec (aFirstLin.Location(), aSecondLin.Location()));
- }
+ // Counts text position according to the dimension parameters
+ gp_Pnt aTextPosition (gp::Origin());
- aFirstLine = new Geom_Line (aFirstLin);
- }
- else if (anExtIndex == 2) // Second curve is out of the plane
- {
- if (myIsWorkingPlaneCustom)
- {
- aSecondLin2d = ProjLib::Project (aPlane, aSecondLin);
- aSecondLin = ElCLib::To3d (aPlane.Position().Ax2(), aSecondLin2d);
- }
- else
- {
- aSecondLin.Translate (gp_Vec (aSecondLin.Location(), aFirstLin.Location()));
- }
+ Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
- aSecondLine = new Geom_Line (aSecondLin);
- }
- }
+ // Prepare label string and compute its geometrical width
+ Standard_Real aLabelWidth;
+ TCollection_ExtendedString aLabelString = GetValueString (aLabelWidth);
- /// PART 2 is for dimension computation using the working plane
+ gp_Pnt aFirstAttach = myCenterPoint.Translated (gp_Vec(myCenterPoint, myFirstPoint).Normalized() * GetFlyout());
+ gp_Pnt aSecondAttach = myCenterPoint.Translated (gp_Vec(myCenterPoint, mySecondPoint).Normalized() * GetFlyout());
- if (aFirstLin.Direction ().IsParallel (aSecondLin.Direction (), Precision::Angular ()))
- {
- // Parallel lines
- isSameLines = aFirstLin.Distance(aSecondLin.Location()) <= Precision::Confusion();
- if (!isSameLines)
- return Standard_False;
+ // Handle user-defined and automatic arrow placement
+ Standard_Boolean isArrowsExternal = Standard_False;
+ Standard_Integer aLabelPosition = LabelPosition_None;
+ FitTextAlignment (aDimensionAspect->TextHorizontalPosition(),
+ aLabelPosition, isArrowsExternal);
- myFirstPoint = aFirstLin.Location();
- mySecondPoint = ElCLib::Value (ElCLib::Parameter (aFirstLin, myFirstPoint), aSecondLin);
- if (mySecondPoint.Distance (mySecondPoint) <= Precision::Confusion ())
- mySecondPoint.Translate (gp_Vec (aSecondLin.Direction ())*Abs(GetFlyout()));
- myCenter.SetXYZ( (myFirstPoint.XYZ() + mySecondPoint.XYZ()) / 2. );
- }
- else
+ // Get text position
+ switch (aLabelPosition & LabelPosition_HMask)
{
- // Find intersection
- aFirstLin2d = ProjLib::Project (aPlane, aFirstLin);
- aSecondLin2d = ProjLib::Project (aPlane, aSecondLin);
-
- IntAna2d_AnaIntersection anInt2d (aFirstLin2d, aSecondLin2d);
- gp_Pnt2d anIntersectPoint;
- if (!anInt2d.IsDone() || anInt2d.IsEmpty())
+ case LabelPosition_HCenter:
{
- return Standard_False;
+ aTextPosition = GetCenterOnArc (aFirstAttach, aSecondAttach, myCenterPoint);
}
-
- anIntersectPoint = gp_Pnt2d (anInt2d.Point(1).Value());
- myCenter = ElCLib::To3d(aPlane.Position().Ax2(), anIntersectPoint);
-
- if (isInfinite1 || isInfinite2)
+ break;
+ case LabelPosition_Left:
{
- myFirstPoint = myCenter.Translated (gp_Vec (aFirstLin.Direction())*Abs (GetFlyout()));
- mySecondPoint = myCenter.Translated (gp_Vec (aSecondLin.Direction())*Abs (GetFlyout()));
- return Standard_True;
+ 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);
}
-
- // |
- // | <- dimension should be here
- // *----
- myFirstPoint = myCenter.Distance (aFirstPoint1) > myCenter.Distance (aLastPoint1) ? aFirstPoint1 : aLastPoint1;
- mySecondPoint = myCenter.Distance (aFirstPoint2) > myCenter.Distance (aLastPoint2) ? aFirstPoint2 : aLastPoint2;
+ 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 Standard_True;
-}
-
-//=======================================================================
-//function : canTextBeInCenter
-//purpose : Auxiliary method to arrange text and arrows
-//=======================================================================
-Standard_Boolean AIS_AngleDimension::canTextBeInCenter (const gp_Pnt& theFirstAttach,
- const gp_Pnt& theSecondAttach,
- const Quantity_Length& theTextLength,
- const Quantity_Length& theArrowLength)
-{
- gp_Vec anAttachVector (theFirstAttach, theSecondAttach);
- Standard_Real aValue = anAttachVector.Magnitude();
- return (aValue < theTextLength + 2.*theArrowLength) ? Standard_False : Standard_True;
+ return aTextPosition;
}
//=======================================================================
-//function: getCenterOnArc
-//purpose :
+//function : SetTextPosition
+//purpose :
//=======================================================================
-gp_Pnt AIS_AngleDimension::getCenterOnArc (const gp_Pnt& theFirstAttach,
- const gp_Pnt& theSecondAttach)
+void AIS_AngleDimension::SetTextPosition (const gp_Pnt& theTextPos)
{
- 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);
-
- // 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());
- gp_Pnt aCenterOnArc = ElCLib::To3d (GetWorkingPlane().Position().Ax2(), aTextCenterOnArc2d);
- return aCenterOnArc;
-}
-
-//=======================================================================
-//function: drawArcWithText
-//purpose :
-//=======================================================================
+ if (!IsValid())
+ {
+ return;
+ }
-void AIS_AngleDimension::drawArcWithText (const Handle(Prs3d_Presentation)& thePresentation,
- const gp_Pnt& theFirstAttach,
- const gp_Pnt& theSecondAttach,
- const TCollection_ExtendedString& theText,
- const AIS_DimensionDisplayMode theMode)
-{
- 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);
-
- // 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);
-
- // Drawing text
- gp_Vec aVec (theFirstAttach, theSecondAttach);
- Standard_Real aTextWidth = drawText (thePresentation,
- myIsTextReversed ? aVec.Reversed() : aVec,
- theText,theMode);
-
- // 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);
-
-
- gp_Lin2d aCenterToTextBeginLin = gce_MakeLin2d (aCenter2d, aTextBeginPnt),
- aCenterToTextEndLin = gce_MakeLin2d (aCenter2d, aTextEndPnt);
-
- // 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());
-
- anInt2d.Perform (aCenterToTextEndLin, aCircle);
- if (anInt2d.IsDone())
- if (!anInt2d.IsEmpty())
- aTextEndOnArc2d = gp_Pnt2d (anInt2d.Point (1).Value());
-
- gp_Pnt aTextBeginOnArc = ElCLib::To3d (GetWorkingPlane().Position().Ax2(), aTextBeginOnArc2d);
- gp_Pnt aTextEndOnArc = ElCLib::To3d (GetWorkingPlane().Position().Ax2(), aTextEndOnArc2d);
-
- // Drawing arcs
- if (theMode != AIS_DDM_Text)
+ // The text position point for angle dimension should belong to the working plane.
+ if (!GetPlane().Contains (theTextPos, Precision::Confusion()))
{
- drawArc (thePresentation, theFirstAttach, aTextBeginOnArc, myCenter, aRadius, theMode);
- drawArc (thePresentation, aTextEndOnArc, theSecondAttach, myCenter, aRadius, theMode);
+ throw Standard_ProgramError("The text position point for angle dimension doesn't belong to the working plane.");
}
+ myIsTextPositionFixed = Standard_True;
+ myFixedTextPosition = theTextPos;
}
//=======================================================================
-//function : drawArc
-//purpose : draws the arc between two attach points
+//function : AdjustParameters
+//purpose :
//=======================================================================
-
-void AIS_AngleDimension::drawArc (const Handle(Prs3d_Presentation)& thePresentation,
- const gp_Pnt& theFirstAttach,
- const gp_Pnt& theSecondAttach,
- const gp_Pnt& theCenter,
- const Standard_Real theRadius,
- const AIS_DimensionDisplayMode theMode)
+void AIS_AngleDimension::AdjustParameters (const gp_Pnt& theTextPos,
+ Standard_Real& theExtensionSize,
+ Prs3d_DimensionTextHorizontalPosition& theAlignment,
+ Standard_Real& theFlyout) const
{
- Handle(SelectMgr_EntityOwner) anEmptyOwner;
- Prs3d_Root::CurrentGroup (thePresentation)->
- SetPrimitivesAspect(myDrawer->DimensionAspect()->LineAspect()->Aspect());
-
- 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);
-
- 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;
-
- for (Standard_Integer anI = 1; anI < aPointsOnArc - 1; ++anI)
+ Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
+ Standard_Real anArrowLength = aDimensionAspect->ArrowAspect()->Length();
+
+ // 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())
{
- 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);
+ gp_Circ aCircle = aConstructCircle.Value();
- // Fill sensitive list
- myGeom.mySensitiveSegments.Append(new Select3D_SensitiveCurve(anEmptyOwner,aPointArray));
+ // Default values
+ theExtensionSize = aDimensionAspect->ArrowAspect()->Length();
+ theAlignment = Prs3d_DTHP_Center;
- // Fill display presentation
- if (!myDrawer->DimensionAspect()->IsText3d() && theMode == AIS_DDM_All)
+ Standard_Real aParamBeg = ElCLib::Parameter (aCircle, aFirstAttach);
+ Standard_Real aParamEnd = ElCLib::Parameter (aCircle, aSecondAttach);
+ if (aParamEnd < aParamBeg)
{
- Prs3d_Root::CurrentGroup (thePresentation)->SetStencilTestOptions (Standard_True);
+ Standard_Real aParam = aParamEnd;
+ aParamEnd = aParamBeg;
+ aParamBeg = aParam;
}
- Prs3d_Root::CurrentGroup (thePresentation)->AddPrimitiveArray (aPrimSegments);
- if (!myDrawer->DimensionAspect()->IsText3d() && theMode == AIS_DDM_All)
+
+ 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)
{
- Prs3d_Root::CurrentGroup (thePresentation)->SetStencilTestOptions (Standard_False);
+ theFlyout = aRadius;
+ return;
}
-}
-
-//=======================================================================
-//function : Compute
-//purpose : Having three gp_Pnt points compute presentation
-//=======================================================================
-void AIS_AngleDimension::Compute (const Handle(PrsMgr_PresentationManager3d)& /*thePM*/,
- const Handle(Prs3d_Presentation)& thePresentation,
- const Standard_Integer theMode)
-{
- thePresentation->Clear();
- myGeom.mySensitiveSegments.Clear();
- Handle(SelectMgr_EntityOwner) anEmptyOwner;
+ aParamBeg += M_PI;
+ aParamEnd += M_PI;
+ ElCLib::AdjustPeriodic (0.0, M_PI * 2, Precision::PConfusion(), aParamBeg, aParamEnd);
- if (!myIsInitialized)
+ if (aTextPar > aParamBeg && aTextPar < aParamEnd)
{
- if (myShapesNumber == 1)
- {
- myIsInitialized = initConeAngle (TopoDS::Face (myFirstShape));
- }
- else if (myShapesNumber == 2)
- {
- switch (myFirstShape.ShapeType())
- {
- case TopAbs_FACE:
- {
- myIsInitialized = initTwoFacesAngle ();
- }
- break;
- case TopAbs_EDGE:
- {
- myIsInitialized = initTwoEdgesAngle ();
- }
- break;
- default:
- return;
- }
- }
- else
- return;
+ theFlyout = -aRadius;
+ return;
}
- // If initialization failed
- if (!myIsInitialized)
- 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);
- // Parameters for presentation
- Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
- Prs3d_Root::CurrentGroup(thePresentation)->
- SetPrimitivesAspect(aDimensionAspect->LineAspect()->Aspect());
- Quantity_Length anArrowLength = aDimensionAspect->ArrowAspect()->Length();
- if (!myIsValueCustom)
- computeValue ();
- TCollection_ExtendedString aValueString;
- Standard_Real aTextLength;
- getTextWidthAndString (aTextLength, aValueString);
- if (!myIsWorkingPlaneCustom)
- countDefaultPlane();
- gp_Pnt aFirstAttach = myCenter.Translated (gp_Vec(myCenter, myFirstPoint).Normalized() * GetFlyout());
- gp_Pnt aSecondAttach = myCenter.Translated (gp_Vec(myCenter, mySecondPoint).Normalized() * GetFlyout());
- // Attach points and radius
- if (aDimensionAspect->HorizontalTextAlignment () == Prs3d_HTA_Center)
+ if (aFirstDist <= aSecondDist)
{
- aDimensionAspect->SetArrowOrientation (Prs3d_DAO_Internal);
+ aRadius = myCenterPoint.Distance (aFirstTextProj);
+ Standard_Real aNewExtensionSize = aFirstDist - anArrowLength;
+ theExtensionSize = aNewExtensionSize < 0.0 ? 0.0 : aNewExtensionSize;
- if (!canTextBeInCenter (aFirstAttach, aSecondAttach, aTextLength, anArrowLength))
- {
- aDimensionAspect->SetArrowOrientation (Prs3d_DAO_External);
- aDimensionAspect->SetHorizontalTextAlignment (Prs3d_HTA_Left);
- }
+ theAlignment = Prs3d_DTHP_Left;
+
+ gp_Vec aPosFlyoutDir = gp_Vec (myCenterPoint, myFirstPoint).Normalized().Scaled (aRadius);
+
+ theFlyout = aFirstTextProj.Distance (myCenterPoint.Translated (aPosFlyoutDir)) > Precision::Confusion()
+ ? -aRadius : aRadius;
}
else
- aDimensionAspect->SetArrowOrientation (Prs3d_DAO_External);
+ {
+ aRadius = myCenterPoint.Distance (aSecondTextProj);
- //Arrows positions and directions
- gp_Vec aFirstArrowVec = (gp_Vec(myCenter, aFirstAttach)^gp_Vec(GetWorkingPlane().Axis().Direction())).Normalized().Reversed()*anArrowLength;
- gp_Vec aSecondArrowVec = (gp_Vec(myCenter, aSecondAttach)^gp_Vec(GetWorkingPlane().Axis().Direction())).Normalized()*anArrowLength;
+ Standard_Real aNewExtensionSize = aSecondDist - anArrowLength;
- gp_Pnt aFirstArrowBegin,
- aFirstArrowEnd,
- aSecondArrowBegin,
- aSecondArrowEnd;
+ theExtensionSize = aNewExtensionSize < 0.0 ? 0.0 : aNewExtensionSize;
- if (aDimensionAspect->GetArrowOrientation() == Prs3d_DAO_External)
- {
- aFirstArrowVec.Reverse();
- aSecondArrowVec.Reverse();
+ theAlignment = Prs3d_DTHP_Right;
- aFirstArrowBegin = aFirstAttach.Translated (aFirstArrowVec);
- aFirstArrowEnd = aFirstAttach;
- aSecondArrowBegin = aSecondAttach;
- aSecondArrowEnd = aSecondAttach.Translated (aSecondArrowVec);
+ gp_Vec aPosFlyoutDir = gp_Vec (myCenterPoint, mySecondPoint).Normalized().Scaled (aRadius);
+
+ theFlyout = aSecondTextProj.Distance (myCenterPoint.Translated (aPosFlyoutDir)) > Precision::Confusion()
+ ? -aRadius : aRadius;
}
- else
+}
+
+//=======================================================================
+//function : FitTextAlignment
+//purpose :
+//=======================================================================
+void AIS_AngleDimension::FitTextAlignment (const Prs3d_DimensionTextHorizontalPosition& theHorizontalTextPos,
+ Standard_Integer& theLabelPosition,
+ Standard_Boolean& theIsArrowsExternal) const
+{
+ Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
+
+ Standard_Real 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())
{
- aFirstArrowBegin = aFirstAttach;
- aFirstArrowEnd = aFirstAttach.Translated (aFirstArrowVec);
- aSecondArrowBegin = aSecondAttach.Translated (aSecondArrowVec);
- aSecondArrowEnd = aSecondAttach;
+ aLabelWidth += aDimensionAspect->TextAspect()->Height() * THE_3D_TEXT_MARGIN * 2.0;
}
- // Fill presentation
- Handle(Graphic3d_ArrayOfSegments) aPrimSegments;
- Standard_Boolean isTextInCenter = aDimensionAspect->VerticalTextAlignment() == Prs3d_VTA_Center;
- if (aDimensionAspect->HorizontalTextAlignment() == Prs3d_HTA_Center)
+ 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())
{
- // Important! Current implementation doesn't draw the extensions here
- aPrimSegments = new Graphic3d_ArrayOfSegments (4);
- // Get text begin and end positions (text is positioned in the center between two attach points)
- gp_Pnt aTextBeginOnArc, aTextEndOnArc, anArcCenter;
- if (isTextInCenter && aDimensionAspect->IsText3d())
- {
- drawArcWithText (thePresentation, aFirstAttach, aSecondAttach, aValueString, (AIS_DimensionDisplayMode)theMode);
- }
- else
+ case Prs3d_DAO_External: theIsArrowsExternal = true; break;
+ case Prs3d_DAO_Internal: theIsArrowsExternal = false; break;
+ case Prs3d_DAO_Fit:
{
- gp_Vec aTextDir (aFirstArrowEnd, aSecondArrowBegin);
- myGeom.myTextPosition = getCenterOnArc (aFirstArrowEnd, aSecondArrowBegin);
- drawText (thePresentation,
- myIsTextReversed ? aTextDir.Reversed() : aTextDir,
- aValueString, (AIS_DimensionDisplayMode)theMode);
- if (theMode != AIS_DDM_Text)
- drawArc (thePresentation, aFirstArrowEnd, aSecondArrowBegin, myCenter, Abs (GetFlyout()), (AIS_DimensionDisplayMode)theMode);
+ 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;
}
}
- else
+
+ // Handle user-defined and automatic text placement
+ switch (theHorizontalTextPos)
{
- // Lines for extensions
- gp_Lin aLeftExtension (aFirstAttach,gp_Dir(aFirstArrowVec));
- gp_Lin aRightExtension (aSecondAttach, gp_Dir(aSecondArrowVec));
- aPrimSegments = new Graphic3d_ArrayOfSegments (6);
- gp_Pnt aStartPoint;
- if (aDimensionAspect->HorizontalTextAlignment() == Prs3d_HTA_Left)
- {
- aStartPoint = aFirstArrowBegin;
- // Short extension
- aPrimSegments->AddVertex (aSecondArrowEnd);
- aPrimSegments->AddVertex (aSecondArrowEnd.Translated(gp_Vec(aRightExtension.Direction())*anArrowLength));
- myGeom.mySensitiveSegments.Append (new Select3D_SensitiveSegment(anEmptyOwner,
- aSecondArrowEnd,
- aSecondArrowEnd.Translated(gp_Vec(aRightExtension.Direction())*anArrowLength)));
-
- // Long extension
- drawExtensionWithText (thePresentation, aStartPoint, aLeftExtension, aValueString, (AIS_DimensionDisplayMode)theMode);
- }
- else // Prs3d_HTA_Right
+ 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:
{
- aStartPoint = aSecondArrowEnd;
- // Short extension
- aPrimSegments->AddVertex (aFirstArrowBegin);
- aPrimSegments->AddVertex (aFirstArrowBegin.Translated (gp_Vec (aLeftExtension.Direction()) * anArrowLength));
- myGeom.mySensitiveSegments.Append (new Select3D_SensitiveSegment(anEmptyOwner,
- aFirstArrowBegin,
- aFirstArrowBegin.Translated (gp_Vec (aLeftExtension.Direction()) * anArrowLength)));
-
- // Long extension
- drawExtensionWithText (thePresentation, aStartPoint, aRightExtension, aValueString, (AIS_DimensionDisplayMode)theMode);
- }
+ gp_Vec anAttachVector (aFirstAttach, aSecondAttach);
+ Standard_Real aDimensionWidth = anAttachVector.Magnitude();
+ Standard_Real anArrowsWidth = anArrowLength * 2.0;
+ Standard_Real aContentWidth = theIsArrowsExternal ? aLabelWidth : aLabelWidth + anArrowsWidth;
- if (theMode != AIS_DDM_Text)
- {
- // Draw main arc
- drawArc (thePresentation, aFirstArrowEnd, aSecondArrowBegin, myCenter, Abs(GetFlyout ()), (AIS_DimensionDisplayMode)theMode);
+ theLabelPosition |= aDimensionWidth < aContentWidth ? LabelPosition_Left : LabelPosition_HCenter;
+ break;
}
}
- // Draw flyout lines and arrows in new group.
- Prs3d_Root::NewGroup (thePresentation)
- ->SetPrimitivesAspect (myDrawer->DimensionAspect()->LineAspect()->Aspect());
- if (theMode == AIS_DDM_All && myIsFlyoutLines)
- {
- aPrimSegments->AddVertex (myCenter);
- aPrimSegments->AddVertex (aFirstAttach);
- aPrimSegments->AddVertex (myCenter);
- aPrimSegments->AddVertex (aSecondAttach);
- }
- if (theMode != AIS_DDM_Text)
+ switch (aDimensionAspect->TextVerticalPosition())
{
- Prs3d_Root::CurrentGroup (thePresentation)->AddPrimitiveArray (aPrimSegments);
- drawArrow (thePresentation, aFirstAttach, gp_Dir (aFirstArrowVec));
- drawArrow (thePresentation, aSecondAttach, gp_Dir (aSecondArrowVec));
+ case Prs3d_DTVP_Above : theLabelPosition |= LabelPosition_Above; break;
+ case Prs3d_DTVP_Below : theLabelPosition |= LabelPosition_Below; break;
+ case Prs3d_DTVP_Center : theLabelPosition |= LabelPosition_VCenter; break;
}
-
- setComputed (Standard_True);
}