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