From: nds Date: Fri, 29 Apr 2016 09:13:34 +0000 (+0300) Subject: #1449 Additional angle presentation: class is renamed because of linking trouble... X-Git-Tag: V_2.3.0~64 X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=30269a68f190e02c9aaf3d4596ad6f41ee44a2d4;p=modules%2Fshaper.git #1449 Additional angle presentation: class is renamed because of linking trouble on Linux. Later, the modification is planed to integrate in OCCT, so the sources of the previous version should be taken --- diff --git a/src/SketcherPrs/AIS_AngleDimension.cxx b/src/SketcherPrs/AIS_AngleDimension.cxx deleted file mode 100755 index f37afab0a..000000000 --- a/src/SketcherPrs/AIS_AngleDimension.cxx +++ /dev/null @@ -1,1441 +0,0 @@ -// Created on: 1996-12-05 -// Created by: Arnaud BOUZY/Odile Olivier -// Copyright (c) 1996-1999 Matra Datavision -// Copyright (c) 1999-2014 OPEN CASCADE SAS -// -// This file is part of Open CASCADE Technology software library. -// -// 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. -// -// Alternatively, this file may be used under the terms of Open CASCADE -// commercial license or contractual agreement. - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -IMPLEMENT_STANDARD_HANDLE (AIS_AngleDimension, AIS_Dimension) -IMPLEMENT_STANDARD_RTTIEXT (AIS_AngleDimension, AIS_Dimension) - -namespace -{ - 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; -}; - -//======================================================================= -//function : Constructor -//purpose : -//======================================================================= -AIS_AngleDimension::AIS_AngleDimension (const TopoDS_Edge& theFirstEdge, - const TopoDS_Edge& theSecondEdge) -: AIS_Dimension (AIS_KOD_PLANEANGLE) -{ - Init(); - SetMeasuredGeometry (theFirstEdge, theSecondEdge); -} - -//======================================================================= -//function : Constructor -//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); -} - -//======================================================================= -//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(); - SetMeasuredGeometry (theFirstVertex, theSecondVertex, theThirdVertex); -} - -//======================================================================= -//function : Constructor -//purpose : -//======================================================================= -AIS_AngleDimension::AIS_AngleDimension (const TopoDS_Face& theCone) -: AIS_Dimension (AIS_KOD_PLANEANGLE) -{ - Init(); - SetMeasuredGeometry (theCone); -} - -//======================================================================= -//function : Constructor -//purpose : -//======================================================================= -AIS_AngleDimension::AIS_AngleDimension (const TopoDS_Face& theFirstFace, - const TopoDS_Face& theSecondFace) -: AIS_Dimension (AIS_KOD_PLANEANGLE) -{ - Init(); - SetMeasuredGeometry (theFirstFace, theSecondFace); -} - -//======================================================================= -//function : Constructor -//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); -} - -//======================================================================= -//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) - { - ComputePlane(); - } - - SetToUpdate(); -} - -//======================================================================= -//function : SetMeasuredGeometry -//purpose : -//======================================================================= -void AIS_AngleDimension::SetMeasuredGeometry (const gp_Pnt& theFirstPoint, - const gp_Pnt& theSecondPoint, - const gp_Pnt& theThirdPoint) -{ - 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); - - if (myIsGeometryValid && !myIsPlaneCustom) - { - ComputePlane(); - } - - SetToUpdate(); -} - -//======================================================================= -//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); - - if (myIsGeometryValid && !myIsPlaneCustom) - { - ComputePlane(); - } - - SetToUpdate(); -} - -//======================================================================= -//function : SetMeasuredGeometry -//purpose : -//======================================================================= -void AIS_AngleDimension::SetMeasuredGeometry (const TopoDS_Face& theCone) -{ - myFirstShape = theCone; - mySecondShape = TopoDS_Shape(); - myThirdShape = TopoDS_Shape(); - myGeometryType = GeometryType_Face; - myIsGeometryValid = InitConeAngle(); - - if (myIsGeometryValid && !myIsPlaneCustom) - { - ComputePlane(); - } - - SetToUpdate(); -} - -//======================================================================= -//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() -{ - SetAngleReversed (Standard_False); - SetArrowVisible (Standard_True, Standard_True); - 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(); - if (myUseReverse) { - 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 : 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) -{ - // construct plane where the circle and the arc are located - gce_MakePln aConstructPlane (theFirstAttach, theSecondAttach, theCenter); - if (!aConstructPlane.IsDone()) - { - return; - } - - gp_Pln aPlane = aConstructPlane.Value(); - if (myUseReverse) { - 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); - - gp_Ax1 anAxis = aPlane.Axis(); - gp_Dir aDir = anAxis.Direction(); - gp_Vec aRefVec(aDir); - Standard_Real anAngle = aCenterToFirstVec.AngleWithRef (aCenterToSecondVec, aRefVec); - if (anAngle < 0) - anAngle = 2.0 * M_PI + anAngle; - 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) -{ - // construct plane where the circle and the arc are located - gce_MakePln aConstructPlane (theFirstAttach, theSecondAttach, theCenter); - if (!aConstructPlane.IsDone()) - { - return; - } - - gp_Pln aPlane = aConstructPlane.Value(); - - 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 aSectorOnCircle = theTextWidth / aRadius; - - gp_Pnt aTextPntBeg = ElCLib::Value (aParamMid - aSectorOnCircle * 0.5, aCircle); - gp_Pnt aTextPntEnd = ElCLib::Value (aParamMid + aSectorOnCircle * 0.5, aCircle); - - // Drawing arcs - DrawArc (thePresentation, theFirstAttach, aTextPntBeg, theCenter, aRadius, theMode); - DrawArc (thePresentation, theSecondAttach, aTextPntEnd, 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; - } - - gp_Vec aFirstVec = gp_Vec (myCenterPoint, myFirstPoint).Normalized(); - gp_Vec aSecondVec = gp_Vec (myCenterPoint, mySecondPoint).Normalized(); - gp_Vec aDirectionN = aSecondVec.Crossed (aFirstVec).Normalized(); - gp_Vec aDirectionY = (aFirstVec + aSecondVec).Normalized(); - gp_Vec aDirectionX = aDirectionY.Crossed (aDirectionN).Normalized(); - - 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 = aVec2.AngleWithRef (aVec1, GetPlane().Axis().Direction()); - - 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) -{ - thePresentation->Clear(); - mySelectionGeom.Clear (theMode); - - if (!IsValid()) - { - return; - } - - // Parameters for presentation - Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect(); - - Prs3d_Root::CurrentGroup(thePresentation)->SetPrimitivesAspect (aDimensionAspect->LineAspect()->Aspect()); - - 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; - } - - // 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 aWPDir = gp_Vec (GetPlane().Axis().Direction()); - - gp_Dir aFirstExtensionDir = aWPDir ^ gp_Vec (myCenterPoint, aFirstAttach); - gp_Dir aSecondExtensionDir = aWPDir.Reversed() ^ gp_Vec (myCenterPoint, aSecondAttach); - - gp_Vec aFirstArrowVec = gp_Vec (aFirstExtensionDir) * anArrowLength; - gp_Vec aSecondArrowVec = gp_Vec (aSecondExtensionDir) * anArrowLength; - - 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); - - if (isArrowsExternal) - { - aFirstArrowVec.Reverse(); - aSecondArrowVec.Reverse(); - } - - 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 || !myFirstArrowVisible) ? aFirstAttach : aFirstArrowEnd, - (isArrowsExternal || !mySecondArrowVisible) ? aSecondAttach : aSecondArrowEnd, - myCenterPoint, - Abs (GetFlyout()), - theMode); - } - } - break; - - case LabelPosition_Left : - { - DrawExtension (thePresentation, - anExtensionSize, - (isArrowsExternal && myFirstArrowVisible) ? aFirstArrowEnd : aFirstAttach, - aFirstExtensionDir, - aLabelString, - aLabelWidth, - theMode, - aLabelPosition); - } - break; - - case LabelPosition_Right : - { - DrawExtension (thePresentation, - anExtensionSize, - (isArrowsExternal && mySecondArrowVisible) ? 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 || !myFirstArrowVisible) ? aFirstAttach : aFirstArrowEnd, - (isArrowsExternal || !mySecondArrowVisible) ? aSecondAttach : aSecondArrowEnd, - myCenterPoint, - Abs(GetFlyout ()), - theMode); - } - - // arrows and arrow extensions - if (theMode == ComputeMode_All || theMode == ComputeMode_Line) - { - Prs3d_Root::NewGroup (thePresentation); - - if (myFirstArrowVisible) - DrawArrow (thePresentation, aFirstArrowBegin, gp_Dir (aFirstArrowVec)); - if (mySecondArrowVisible) - DrawArrow (thePresentation, aSecondArrowBegin, gp_Dir (aSecondArrowVec)); - } - - if ((theMode == ComputeMode_All || theMode == ComputeMode_Line) && isArrowsExternal) - { - Prs3d_Root::NewGroup (thePresentation); - - if (aHPosition != LabelPosition_Left && myFirstArrowVisible) - { - DrawExtension (thePresentation, - aDimensionAspect->ArrowTailSize(), - aFirstArrowEnd, - aFirstExtensionDir, - THE_EMPTY_LABEL_STRING, - THE_EMPTY_LABEL_WIDTH, - theMode, - LabelPosition_None); - } - - if (aHPosition != LabelPosition_Right && mySecondArrowVisible) - { - 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 = Abs (aFirstLin.Angle (aSecondLin) - M_PI) <= Precision::Angular(); - - gp_Pnt aPoint = aFirstLine->Value (0.0); - gp_Dir aNormal = isParallelLines - ? gp_Vec (aSecondLin.Normal (aPoint).Direction()) ^ gp_Vec (aSecondLin.Direction()) - : gp_Vec (aFirstLin.Direction()) ^ gp_Vec (aSecondLin.Direction()); - - theComputedPlane = gp_Pln (aPoint, aNormal); - - // Compute geometry for this plane and edges - Standard_Boolean isInfinite1,isInfinite2; - gp_Pnt aFirstPoint1, aLastPoint1, aFirstPoint2, aLastPoint2; - gp_Lin2d aFirstLin2d, aSecondLin2d; - - if (!AIS::ComputeGeometry (aFirstEdge, aSecondEdge, - aFirstLine, aSecondLine, - aFirstPoint1, aLastPoint1, - aFirstPoint2, aLastPoint2, - isInfinite1, isInfinite2)) - { - return Standard_False; - } - - if (aFirstLin.Direction().IsParallel (aSecondLin.Direction(), Precision::Angular())) - { - myFirstPoint = aFirstLin.Location(); - mySecondPoint = ElCLib::Value (ElCLib::Parameter (aFirstLin, myFirstPoint), aSecondLin); - - if (mySecondPoint.Distance (myFirstPoint) <= Precision::Confusion()) - { - mySecondPoint.Translate (gp_Vec (aSecondLin.Direction()) * Abs (GetFlyout())); - } - - myCenterPoint.SetXYZ ((myFirstPoint.XYZ() + mySecondPoint.XYZ()) / 2.0); - } - 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.IsEqual(aFirstPoint1, Precision::Confusion()) - ? aFirstPoint1 - : aLastPoint1; - mySecondPoint = !myCenterPoint.IsEqual(aFirstPoint2, Precision::Confusion()) - ? 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 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 && 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 : InitTwoFacesAngle -//purpose : initialization of angle dimension between two faces -//======================================================================= -Standard_Boolean AIS_AngleDimension::InitTwoFacesAngle (const gp_Pnt thePointOnFirstFace) -{ - 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); - - 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 -//purpose : initialization of the cone angle -//======================================================================= -Standard_Boolean AIS_AngleDimension::InitConeAngle() -{ - if (myFirstShape.IsNull()) - { - return Standard_False; - } - - TopoDS_Face aConeShape = TopoDS::Face (myFirstShape); - gp_Pln aPln; - gp_Cone aCone; - gp_Circ aCircle; - // A surface from the Face - Handle(Geom_Surface) aSurf; - Handle(Geom_OffsetSurface) aOffsetSurf; - Handle(Geom_ConicalSurface) aConicalSurf; - Handle(Geom_SurfaceOfRevolution) aRevSurf; - Handle(Geom_Line) aLine; - BRepAdaptor_Surface aConeAdaptor (aConeShape); - TopoDS_Face aFace; - AIS_KindOfSurface aSurfType; - Standard_Real anOffset = 0.; - Handle(Standard_Type) aType; - - Standard_Real aMaxV = aConeAdaptor.FirstVParameter(); - Standard_Real aMinV = aConeAdaptor.LastVParameter(); - - AIS::GetPlaneFromFace (aConeShape, aPln, aSurf, aSurfType, anOffset); - - if (aSurfType == AIS_KOS_Revolution) - { - // Surface of revolution - aRevSurf = Handle(Geom_SurfaceOfRevolution)::DownCast(aSurf); - gp_Lin aLin (aRevSurf->Axis()); - Handle(Geom_Curve) aBasisCurve = aRevSurf->BasisCurve(); - //Must be a part of line (basis curve should be linear) - if (aBasisCurve ->DynamicType() != STANDARD_TYPE(Geom_Line)) - return Standard_False; - - gp_Pnt aFirst1 = aConeAdaptor.Value (0., aMinV); - gp_Pnt aLast1 = aConeAdaptor.Value (0., aMaxV); - gp_Vec aVec1 (aFirst1, aLast1); - - //Projection on - gp_Pnt aFirst2 = ElCLib::Value (ElCLib::Parameter (aLin, aFirst1), aLin); - // Projection on - gp_Pnt aLast2 = ElCLib::Value (ElCLib::Parameter (aLin, aLast1), aLin); - - gp_Vec aVec2 (aFirst2, aLast2); - - // Check if two parts of revolution are parallel (it's a cylinder) or normal (it's a circle). - if (aVec1.IsParallel (aVec2, Precision::Angular()) - || aVec1.IsNormal (aVec2,Precision::Angular())) - return Standard_False; - - gce_MakeCone aMkCone (aRevSurf->Axis(), aFirst1, aLast1); - aCone = aMkCone.Value(); - myCenterPoint = aCone.Apex(); - } - else - { - aType = aSurf->DynamicType(); - if (aType == STANDARD_TYPE(Geom_OffsetSurface) || anOffset > 0.01) - { - // Offset surface - aOffsetSurf = new Geom_OffsetSurface (aSurf, anOffset); - aSurf = aOffsetSurf->Surface(); - BRepBuilderAPI_MakeFace aMkFace(aSurf, Precision::Confusion()); - aMkFace.Build(); - if (!aMkFace.IsDone()) - return Standard_False; - aConeAdaptor.Initialize (aMkFace.Face()); - } - aCone = aConeAdaptor.Cone(); - aConicalSurf = Handle(Geom_ConicalSurface)::DownCast (aSurf); - myCenterPoint = aConicalSurf->Apex(); - } - - // A circle where the angle is drawn - Handle(Geom_Curve) aCurve; - Standard_Real aMidV = ( aMinV + aMaxV ) / 2.5; - aCurve = aSurf->VIso (aMidV); - aCircle = Handle(Geom_Circle)::DownCast (aCurve)->Circ(); - - aCurve = aSurf->VIso(aMaxV); - gp_Circ aCircVmax = Handle(Geom_Circle)::DownCast(aCurve)->Circ(); - aCurve = aSurf->VIso(aMinV); - gp_Circ aCircVmin = Handle(Geom_Circle)::DownCast(aCurve)->Circ(); - - if (aCircVmax.Radius() < aCircVmin.Radius()) - { - gp_Circ aTmpCirc = aCircVmax; - aCircVmax = aCircVmin; - aCircVmin = aTmpCirc; - } - - myFirstPoint = ElCLib::Value (0, aCircle); - mySecondPoint = ElCLib::Value (M_PI, aCircle); - return Standard_True; -} - -//======================================================================= -//function : IsValidPoints -//purpose : -//======================================================================= -Standard_Boolean AIS_AngleDimension::IsValidPoints (const gp_Pnt& theFirstPoint, - const gp_Pnt& theCenterPoint, - const gp_Pnt& theSecondPoint) const -{ - return theFirstPoint.Distance (theCenterPoint) > Precision::Confusion() - && theSecondPoint.Distance (theCenterPoint) > Precision::Confusion() - && 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 : SetAngleReversed -//purpose : -//======================================================================= -void AIS_AngleDimension::SetAngleReversed(const Standard_Boolean& theUseReverse) -{ - myUseReverse = theUseReverse; -} - -//======================================================================= -//function : SetArrowVisible -//purpose : -//======================================================================= -void AIS_AngleDimension::SetArrowVisible(const Standard_Boolean& theFirstArrowVisible, - const Standard_Boolean& theSecondArrowVisible) -{ - myFirstArrowVisible = theFirstArrowVisible; - mySecondArrowVisible = theSecondArrowVisible; -} - -//======================================================================= -//function : AdjustParameters -//purpose : -//======================================================================= -void AIS_AngleDimension::AdjustParameters (const gp_Pnt& theTextPos, - Standard_Real& theExtensionSize, - Prs3d_DimensionTextHorizontalPosition& theAlignment, - Standard_Real& theFlyout) const -{ - 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()) - { - 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) - { - theFlyout = aRadius; - return; - } - - aParamBeg += M_PI; - aParamEnd += M_PI; - ElCLib::AdjustPeriodic (0.0, M_PI * 2, Precision::PConfusion(), aParamBeg, aParamEnd); - - if (aTextPar > aParamBeg && aTextPar < aParamEnd) - { - theFlyout = -aRadius; - 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); - - theFlyout = 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); - - theFlyout = 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; - } -} diff --git a/src/SketcherPrs/AIS_AngleDimension.hxx b/src/SketcherPrs/AIS_AngleDimension.hxx deleted file mode 100755 index b09fa7543..000000000 --- a/src/SketcherPrs/AIS_AngleDimension.hxx +++ /dev/null @@ -1,365 +0,0 @@ -// Copyright (c) 1995-1999 Matra Datavision -// Copyright (c) 1999-2013 OPEN CASCADE SAS -// -// This file is part of Open CASCADE Technology software library. -// -// 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. -// -// Alternatively, this file may be used under the terms of Open CASCADE -// commercial license or contractual agreement. - -#ifndef _AIS_AngleDimension_HeaderFile -#define _AIS_AngleDimension_HeaderFile - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -DEFINE_STANDARD_HANDLE (AIS_AngleDimension, AIS_Dimension) - -//! Angle dimension. Can be constructed: -//! - on two intersected edges. -//! - on three points or vertices. -//! - on conical face. -//! - between two intersected faces. -//! -//! In case of three points or two intersected edges the dimension plane -//! (on which dimension presentation is built) can be computed uniquely -//! as through three defined points can be built only one plane. -//! Therefore, if user-defined plane differs from this one, the dimension can't be built. -//! -//! In cases of two planes automatic plane by default is built on point of the -//! origin of parametric space of the first face (the basis surface) so, that -//! the working plane and two faces intersection forms minimal angle between the faces. -//! User can define the other point which the dimension plane should pass through -//! using the appropriate constructor. This point can lay on the one of the faces or not. -//! Also user can define his own plane but it should pass through the three points -//! computed on the geometry initialization step (when the constructor or SetMeasuredGeometry() method -//! is called). -//! -//! In case of the conical face the center point of the angle is the apex of the conical surface. -//! The attachment points are points of the first and the last parameter of the basis circle of the cone. -//! -class AIS_AngleDimension : public AIS_Dimension -{ -public: - - //! Constructs minimum angle dimension between two linear edges (where possible). - //! These two edges should be intersected by each other. Otherwise the geometry is not valid. - //! @param theFirstEdge [in] the first edge. - //! @param theSecondEdge [in] the second edge. - //! the maximum distanced point of edges from the presentation center - Standard_EXPORT AIS_AngleDimension (const TopoDS_Edge& theFirstEdge, - const TopoDS_Edge& theSecondEdge); - - //! Constructs the angle display object defined by three points. - //! @param theFirstPoint [in] the first point (point on first angle flyout). - //! @param theSecondPoint [in] the center point of angle dimension. - //! @param theThirdPoint [in] the second point (point on second angle flyout). - Standard_EXPORT AIS_AngleDimension (const gp_Pnt& theFirstPoint, - const gp_Pnt& theSecondPoint, - const gp_Pnt& theThirdPoint); - - //! Constructs the angle display object defined by three vertices. - //! @param theFirstVertex [in] the first vertex (vertex for first angle flyout). - //! @param theSecondVertex [in] the center vertex of angle dimension. - //! @param theThirdPoint [in] the second vertex (vertex for second angle flyout). - Standard_EXPORT AIS_AngleDimension (const TopoDS_Vertex& theFirstVertex, - const TopoDS_Vertex& theSecondVertex, - const TopoDS_Vertex& theThirdVertex); - - //! Constructs angle dimension for the cone face. - //! @param theCone [in] the conical face. - Standard_EXPORT AIS_AngleDimension (const TopoDS_Face& theCone); - - //! Constructs angle dimension between two planar faces. - //! @param theFirstFace [in] the first face. - //! @param theSecondFace [in] the second face. - Standard_EXPORT AIS_AngleDimension (const TopoDS_Face& theFirstFace, - const TopoDS_Face& theSecondFace); - - //! Constructs angle dimension between two planar faces. - //! @param theFirstFace [in] the first face. - //! @param theSecondFace [in] the second face. - //! @param thePoint [in] the point which the dimension plane should pass through. - //! This point can lay on the one of the faces or not. - Standard_EXPORT AIS_AngleDimension (const TopoDS_Face& theFirstFace, - const TopoDS_Face& theSecondFace, - const gp_Pnt& thePoint); - -public: - - //! @return first point forming the angle. - const gp_Pnt& FirstPoint() const - { - return myFirstPoint; - } - - //! @return second point forming the angle. - const gp_Pnt& SecondPoint() const - { - return mySecondPoint; - } - - //! @return center point forming the angle. - const gp_Pnt& CenterPoint() const - { - return myCenterPoint; - } - - //! @return first argument shape. - const TopoDS_Shape& FirstShape() const - { - return myFirstShape; - } - - //! @return second argument shape. - const TopoDS_Shape& SecondShape() const - { - return mySecondShape; - } - - //! @return third argument shape. - const TopoDS_Shape& ThirdShape() const - { - return myThirdShape; - } - -public: - - //! Measures minimum angle dimension between two linear edges. - //! These two edges should be intersected by each other. Otherwise the geometry is not valid. - //! @param theFirstEdge [in] the first edge. - //! @param theSecondEdge [in] the second edge. - //! the maximum distanced point of edges from the presentation center - Standard_EXPORT void SetMeasuredGeometry (const TopoDS_Edge& theFirstEdge, - const TopoDS_Edge& theSecondEdge); - - //! Measures angle defined by three points. - //! @param theFirstPoint [in] the first point (point on first angle flyout). - //! @param theSecondPoint [in] the center point of angle dimension. - //! @param theThirdPoint [in] the second point (point on second angle flyout). - Standard_EXPORT void SetMeasuredGeometry (const gp_Pnt& theFirstPoint, - const gp_Pnt& theSecondPoint, - const gp_Pnt& theThridPoint); - - //! Measures angle defined by three vertices. - //! @param theFirstVertex [in] the first vertex (vertex for first angle flyout). - //! @param theSecondVertex [in] the center vertex of angle dimension. - //! @param theThirdPoint [in] the second vertex (vertex for second angle flyout). - Standard_EXPORT void SetMeasuredGeometry (const TopoDS_Vertex& theFirstVertex, - const TopoDS_Vertex& theSecondVertex, - const TopoDS_Vertex& theThirdVertex); - - //! Measures angle of conical face. - //! @param theCone [in] the shape to measure. - Standard_EXPORT void SetMeasuredGeometry (const TopoDS_Face& theCone); - - //! Measures angle between two planar faces. - //! @param theFirstFace [in] the first face. - //! @param theSecondFace [in] the second face.. - Standard_EXPORT void SetMeasuredGeometry (const TopoDS_Face& theFirstFace, - const TopoDS_Face& theSecondFace); - - //! Measures angle between two planar faces. - //! @param theFirstFace [in] the first face. - //! @param theSecondFace [in] the second face. - //! @param thePoint [in] the point which the dimension plane should pass through. - //! This point can lay on the one of the faces or not. - Standard_EXPORT void SetMeasuredGeometry (const TopoDS_Face& theFirstFace, - const TopoDS_Face& theSecondFace, - const gp_Pnt& thePoint); - - //! @return the display units string. - Standard_EXPORT virtual const TCollection_AsciiString& GetDisplayUnits() const; - - //! @return the model units string. - Standard_EXPORT virtual const TCollection_AsciiString& GetModelUnits() const; - - Standard_EXPORT virtual void SetDisplayUnits (const TCollection_AsciiString& theUnits); - - Standard_EXPORT virtual void SetModelUnits (const TCollection_AsciiString& theUnits); - - //! Principle of horizontal text alignment settings: - //! - divide circle into two halves according to attachment points - //! - if aTextPos is between attach points -> Center + positive flyout - //! - if aTextPos is not between attach points but in this half -> Left or Right + positive flyout - //! - if aTextPos is between reflections of attach points -> Center + negative flyout - //! - if aTextPos is not between reflections of attach points -> Left or Right + negative flyout - Standard_EXPORT virtual void SetTextPosition (const gp_Pnt& theTextPos); - - Standard_EXPORT virtual const gp_Pnt GetTextPosition () const; - - //! Sets state if the angle arc should be built reversing to the presentation plane. - //! Default state is not reversed - //! @param theUseReverse [in] the boolean state. - void SetAngleReversed(const Standard_Boolean& theUseReverse); - - //! Sets visible state of angle arrows. Default value is true for both - //! @param theFirstArrowVisible [in] the visibility of the first arrow. - //! @param theSecondArrowVisible [in] the visibility of the second arrow. - void SetArrowVisible(const Standard_Boolean& theFirstArrowVisible, - const Standard_Boolean& theSecondArrowVisible); - -public: - - DEFINE_STANDARD_RTTI (AIS_AngleDimension) - -protected: - - //! Initialization of fields that is common to all constructors. - Standard_EXPORT void Init(); - - //! @param theFirstAttach [in] the first attachment point. - //! @param theSecondAttach [in] the second attachment point. - //! @param theCenter [in] the center point (center point of the angle). - //! @return the center of the dimension arc (the main dimension line in case of angle). - Standard_EXPORT gp_Pnt GetCenterOnArc (const gp_Pnt& theFirstAttach, - const gp_Pnt& theSecondAttach, - const gp_Pnt& theCenter) const; - - //! Draws main dimension line (arc). - //! @param thePresentation [in] the dimension presentation. - //! @param theFirstAttach [in] the first attachment point. - //! @param theSecondAttach [in] the second attachment point. - //! @param theCenter [in] the center point (center point of the angle). - //! @param theRadius [in] the radius of the dimension arc. - //! @param theMode [in] the display mode. - Standard_EXPORT void 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); - - //! Draws main dimension line (arc) with text. - //! @param thePresentation [in] the dimension presentation. - //! @param theFirstAttach [in] the first attachment point. - //! @param theSecondAttach [in] the second attachment point. - //! @param theCenter [in] the center point (center point of the angle). - //! @param theText [in] the text label string. - //! @param theTextWidth [in] the text label width. - //! @param theMode [in] the display mode. - //! @param theLabelPosition [in] the text label vertical and horizontal positioning option - //! respectively to the main dimension line. - Standard_EXPORT void 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); - - //! Fits text alignment relatively to the dimension line; - //! it computes the value of label position and arrow orientation - //! according set in the aspect and dimension properties. - //! @param theHorizontalTextPos [in] the horizontal alignment for text position. - //! @param theLabelPosition [out] the label position, contains bits that defines - //! vertical and horizontal alignment. (for internal usage in count text position). - //! @param theIsArrowExternal [out] is the arrows external, - //! if arrow orientation in the dimension aspect is Prs3d_DAO_Fit, it fits arrow - //! orientation automatically. - Standard_EXPORT void FitTextAlignment (const Prs3d_DimensionTextHorizontalPosition& theHorizontalTextPos, - Standard_Integer& theLabelPosition, - Standard_Boolean& theIsArrowsExternal) const; - - //! Adjusts aspect parameters according the text position: - //! extension size, vertical text alignment and flyout. - //! @param theTextPos [in] the user defined 3d point of text position. - //! @param theExtensionSize [out] the adjusted extension size. - //! @param theAlignment [out] the horizontal label alignment. - //! @param theFlyout [out] the adjusted value of flyout. - Standard_EXPORT void AdjustParameters (const gp_Pnt& theTextPos, - Standard_Real& theExtensionSize, - Prs3d_DimensionTextHorizontalPosition& theAlignment, - Standard_Real& theFlyout) const; - -protected: - - Standard_EXPORT virtual void ComputePlane(); - - //! Checks if the plane includes three angle points to build dimension. - Standard_EXPORT virtual Standard_Boolean CheckPlane (const gp_Pln& thePlane) const; - - Standard_EXPORT virtual Standard_Real ComputeValue() const; - - Standard_EXPORT virtual void Compute (const Handle(PrsMgr_PresentationManager3d)& thePM, - const Handle(Prs3d_Presentation)& thePresentation, - const Standard_Integer theMode = 0); - - Standard_EXPORT virtual void ComputeFlyoutSelection (const Handle(SelectMgr_Selection)& theSelection, - const Handle(SelectMgr_EntityOwner)& theOwner); - -protected: - - //! Init angular dimension to measure angle between two linear edges. - //! the maximum distanced point of edges from the presentation center - //! @return TRUE if the angular dimension can be constructured - //! for the passed edges. - Standard_EXPORT Standard_Boolean InitTwoEdgesAngle (gp_Pln& theComputedPlane); - - //! Init angular dimension to measure angle between two planar faces. - //! there is no user-defined poisitoning. So attach points are set - //! according to faces geometry (in origin of the first face basis surface). - //! @return TRUE if the angular dimension can be constructed - //! for the passed faces. - Standard_EXPORT Standard_Boolean InitTwoFacesAngle(); - - //! Init angular dimension to measure angle between two planar faces. - //! @param thePointOnFirstFace [in] the point which the dimension plane should pass through. - //! This point can lay on the one of the faces or not. - //! It will be projected on the first face and this point will be set - //! as the first point attach point. - //! It defines some kind of dimension positioning over the faces. - //! @return TRUE if the angular dimension can be constructed - //! for the passed faces. - Standard_EXPORT Standard_Boolean InitTwoFacesAngle (const gp_Pnt thePointOnFirstFace); - - //! Init angular dimension to measure cone face. - //! @return TRUE if the angular dimension can be constructed - //! for the passed cone. - Standard_EXPORT Standard_Boolean InitConeAngle(); - - //! Check that the points forming angle are valid. - //! @return TRUE if the points met the following requirements: - //! The (P1, Center), (P2, Center) can be built. - //! The angle between the vectors > Precision::Angular(). - Standard_EXPORT Standard_Boolean IsValidPoints (const gp_Pnt& theFirstPoint, - const gp_Pnt& theCenterPoint, - const gp_Pnt& theSecondPoint) const; - -private: - Standard_Boolean myUseReverse; - - Standard_Boolean myFirstArrowVisible; - Standard_Boolean mySecondArrowVisible; - - gp_Pnt myFirstPoint; - gp_Pnt mySecondPoint; - gp_Pnt myCenterPoint; - TopoDS_Shape myFirstShape; - TopoDS_Shape mySecondShape; - TopoDS_Shape myThirdShape; -}; - -#endif // _AIS_AngleDimension_HeaderFile diff --git a/src/SketcherPrs/AIS_AngleDimension_.cxx b/src/SketcherPrs/AIS_AngleDimension_.cxx new file mode 100755 index 000000000..c4d6ab40f --- /dev/null +++ b/src/SketcherPrs/AIS_AngleDimension_.cxx @@ -0,0 +1,1441 @@ +// Created on: 1996-12-05 +// Created by: Arnaud BOUZY/Odile Olivier +// Copyright (c) 1996-1999 Matra Datavision +// Copyright (c) 1999-2014 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// 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. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +IMPLEMENT_STANDARD_HANDLE (AIS_AngleDimension_, AIS_Dimension) +IMPLEMENT_STANDARD_RTTIEXT (AIS_AngleDimension_, AIS_Dimension) + +namespace +{ + 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; +}; + +//======================================================================= +//function : Constructor +//purpose : +//======================================================================= +AIS_AngleDimension_::AIS_AngleDimension_ (const TopoDS_Edge& theFirstEdge, + const TopoDS_Edge& theSecondEdge) +: AIS_Dimension (AIS_KOD_PLANEANGLE) +{ + Init(); + SetMeasuredGeometry (theFirstEdge, theSecondEdge); +} + +//======================================================================= +//function : Constructor +//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); +} + +//======================================================================= +//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(); + SetMeasuredGeometry (theFirstVertex, theSecondVertex, theThirdVertex); +} + +//======================================================================= +//function : Constructor +//purpose : +//======================================================================= +AIS_AngleDimension_::AIS_AngleDimension_ (const TopoDS_Face& theCone) +: AIS_Dimension (AIS_KOD_PLANEANGLE) +{ + Init(); + SetMeasuredGeometry (theCone); +} + +//======================================================================= +//function : Constructor +//purpose : +//======================================================================= +AIS_AngleDimension_::AIS_AngleDimension_ (const TopoDS_Face& theFirstFace, + const TopoDS_Face& theSecondFace) +: AIS_Dimension (AIS_KOD_PLANEANGLE) +{ + Init(); + SetMeasuredGeometry (theFirstFace, theSecondFace); +} + +//======================================================================= +//function : Constructor +//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); +} + +//======================================================================= +//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) + { + ComputePlane(); + } + + SetToUpdate(); +} + +//======================================================================= +//function : SetMeasuredGeometry +//purpose : +//======================================================================= +void AIS_AngleDimension_::SetMeasuredGeometry (const gp_Pnt& theFirstPoint, + const gp_Pnt& theSecondPoint, + const gp_Pnt& theThirdPoint) +{ + 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); + + if (myIsGeometryValid && !myIsPlaneCustom) + { + ComputePlane(); + } + + SetToUpdate(); +} + +//======================================================================= +//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); + + if (myIsGeometryValid && !myIsPlaneCustom) + { + ComputePlane(); + } + + SetToUpdate(); +} + +//======================================================================= +//function : SetMeasuredGeometry +//purpose : +//======================================================================= +void AIS_AngleDimension_::SetMeasuredGeometry (const TopoDS_Face& theCone) +{ + myFirstShape = theCone; + mySecondShape = TopoDS_Shape(); + myThirdShape = TopoDS_Shape(); + myGeometryType = GeometryType_Face; + myIsGeometryValid = InitConeAngle(); + + if (myIsGeometryValid && !myIsPlaneCustom) + { + ComputePlane(); + } + + SetToUpdate(); +} + +//======================================================================= +//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() +{ + SetAngleReversed (Standard_False); + SetArrowVisible (Standard_True, Standard_True); + 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(); + if (myUseReverse) { + 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 : 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) +{ + // construct plane where the circle and the arc are located + gce_MakePln aConstructPlane (theFirstAttach, theSecondAttach, theCenter); + if (!aConstructPlane.IsDone()) + { + return; + } + + gp_Pln aPlane = aConstructPlane.Value(); + if (myUseReverse) { + 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); + + gp_Ax1 anAxis = aPlane.Axis(); + gp_Dir aDir = anAxis.Direction(); + gp_Vec aRefVec(aDir); + Standard_Real anAngle = aCenterToFirstVec.AngleWithRef (aCenterToSecondVec, aRefVec); + if (anAngle < 0) + anAngle = 2.0 * M_PI + anAngle; + 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) +{ + // construct plane where the circle and the arc are located + gce_MakePln aConstructPlane (theFirstAttach, theSecondAttach, theCenter); + if (!aConstructPlane.IsDone()) + { + return; + } + + gp_Pln aPlane = aConstructPlane.Value(); + + 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 aSectorOnCircle = theTextWidth / aRadius; + + gp_Pnt aTextPntBeg = ElCLib::Value (aParamMid - aSectorOnCircle * 0.5, aCircle); + gp_Pnt aTextPntEnd = ElCLib::Value (aParamMid + aSectorOnCircle * 0.5, aCircle); + + // Drawing arcs + DrawArc (thePresentation, theFirstAttach, aTextPntBeg, theCenter, aRadius, theMode); + DrawArc (thePresentation, theSecondAttach, aTextPntEnd, 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; + } + + gp_Vec aFirstVec = gp_Vec (myCenterPoint, myFirstPoint).Normalized(); + gp_Vec aSecondVec = gp_Vec (myCenterPoint, mySecondPoint).Normalized(); + gp_Vec aDirectionN = aSecondVec.Crossed (aFirstVec).Normalized(); + gp_Vec aDirectionY = (aFirstVec + aSecondVec).Normalized(); + gp_Vec aDirectionX = aDirectionY.Crossed (aDirectionN).Normalized(); + + 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 = aVec2.AngleWithRef (aVec1, GetPlane().Axis().Direction()); + + 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) +{ + thePresentation->Clear(); + mySelectionGeom.Clear (theMode); + + if (!IsValid()) + { + return; + } + + // Parameters for presentation + Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect(); + + Prs3d_Root::CurrentGroup(thePresentation)->SetPrimitivesAspect (aDimensionAspect->LineAspect()->Aspect()); + + 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; + } + + // 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 aWPDir = gp_Vec (GetPlane().Axis().Direction()); + + gp_Dir aFirstExtensionDir = aWPDir ^ gp_Vec (myCenterPoint, aFirstAttach); + gp_Dir aSecondExtensionDir = aWPDir.Reversed() ^ gp_Vec (myCenterPoint, aSecondAttach); + + gp_Vec aFirstArrowVec = gp_Vec (aFirstExtensionDir) * anArrowLength; + gp_Vec aSecondArrowVec = gp_Vec (aSecondExtensionDir) * anArrowLength; + + 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); + + if (isArrowsExternal) + { + aFirstArrowVec.Reverse(); + aSecondArrowVec.Reverse(); + } + + 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 || !myFirstArrowVisible) ? aFirstAttach : aFirstArrowEnd, + (isArrowsExternal || !mySecondArrowVisible) ? aSecondAttach : aSecondArrowEnd, + myCenterPoint, + Abs (GetFlyout()), + theMode); + } + } + break; + + case LabelPosition_Left : + { + DrawExtension (thePresentation, + anExtensionSize, + (isArrowsExternal && myFirstArrowVisible) ? aFirstArrowEnd : aFirstAttach, + aFirstExtensionDir, + aLabelString, + aLabelWidth, + theMode, + aLabelPosition); + } + break; + + case LabelPosition_Right : + { + DrawExtension (thePresentation, + anExtensionSize, + (isArrowsExternal && mySecondArrowVisible) ? 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 || !myFirstArrowVisible) ? aFirstAttach : aFirstArrowEnd, + (isArrowsExternal || !mySecondArrowVisible) ? aSecondAttach : aSecondArrowEnd, + myCenterPoint, + Abs(GetFlyout ()), + theMode); + } + + // arrows and arrow extensions + if (theMode == ComputeMode_All || theMode == ComputeMode_Line) + { + Prs3d_Root::NewGroup (thePresentation); + + if (myFirstArrowVisible) + DrawArrow (thePresentation, aFirstArrowBegin, gp_Dir (aFirstArrowVec)); + if (mySecondArrowVisible) + DrawArrow (thePresentation, aSecondArrowBegin, gp_Dir (aSecondArrowVec)); + } + + if ((theMode == ComputeMode_All || theMode == ComputeMode_Line) && isArrowsExternal) + { + Prs3d_Root::NewGroup (thePresentation); + + if (aHPosition != LabelPosition_Left && myFirstArrowVisible) + { + DrawExtension (thePresentation, + aDimensionAspect->ArrowTailSize(), + aFirstArrowEnd, + aFirstExtensionDir, + THE_EMPTY_LABEL_STRING, + THE_EMPTY_LABEL_WIDTH, + theMode, + LabelPosition_None); + } + + if (aHPosition != LabelPosition_Right && mySecondArrowVisible) + { + 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 = Abs (aFirstLin.Angle (aSecondLin) - M_PI) <= Precision::Angular(); + + gp_Pnt aPoint = aFirstLine->Value (0.0); + gp_Dir aNormal = isParallelLines + ? gp_Vec (aSecondLin.Normal (aPoint).Direction()) ^ gp_Vec (aSecondLin.Direction()) + : gp_Vec (aFirstLin.Direction()) ^ gp_Vec (aSecondLin.Direction()); + + theComputedPlane = gp_Pln (aPoint, aNormal); + + // Compute geometry for this plane and edges + Standard_Boolean isInfinite1,isInfinite2; + gp_Pnt aFirstPoint1, aLastPoint1, aFirstPoint2, aLastPoint2; + gp_Lin2d aFirstLin2d, aSecondLin2d; + + if (!AIS::ComputeGeometry (aFirstEdge, aSecondEdge, + aFirstLine, aSecondLine, + aFirstPoint1, aLastPoint1, + aFirstPoint2, aLastPoint2, + isInfinite1, isInfinite2)) + { + return Standard_False; + } + + if (aFirstLin.Direction().IsParallel (aSecondLin.Direction(), Precision::Angular())) + { + myFirstPoint = aFirstLin.Location(); + mySecondPoint = ElCLib::Value (ElCLib::Parameter (aFirstLin, myFirstPoint), aSecondLin); + + if (mySecondPoint.Distance (myFirstPoint) <= Precision::Confusion()) + { + mySecondPoint.Translate (gp_Vec (aSecondLin.Direction()) * Abs (GetFlyout())); + } + + myCenterPoint.SetXYZ ((myFirstPoint.XYZ() + mySecondPoint.XYZ()) / 2.0); + } + 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.IsEqual(aFirstPoint1, Precision::Confusion()) + ? aFirstPoint1 + : aLastPoint1; + mySecondPoint = !myCenterPoint.IsEqual(aFirstPoint2, Precision::Confusion()) + ? 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 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 && 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 : InitTwoFacesAngle +//purpose : initialization of angle dimension between two faces +//======================================================================= +Standard_Boolean AIS_AngleDimension_::InitTwoFacesAngle (const gp_Pnt thePointOnFirstFace) +{ + 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); + + 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 +//purpose : initialization of the cone angle +//======================================================================= +Standard_Boolean AIS_AngleDimension_::InitConeAngle() +{ + if (myFirstShape.IsNull()) + { + return Standard_False; + } + + TopoDS_Face aConeShape = TopoDS::Face (myFirstShape); + gp_Pln aPln; + gp_Cone aCone; + gp_Circ aCircle; + // A surface from the Face + Handle(Geom_Surface) aSurf; + Handle(Geom_OffsetSurface) aOffsetSurf; + Handle(Geom_ConicalSurface) aConicalSurf; + Handle(Geom_SurfaceOfRevolution) aRevSurf; + Handle(Geom_Line) aLine; + BRepAdaptor_Surface aConeAdaptor (aConeShape); + TopoDS_Face aFace; + AIS_KindOfSurface aSurfType; + Standard_Real anOffset = 0.; + Handle(Standard_Type) aType; + + Standard_Real aMaxV = aConeAdaptor.FirstVParameter(); + Standard_Real aMinV = aConeAdaptor.LastVParameter(); + + AIS::GetPlaneFromFace (aConeShape, aPln, aSurf, aSurfType, anOffset); + + if (aSurfType == AIS_KOS_Revolution) + { + // Surface of revolution + aRevSurf = Handle(Geom_SurfaceOfRevolution)::DownCast(aSurf); + gp_Lin aLin (aRevSurf->Axis()); + Handle(Geom_Curve) aBasisCurve = aRevSurf->BasisCurve(); + //Must be a part of line (basis curve should be linear) + if (aBasisCurve ->DynamicType() != STANDARD_TYPE(Geom_Line)) + return Standard_False; + + gp_Pnt aFirst1 = aConeAdaptor.Value (0., aMinV); + gp_Pnt aLast1 = aConeAdaptor.Value (0., aMaxV); + gp_Vec aVec1 (aFirst1, aLast1); + + //Projection on + gp_Pnt aFirst2 = ElCLib::Value (ElCLib::Parameter (aLin, aFirst1), aLin); + // Projection on + gp_Pnt aLast2 = ElCLib::Value (ElCLib::Parameter (aLin, aLast1), aLin); + + gp_Vec aVec2 (aFirst2, aLast2); + + // Check if two parts of revolution are parallel (it's a cylinder) or normal (it's a circle). + if (aVec1.IsParallel (aVec2, Precision::Angular()) + || aVec1.IsNormal (aVec2,Precision::Angular())) + return Standard_False; + + gce_MakeCone aMkCone (aRevSurf->Axis(), aFirst1, aLast1); + aCone = aMkCone.Value(); + myCenterPoint = aCone.Apex(); + } + else + { + aType = aSurf->DynamicType(); + if (aType == STANDARD_TYPE(Geom_OffsetSurface) || anOffset > 0.01) + { + // Offset surface + aOffsetSurf = new Geom_OffsetSurface (aSurf, anOffset); + aSurf = aOffsetSurf->Surface(); + BRepBuilderAPI_MakeFace aMkFace(aSurf, Precision::Confusion()); + aMkFace.Build(); + if (!aMkFace.IsDone()) + return Standard_False; + aConeAdaptor.Initialize (aMkFace.Face()); + } + aCone = aConeAdaptor.Cone(); + aConicalSurf = Handle(Geom_ConicalSurface)::DownCast (aSurf); + myCenterPoint = aConicalSurf->Apex(); + } + + // A circle where the angle is drawn + Handle(Geom_Curve) aCurve; + Standard_Real aMidV = ( aMinV + aMaxV ) / 2.5; + aCurve = aSurf->VIso (aMidV); + aCircle = Handle(Geom_Circle)::DownCast (aCurve)->Circ(); + + aCurve = aSurf->VIso(aMaxV); + gp_Circ aCircVmax = Handle(Geom_Circle)::DownCast(aCurve)->Circ(); + aCurve = aSurf->VIso(aMinV); + gp_Circ aCircVmin = Handle(Geom_Circle)::DownCast(aCurve)->Circ(); + + if (aCircVmax.Radius() < aCircVmin.Radius()) + { + gp_Circ aTmpCirc = aCircVmax; + aCircVmax = aCircVmin; + aCircVmin = aTmpCirc; + } + + myFirstPoint = ElCLib::Value (0, aCircle); + mySecondPoint = ElCLib::Value (M_PI, aCircle); + return Standard_True; +} + +//======================================================================= +//function : IsValidPoints +//purpose : +//======================================================================= +Standard_Boolean AIS_AngleDimension_::IsValidPoints (const gp_Pnt& theFirstPoint, + const gp_Pnt& theCenterPoint, + const gp_Pnt& theSecondPoint) const +{ + return theFirstPoint.Distance (theCenterPoint) > Precision::Confusion() + && theSecondPoint.Distance (theCenterPoint) > Precision::Confusion() + && 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 : SetAngleReversed +//purpose : +//======================================================================= +void AIS_AngleDimension_::SetAngleReversed(const Standard_Boolean& theUseReverse) +{ + myUseReverse = theUseReverse; +} + +//======================================================================= +//function : SetArrowVisible +//purpose : +//======================================================================= +void AIS_AngleDimension_::SetArrowVisible(const Standard_Boolean& theFirstArrowVisible, + const Standard_Boolean& theSecondArrowVisible) +{ + myFirstArrowVisible = theFirstArrowVisible; + mySecondArrowVisible = theSecondArrowVisible; +} + +//======================================================================= +//function : AdjustParameters +//purpose : +//======================================================================= +void AIS_AngleDimension_::AdjustParameters (const gp_Pnt& theTextPos, + Standard_Real& theExtensionSize, + Prs3d_DimensionTextHorizontalPosition& theAlignment, + Standard_Real& theFlyout) const +{ + 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()) + { + 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) + { + theFlyout = aRadius; + return; + } + + aParamBeg += M_PI; + aParamEnd += M_PI; + ElCLib::AdjustPeriodic (0.0, M_PI * 2, Precision::PConfusion(), aParamBeg, aParamEnd); + + if (aTextPar > aParamBeg && aTextPar < aParamEnd) + { + theFlyout = -aRadius; + 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); + + theFlyout = 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); + + theFlyout = 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; + } +} diff --git a/src/SketcherPrs/AIS_AngleDimension_.hxx b/src/SketcherPrs/AIS_AngleDimension_.hxx new file mode 100755 index 000000000..0a800f018 --- /dev/null +++ b/src/SketcherPrs/AIS_AngleDimension_.hxx @@ -0,0 +1,365 @@ +// Copyright (c) 1995-1999 Matra Datavision +// Copyright (c) 1999-2013 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// 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. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _AIS_AngleDimension_HeaderFile +#define _AIS_AngleDimension_HeaderFile + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +DEFINE_STANDARD_HANDLE (AIS_AngleDimension_, AIS_Dimension) + +//! Angle dimension. Can be constructed: +//! - on two intersected edges. +//! - on three points or vertices. +//! - on conical face. +//! - between two intersected faces. +//! +//! In case of three points or two intersected edges the dimension plane +//! (on which dimension presentation is built) can be computed uniquely +//! as through three defined points can be built only one plane. +//! Therefore, if user-defined plane differs from this one, the dimension can't be built. +//! +//! In cases of two planes automatic plane by default is built on point of the +//! origin of parametric space of the first face (the basis surface) so, that +//! the working plane and two faces intersection forms minimal angle between the faces. +//! User can define the other point which the dimension plane should pass through +//! using the appropriate constructor. This point can lay on the one of the faces or not. +//! Also user can define his own plane but it should pass through the three points +//! computed on the geometry initialization step (when the constructor or SetMeasuredGeometry() method +//! is called). +//! +//! In case of the conical face the center point of the angle is the apex of the conical surface. +//! The attachment points are points of the first and the last parameter of the basis circle of the cone. +//! +class AIS_AngleDimension_ : public AIS_Dimension +{ +public: + + //! Constructs minimum angle dimension between two linear edges (where possible). + //! These two edges should be intersected by each other. Otherwise the geometry is not valid. + //! @param theFirstEdge [in] the first edge. + //! @param theSecondEdge [in] the second edge. + //! the maximum distanced point of edges from the presentation center + Standard_EXPORT AIS_AngleDimension_ (const TopoDS_Edge& theFirstEdge, + const TopoDS_Edge& theSecondEdge); + + //! Constructs the angle display object defined by three points. + //! @param theFirstPoint [in] the first point (point on first angle flyout). + //! @param theSecondPoint [in] the center point of angle dimension. + //! @param theThirdPoint [in] the second point (point on second angle flyout). + Standard_EXPORT AIS_AngleDimension_ (const gp_Pnt& theFirstPoint, + const gp_Pnt& theSecondPoint, + const gp_Pnt& theThirdPoint); + + //! Constructs the angle display object defined by three vertices. + //! @param theFirstVertex [in] the first vertex (vertex for first angle flyout). + //! @param theSecondVertex [in] the center vertex of angle dimension. + //! @param theThirdPoint [in] the second vertex (vertex for second angle flyout). + Standard_EXPORT AIS_AngleDimension_ (const TopoDS_Vertex& theFirstVertex, + const TopoDS_Vertex& theSecondVertex, + const TopoDS_Vertex& theThirdVertex); + + //! Constructs angle dimension for the cone face. + //! @param theCone [in] the conical face. + Standard_EXPORT AIS_AngleDimension_ (const TopoDS_Face& theCone); + + //! Constructs angle dimension between two planar faces. + //! @param theFirstFace [in] the first face. + //! @param theSecondFace [in] the second face. + Standard_EXPORT AIS_AngleDimension_ (const TopoDS_Face& theFirstFace, + const TopoDS_Face& theSecondFace); + + //! Constructs angle dimension between two planar faces. + //! @param theFirstFace [in] the first face. + //! @param theSecondFace [in] the second face. + //! @param thePoint [in] the point which the dimension plane should pass through. + //! This point can lay on the one of the faces or not. + Standard_EXPORT AIS_AngleDimension_ (const TopoDS_Face& theFirstFace, + const TopoDS_Face& theSecondFace, + const gp_Pnt& thePoint); + +public: + + //! @return first point forming the angle. + const gp_Pnt& FirstPoint() const + { + return myFirstPoint; + } + + //! @return second point forming the angle. + const gp_Pnt& SecondPoint() const + { + return mySecondPoint; + } + + //! @return center point forming the angle. + const gp_Pnt& CenterPoint() const + { + return myCenterPoint; + } + + //! @return first argument shape. + const TopoDS_Shape& FirstShape() const + { + return myFirstShape; + } + + //! @return second argument shape. + const TopoDS_Shape& SecondShape() const + { + return mySecondShape; + } + + //! @return third argument shape. + const TopoDS_Shape& ThirdShape() const + { + return myThirdShape; + } + +public: + + //! Measures minimum angle dimension between two linear edges. + //! These two edges should be intersected by each other. Otherwise the geometry is not valid. + //! @param theFirstEdge [in] the first edge. + //! @param theSecondEdge [in] the second edge. + //! the maximum distanced point of edges from the presentation center + Standard_EXPORT void SetMeasuredGeometry (const TopoDS_Edge& theFirstEdge, + const TopoDS_Edge& theSecondEdge); + + //! Measures angle defined by three points. + //! @param theFirstPoint [in] the first point (point on first angle flyout). + //! @param theSecondPoint [in] the center point of angle dimension. + //! @param theThirdPoint [in] the second point (point on second angle flyout). + Standard_EXPORT void SetMeasuredGeometry (const gp_Pnt& theFirstPoint, + const gp_Pnt& theSecondPoint, + const gp_Pnt& theThridPoint); + + //! Measures angle defined by three vertices. + //! @param theFirstVertex [in] the first vertex (vertex for first angle flyout). + //! @param theSecondVertex [in] the center vertex of angle dimension. + //! @param theThirdPoint [in] the second vertex (vertex for second angle flyout). + Standard_EXPORT void SetMeasuredGeometry (const TopoDS_Vertex& theFirstVertex, + const TopoDS_Vertex& theSecondVertex, + const TopoDS_Vertex& theThirdVertex); + + //! Measures angle of conical face. + //! @param theCone [in] the shape to measure. + Standard_EXPORT void SetMeasuredGeometry (const TopoDS_Face& theCone); + + //! Measures angle between two planar faces. + //! @param theFirstFace [in] the first face. + //! @param theSecondFace [in] the second face.. + Standard_EXPORT void SetMeasuredGeometry (const TopoDS_Face& theFirstFace, + const TopoDS_Face& theSecondFace); + + //! Measures angle between two planar faces. + //! @param theFirstFace [in] the first face. + //! @param theSecondFace [in] the second face. + //! @param thePoint [in] the point which the dimension plane should pass through. + //! This point can lay on the one of the faces or not. + Standard_EXPORT void SetMeasuredGeometry (const TopoDS_Face& theFirstFace, + const TopoDS_Face& theSecondFace, + const gp_Pnt& thePoint); + + //! @return the display units string. + Standard_EXPORT virtual const TCollection_AsciiString& GetDisplayUnits() const; + + //! @return the model units string. + Standard_EXPORT virtual const TCollection_AsciiString& GetModelUnits() const; + + Standard_EXPORT virtual void SetDisplayUnits (const TCollection_AsciiString& theUnits); + + Standard_EXPORT virtual void SetModelUnits (const TCollection_AsciiString& theUnits); + + //! Principle of horizontal text alignment settings: + //! - divide circle into two halves according to attachment points + //! - if aTextPos is between attach points -> Center + positive flyout + //! - if aTextPos is not between attach points but in this half -> Left or Right + positive flyout + //! - if aTextPos is between reflections of attach points -> Center + negative flyout + //! - if aTextPos is not between reflections of attach points -> Left or Right + negative flyout + Standard_EXPORT virtual void SetTextPosition (const gp_Pnt& theTextPos); + + Standard_EXPORT virtual const gp_Pnt GetTextPosition () const; + + //! Sets state if the angle arc should be built reversing to the presentation plane. + //! Default state is not reversed + //! @param theUseReverse [in] the boolean state. + void SetAngleReversed(const Standard_Boolean& theUseReverse); + + //! Sets visible state of angle arrows. Default value is true for both + //! @param theFirstArrowVisible [in] the visibility of the first arrow. + //! @param theSecondArrowVisible [in] the visibility of the second arrow. + void SetArrowVisible(const Standard_Boolean& theFirstArrowVisible, + const Standard_Boolean& theSecondArrowVisible); + +public: + + DEFINE_STANDARD_RTTI (AIS_AngleDimension_) + +protected: + + //! Initialization of fields that is common to all constructors. + Standard_EXPORT void Init(); + + //! @param theFirstAttach [in] the first attachment point. + //! @param theSecondAttach [in] the second attachment point. + //! @param theCenter [in] the center point (center point of the angle). + //! @return the center of the dimension arc (the main dimension line in case of angle). + Standard_EXPORT gp_Pnt GetCenterOnArc (const gp_Pnt& theFirstAttach, + const gp_Pnt& theSecondAttach, + const gp_Pnt& theCenter) const; + + //! Draws main dimension line (arc). + //! @param thePresentation [in] the dimension presentation. + //! @param theFirstAttach [in] the first attachment point. + //! @param theSecondAttach [in] the second attachment point. + //! @param theCenter [in] the center point (center point of the angle). + //! @param theRadius [in] the radius of the dimension arc. + //! @param theMode [in] the display mode. + Standard_EXPORT void 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); + + //! Draws main dimension line (arc) with text. + //! @param thePresentation [in] the dimension presentation. + //! @param theFirstAttach [in] the first attachment point. + //! @param theSecondAttach [in] the second attachment point. + //! @param theCenter [in] the center point (center point of the angle). + //! @param theText [in] the text label string. + //! @param theTextWidth [in] the text label width. + //! @param theMode [in] the display mode. + //! @param theLabelPosition [in] the text label vertical and horizontal positioning option + //! respectively to the main dimension line. + Standard_EXPORT void 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); + + //! Fits text alignment relatively to the dimension line; + //! it computes the value of label position and arrow orientation + //! according set in the aspect and dimension properties. + //! @param theHorizontalTextPos [in] the horizontal alignment for text position. + //! @param theLabelPosition [out] the label position, contains bits that defines + //! vertical and horizontal alignment. (for internal usage in count text position). + //! @param theIsArrowExternal [out] is the arrows external, + //! if arrow orientation in the dimension aspect is Prs3d_DAO_Fit, it fits arrow + //! orientation automatically. + Standard_EXPORT void FitTextAlignment (const Prs3d_DimensionTextHorizontalPosition& theHorizontalTextPos, + Standard_Integer& theLabelPosition, + Standard_Boolean& theIsArrowsExternal) const; + + //! Adjusts aspect parameters according the text position: + //! extension size, vertical text alignment and flyout. + //! @param theTextPos [in] the user defined 3d point of text position. + //! @param theExtensionSize [out] the adjusted extension size. + //! @param theAlignment [out] the horizontal label alignment. + //! @param theFlyout [out] the adjusted value of flyout. + Standard_EXPORT void AdjustParameters (const gp_Pnt& theTextPos, + Standard_Real& theExtensionSize, + Prs3d_DimensionTextHorizontalPosition& theAlignment, + Standard_Real& theFlyout) const; + +protected: + + Standard_EXPORT virtual void ComputePlane(); + + //! Checks if the plane includes three angle points to build dimension. + Standard_EXPORT virtual Standard_Boolean CheckPlane (const gp_Pln& thePlane) const; + + Standard_EXPORT virtual Standard_Real ComputeValue() const; + + Standard_EXPORT virtual void Compute (const Handle(PrsMgr_PresentationManager3d)& thePM, + const Handle(Prs3d_Presentation)& thePresentation, + const Standard_Integer theMode = 0); + + Standard_EXPORT virtual void ComputeFlyoutSelection (const Handle(SelectMgr_Selection)& theSelection, + const Handle(SelectMgr_EntityOwner)& theOwner); + +protected: + + //! Init angular dimension to measure angle between two linear edges. + //! the maximum distanced point of edges from the presentation center + //! @return TRUE if the angular dimension can be constructured + //! for the passed edges. + Standard_EXPORT Standard_Boolean InitTwoEdgesAngle (gp_Pln& theComputedPlane); + + //! Init angular dimension to measure angle between two planar faces. + //! there is no user-defined poisitoning. So attach points are set + //! according to faces geometry (in origin of the first face basis surface). + //! @return TRUE if the angular dimension can be constructed + //! for the passed faces. + Standard_EXPORT Standard_Boolean InitTwoFacesAngle(); + + //! Init angular dimension to measure angle between two planar faces. + //! @param thePointOnFirstFace [in] the point which the dimension plane should pass through. + //! This point can lay on the one of the faces or not. + //! It will be projected on the first face and this point will be set + //! as the first point attach point. + //! It defines some kind of dimension positioning over the faces. + //! @return TRUE if the angular dimension can be constructed + //! for the passed faces. + Standard_EXPORT Standard_Boolean InitTwoFacesAngle (const gp_Pnt thePointOnFirstFace); + + //! Init angular dimension to measure cone face. + //! @return TRUE if the angular dimension can be constructed + //! for the passed cone. + Standard_EXPORT Standard_Boolean InitConeAngle(); + + //! Check that the points forming angle are valid. + //! @return TRUE if the points met the following requirements: + //! The (P1, Center), (P2, Center) can be built. + //! The angle between the vectors > Precision::Angular(). + Standard_EXPORT Standard_Boolean IsValidPoints (const gp_Pnt& theFirstPoint, + const gp_Pnt& theCenterPoint, + const gp_Pnt& theSecondPoint) const; + +private: + Standard_Boolean myUseReverse; + + Standard_Boolean myFirstArrowVisible; + Standard_Boolean mySecondArrowVisible; + + gp_Pnt myFirstPoint; + gp_Pnt mySecondPoint; + gp_Pnt myCenterPoint; + TopoDS_Shape myFirstShape; + TopoDS_Shape mySecondShape; + TopoDS_Shape myThirdShape; +}; + +#endif // _AIS_AngleDimension_HeaderFile diff --git a/src/SketcherPrs/CMakeLists.txt b/src/SketcherPrs/CMakeLists.txt index e060ad325..3d1cadba6 100644 --- a/src/SketcherPrs/CMakeLists.txt +++ b/src/SketcherPrs/CMakeLists.txt @@ -27,7 +27,7 @@ SET(PROJECT_HEADERS SketcherPrs_Mirror.h SketcherPrs_Transformation.h SketcherPrs_Angle.h - AIS_AngleDimension.hxx + AIS_AngleDimension_.hxx ) SET(PROJECT_SOURCES @@ -51,7 +51,7 @@ SET(PROJECT_SOURCES SketcherPrs_Mirror.cpp SketcherPrs_Transformation.cpp SketcherPrs_Angle.cpp - AIS_AngleDimension.cxx + AIS_AngleDimension_.cxx ) SET(PROJECT_LIBRARIES diff --git a/src/SketcherPrs/SketcherPrs_Angle.cpp b/src/SketcherPrs/SketcherPrs_Angle.cpp index 1fb78cb75..c2ad79c46 100644 --- a/src/SketcherPrs/SketcherPrs_Angle.cpp +++ b/src/SketcherPrs/SketcherPrs_Angle.cpp @@ -29,12 +29,12 @@ #define PI 3.1415926535897932 -IMPLEMENT_STANDARD_HANDLE(SketcherPrs_Angle, AIS_AngleDimension); -IMPLEMENT_STANDARD_RTTIEXT(SketcherPrs_Angle, AIS_AngleDimension); +IMPLEMENT_STANDARD_HANDLE(SketcherPrs_Angle, AIS_AngleDimension_); +IMPLEMENT_STANDARD_RTTIEXT(SketcherPrs_Angle, AIS_AngleDimension_); SketcherPrs_Angle::SketcherPrs_Angle(ModelAPI_Feature* theConstraint, const std::shared_ptr& thePlane) -: AIS_AngleDimension(gp_Pnt(0,0,0), gp_Pnt(1,0,0), gp_Pnt(0,1,0)), myConstraint(theConstraint), +: AIS_AngleDimension_(gp_Pnt(0,0,0), gp_Pnt(1,0,0), gp_Pnt(0,1,0)), myConstraint(theConstraint), mySketcherPlane(thePlane), myFirstPoint(gp_Pnt(0,0,0)), myCenterPoint(gp_Pnt(1,0,0)), mySecondPoint(gp_Pnt(0,1,0)), myAngle(90), myValue("90"), myFlyOutPoint(0, 0.5, 0) @@ -202,7 +202,7 @@ void SketcherPrs_Angle::Compute(const Handle(PrsMgr_PresentationManager3d)& theP // Update text visualization: parameter value or parameter text myStyleListener->updateDimensions(this, myHasParameters, myValue); - AIS_AngleDimension::Compute(thePresentationManager, thePresentation, theMode); + AIS_AngleDimension_::Compute(thePresentationManager, thePresentation, theMode); if (!aReadyToDisplay) SketcherPrs_Tools::sendEmptyPresentationError(myConstraint, @@ -232,7 +232,7 @@ void SketcherPrs_Angle::ComputeSelection(const Handle(SelectMgr_Selection)& aSel return; } } - AIS_AngleDimension::ComputeSelection(aSelection, aMode); + AIS_AngleDimension_::ComputeSelection(aSelection, aMode); } bool SketcherPrs_Angle::isAnglePlaneReversedToSketchPlane() diff --git a/src/SketcherPrs/SketcherPrs_Angle.h b/src/SketcherPrs/SketcherPrs_Angle.h index 41265a529..09167273c 100644 --- a/src/SketcherPrs/SketcherPrs_Angle.h +++ b/src/SketcherPrs/SketcherPrs_Angle.h @@ -11,18 +11,18 @@ #include #include -#include +#include #include class SketcherPrs_DimensionStyleListener; -DEFINE_STANDARD_HANDLE(SketcherPrs_Angle, AIS_AngleDimension) +DEFINE_STANDARD_HANDLE(SketcherPrs_Angle, AIS_AngleDimension_) /** * \ingroup GUI * A class for representation of angle constraint */ -class SketcherPrs_Angle : public AIS_AngleDimension +class SketcherPrs_Angle : public AIS_AngleDimension_ { public: /// Constructor