-// Copyright (c) 1999-2013 OPEN CASCADE SAS
+// Created on: 2013-11-11
+// Created by: Anastasia BORISOVA
+// Copyright (c) 2013-2014 OPEN CASCADE SAS
//
-// The content of this file is subject to the Open CASCADE Technology Public
-// License Version 6.5 (the "License"). You may not use the content of this file
-// except in compliance with the License. Please obtain a copy of the License
-// at http://www.opencascade.org and read it completely before using this file.
+// This file is part of Open CASCADE Technology software library.
//
-// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
-// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
//
-// The Original Code and all software distributed under the License is
-// distributed on an "AS IS" basis, without warranty of any kind, and the
-// Initial Developer hereby disclaims all such warranties, including without
-// limitation, any warranties of merchantability, fitness for a particular
-// purpose or non-infringement. Please see the License for the specific terms
-// and conditions governing the rights and limitations under the License.
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
-#include <AIS.hxx>
#include <AIS_Dimension.hxx>
-#include <AIS_DimensionDisplayMode.hxx>
+
+#include <AIS.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 <Bnd_Box.hxx>
#include <ElCLib.hxx>
#include <Font_BRepFont.hxx>
#include <GC_MakeCircle.hxx>
+#include <Geom_Line.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 <gce_MakePln.hxx>
#include <Graphic3d_ArrayOfSegments.hxx>
#include <Graphic3d_ArrayOfTriangles.hxx>
#include <Graphic3d_AspectLine3d.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_SensitiveTriangle.hxx>
+#include <Select3D_SensitiveTriangulation.hxx>
+#include <Poly_Array1OfTriangle.hxx>
+#include <Poly_Triangulation.hxx>
#include <Standard_CString.hxx>
+#include <Standard_ProgramError.hxx>
#include <StdPrs_ShadedShape.hxx>
#include <StdPrs_WFShape.hxx>
#include <TCollection_AsciiString.hxx>
#include <TCollection_ExtendedString.hxx>
#include <TopExp_Explorer.hxx>
#include <TopoDS.hxx>
+#include <TopoDS_Edge.hxx>
#include <TopoDS_Vertex.hxx>
#include <Units.hxx>
#include <Units_UnitsDictionary.hxx>
IMPLEMENT_STANDARD_HANDLE(AIS_Dimension, AIS_InteractiveObject)
IMPLEMENT_STANDARD_RTTIEXT(AIS_Dimension, AIS_InteractiveObject)
-//=======================================================================
-//function : Constructor
-//purpose :
-//=======================================================================
-
-AIS_Dimension::AIS_Dimension (const Standard_Real theExtensionSize /*= 1.0*/)
-: AIS_InteractiveObject(),
- myDefaultPlane (gp_Pln (gp::XOY())),
- myIsWorkingPlaneCustom (Standard_False),
- myValue (0.0),
- myIsValueCustom (Standard_False),
- myUnitsQuantity (TCollection_AsciiString("LENGTH")),
- myToDisplayUnits (Standard_False),
- mySpecialSymbol (' '),
- myDisplaySpecialSymbol (AIS_DSS_No),
- myIsTextReversed (Standard_False),
- myTextOffset (DimensionAspect()->ArrowAspect()->Length()),
- myIsInitialized (Standard_False),
- myFlyout (0.0),
- myKindOfDimension (AIS_KOD_NONE),
- myExtensionSize (theExtensionSize)
+namespace
{
- ResetWorkingPlane();
- // Units default settings
- UnitsAPI::SetLocalSystem (UnitsAPI_SI);
- myModelUnits = Units::DictionaryOfUnits()->ActiveUnit (myUnitsQuantity.ToCString());
- myDisplayUnits = Units::DictionaryOfUnits()->ActiveUnit (myUnitsQuantity.ToCString());
-}
+ // default text strings
+ static const TCollection_ExtendedString THE_EMPTY_LABEL;
+ static const TCollection_AsciiString THE_UNDEFINED_UNITS;
+
+ // 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;
+};
//=======================================================================
//function : Constructor
//purpose :
//=======================================================================
-
-AIS_Dimension::AIS_Dimension (const Handle(Prs3d_DimensionAspect)& theAspect,
- const Standard_Real theExtensionSize /*= 1.0*/)
+AIS_Dimension::AIS_Dimension (const AIS_KindOfDimension theType)
: AIS_InteractiveObject(),
- myDefaultPlane (gp_Pln (gp::XOY())),
- myIsWorkingPlaneCustom (Standard_False),
- myValue (0.0),
+ myCustomValue (0.0),
myIsValueCustom (Standard_False),
- myUnitsQuantity (TCollection_AsciiString("LENGTH")),
- myToDisplayUnits (Standard_False),
mySpecialSymbol (' '),
myDisplaySpecialSymbol (AIS_DSS_No),
- myIsTextReversed (Standard_False),
- myTextOffset (DimensionAspect()->ArrowAspect()->Length()),
- myIsInitialized (Standard_False),
+ myGeometryType (GeometryType_UndefShapes),
+ myIsPlaneCustom (Standard_False),
myFlyout (0.0),
- myKindOfDimension (AIS_KOD_NONE),
- myExtensionSize (theExtensionSize)
+ myIsGeometryValid (Standard_False),
+ myKindOfDimension (theType)
{
- ResetWorkingPlane();
- // Units default settings
- UnitsAPI::SetLocalSystem (UnitsAPI_SI);
- myModelUnits = Units::DictionaryOfUnits()->ActiveUnit (myUnitsQuantity.ToCString());
- myDisplayUnits = Units::DictionaryOfUnits()->ActiveUnit (myUnitsQuantity.ToCString());
- SetDimensionAspect (theAspect);
}
//=======================================================================
-//function : AcceptDisplayMode
-//purpose : Checks if display mode <theMode> is allowed to display object.
+//function : SetCustomValue
+//purpose :
//=======================================================================
-
-Standard_Boolean AIS_Dimension::AcceptDisplayMode (const Standard_Integer theMode) const
+void AIS_Dimension::SetCustomValue (const Standard_Real theValue)
{
- return theMode == 0 ? Standard_True : Standard_False;
-}
+ if (myIsValueCustom && myCustomValue == theValue)
+ {
+ return;
+ }
-//=======================================================================
-//function : computeValue
-//purpose : Computes dimension value in display units.
-//=======================================================================
+ myIsValueCustom = Standard_True;
-void AIS_Dimension::computeValue()
-{
- UnitsAPI::SetCurrentUnit (myUnitsQuantity.ToCString(), myModelUnits.ToCString());
- myValue = UnitsAPI::CurrentFromLS (myValue, myUnitsQuantity.ToCString());
- myValue = valueToDisplayUnits();
+ myCustomValue = theValue;
+
+ SetToUpdate();
}
//=======================================================================
-//function : countDefaultPlane
+//function : GetPlane
//purpose :
//=======================================================================
-
-void AIS_Dimension::countDefaultPlane()
+const gp_Pln& AIS_Dimension::GetPlane() const
{
+ return myPlane;
}
//=======================================================================
-//function : GetWorkingPlane
+//function : GetGeometryType
//purpose :
//=======================================================================
-
-const gp_Pln& AIS_Dimension::GetWorkingPlane() const
+const Standard_Integer AIS_Dimension::GetGeometryType () const
{
- return myWorkingPlane;
+ return myGeometryType;
}
//=======================================================================
-//function : SetWorkingPlane
+//function : SetUserPlane
//purpose :
//=======================================================================
-
-void AIS_Dimension::SetWorkingPlane (const gp_Pln& thePlane)
+void AIS_Dimension::SetCustomPlane (const gp_Pln& thePlane)
{
- myWorkingPlane = thePlane;
- myIsWorkingPlaneCustom = Standard_True;
-}
+ myPlane = thePlane;
+ myIsPlaneCustom = Standard_True;
-//=======================================================================
-//function : ResetWorkingPlane
-//purpose : Set default value of working plane
-//=======================================================================
+ // Disable fixed (custom) text position
+ UnsetFixedTextPosition();
-void AIS_Dimension::ResetWorkingPlane()
-{
- myWorkingPlane = myDefaultPlane;
- myIsWorkingPlaneCustom = Standard_False;
+ // Check validity if geometry has been set already.
+ if (IsValid())
+ {
+ SetToUpdate();
+ }
}
//=======================================================================
-//function : resetWorkingPlane
-//purpose : Set default value of working plane
-// Only for internal use.
+//function : SetDimensionAspect
+//purpose :
//=======================================================================
-
-void AIS_Dimension::resetWorkingPlane (const gp_Pln& theNewDefaultPlane)
+void AIS_Dimension::SetDimensionAspect (const Handle(Prs3d_DimensionAspect)& theDimensionAspect)
{
- myDefaultPlane = theNewDefaultPlane;
- ResetWorkingPlane();
+ myDrawer->SetDimensionAspect (theDimensionAspect);
+
+ SetToUpdate();
}
//=======================================================================
-//function : valueInDisplayUnits
+//function : SetDisplaySpecialSymbol
//purpose :
//=======================================================================
-
-Standard_Real AIS_Dimension::valueToDisplayUnits()
+void AIS_Dimension::SetDisplaySpecialSymbol (const AIS_DisplaySpecialSymbol theDisplaySpecSymbol)
{
- return UnitsAPI::AnyToAny (myValue,
- myModelUnits.ToCString(),
- myDisplayUnits.ToCString());
-}
+ if (myDisplaySpecialSymbol == theDisplaySpecSymbol)
+ {
+ return;
+ }
-//=======================================================================
-//function : KindOfDimension
-//purpose :
-//=======================================================================
+ myDisplaySpecialSymbol = theDisplaySpecSymbol;
-AIS_KindOfDimension AIS_Dimension::KindOfDimension() const
-{
- return myKindOfDimension;
+ SetToUpdate();
}
//=======================================================================
-//function : SetKindOfDimension
-//purpose :
+//function : SetSpecialSymbol
+//purpose :
//=======================================================================
-
-void AIS_Dimension::SetKindOfDimension (const AIS_KindOfDimension theKindOfDimension)
+void AIS_Dimension::SetSpecialSymbol (const Standard_ExtCharacter theSpecialSymbol)
{
- myKindOfDimension = theKindOfDimension;
-}
+ if (mySpecialSymbol == theSpecialSymbol)
+ {
+ return;
+ }
-//=======================================================================
-//function : SetExtensionSize
-//purpose :
-//=======================================================================
+ mySpecialSymbol = theSpecialSymbol;
-void AIS_Dimension::SetExtensionSize (const Standard_Real theExtensionSize)
-{
- myExtensionSize = theExtensionSize;
+ SetToUpdate();
}
-
+
//=======================================================================
-//function : GetExtensionSize
-//purpose :
+//function : SetSelToleranceForText2d
+//purpose :
//=======================================================================
-
-Standard_Real AIS_Dimension::GetExtensionSize() const
+void AIS_Dimension::SetSelToleranceForText2d (const Standard_Real theTol)
{
- return myExtensionSize;
+ if (mySelToleranceForText2d == theTol)
+ {
+ return;
+ }
+
+ mySelToleranceForText2d = theTol;
+
+ SetToUpdate();
}
//=======================================================================
-//function : GetValue
-//purpose :
+//function : SetFlyout
+//purpose :
//=======================================================================
+void AIS_Dimension::SetFlyout (const Standard_Real theFlyout)
+{
+ if (myFlyout == theFlyout)
+ {
+ return;
+ }
-Standard_Real AIS_Dimension::GetValue() const
- {
- return myValue;
- }
+ myFlyout = theFlyout;
+
+ // Disable fixed text position
+ UnsetFixedTextPosition();
+
+ SetToUpdate();
+}
//=======================================================================
-//function : SetCustomValue
-//purpose :
+//function : GetDisplayUnits
+//purpose :
//=======================================================================
-
-void AIS_Dimension::SetCustomValue (const Standard_Real theValue)
+const TCollection_AsciiString& AIS_Dimension::GetDisplayUnits() const
{
- myValue = theValue;
- myIsValueCustom = Standard_True;
+ return THE_UNDEFINED_UNITS;
}
//=======================================================================
-//function : SetFirstShape
-//purpose :
+//function : GetModelUnits
+//purpose :
//=======================================================================
-
-void AIS_Dimension::SetFirstShape (const TopoDS_Shape& theShape)
+const TCollection_AsciiString& AIS_Dimension::GetModelUnits() const
{
- myFirstShape = theShape;
- myIsInitialized = Standard_False;
- resetGeom();
+ return THE_UNDEFINED_UNITS;
}
//=======================================================================
-//function : SetSecondShape
-//purpose :
+//function : ValueToDisplayUnits
+//purpose :
//=======================================================================
-
-void AIS_Dimension::SetSecondShape (const TopoDS_Shape& theShape)
+Standard_Real AIS_Dimension::ValueToDisplayUnits() const
{
- mySecondShape = theShape;
- myIsInitialized = Standard_False;
- resetGeom();
+ return UnitsAPI::AnyToAny (GetValue(),
+ GetModelUnits().ToCString(),
+ GetDisplayUnits().ToCString());
}
//=======================================================================
-//function : getTextWidthAndString
+//function : GetValueString
//purpose :
//=======================================================================
-
-void AIS_Dimension::getTextWidthAndString (Quantity_Length& theWidth,
- TCollection_ExtendedString& theString) const
+TCollection_ExtendedString AIS_Dimension::GetValueString (Standard_Real& theWidth) const
{
- char aValueSimpleStr[25];
- sprintf (aValueSimpleStr, "%g", GetValue());
- theString = TCollection_ExtendedString (aValueSimpleStr);
+ // format value string using "sprintf"
+ TCollection_AsciiString aFormatStr = myDrawer->DimensionAspect()->ValueStringFormat();
- if (IsUnitsDisplayed())
- {
- theString += " ";
- theString += TCollection_ExtendedString (myDisplayUnits);
- }
+ char aFmtBuffer[256];
+ sprintf (aFmtBuffer, aFormatStr.ToCString(), ValueToDisplayUnits());
+ TCollection_ExtendedString aValueStr = TCollection_ExtendedString (aFmtBuffer);
- if (myDisplaySpecialSymbol == AIS_DSS_Before)
+ // add units to values string
+ if (myDrawer->DimensionAspect()->IsUnitsDisplayed())
{
- theString = TCollection_ExtendedString (mySpecialSymbol) + theString;
+ aValueStr += " ";
+ aValueStr += TCollection_ExtendedString (GetDisplayUnits());
}
- else if (myDisplaySpecialSymbol == AIS_DSS_After)
+
+ switch (myDisplaySpecialSymbol)
{
- theString += TCollection_ExtendedString (mySpecialSymbol);
+ case AIS_DSS_Before : aValueStr.Insert (1, mySpecialSymbol); break;
+ case AIS_DSS_After : aValueStr.Insert (aValueStr.Length() + 1, mySpecialSymbol); break;
+ case AIS_DSS_No : break;
}
- // Get font length
- // Get expansion ratio for getting a width of symbols
+ // Get text style parameters
Quantity_Color aColor;
- Standard_CString aFont;
+ Standard_CString aFontName;
Standard_Real aFactor;
Standard_Real aSpace;
- myDrawer->DimensionAspect()->TextAspect()->Aspect()->Values (aColor, aFont, aFactor, aSpace);
- theWidth = (myDrawer->DimensionAspect()->TextAspect()->Height() / aFactor) * theString.Length();
+ myDrawer->DimensionAspect()->TextAspect()->Aspect()->Values (aColor, aFontName, aFactor, aSpace);
+ Font_FontAspect aFontAspect = myDrawer->DimensionAspect()->TextAspect()->Aspect()->GetTextFontAspect();
+ Standard_Real aFontHeight = myDrawer->DimensionAspect()->TextAspect()->Height();
+
+ NCollection_Utf8String anUTFString = (Standard_Utf16Char* )aValueStr.ToExtString();
+
+ theWidth = 0.0;
+
+ 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
+ {
+ // 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);
+ }
+ }
+
+ return aValueStr;
}
//=======================================================================
-//function : drawArrow
+//function : DrawArrow
//purpose :
//=======================================================================
-
-void AIS_Dimension::drawArrow (const Handle(Prs3d_Presentation)& thePresentation,
+void AIS_Dimension::DrawArrow (const Handle(Prs3d_Presentation)& thePresentation,
const gp_Pnt& theLocation,
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.Reversed(),
- myDrawer->DimensionAspect()->ArrowAspect()->Angle(),
- anArrowLength);
+ theDirection,
+ anAngle,
+ aLength);
}
else
{
- gp_Vec anArrowDir (theDirection);
- Quantity_Length theCathetusLength = anArrowLength / Cos (M_PI / 9.0);
+ gp_Pnt aLeftPoint (gp::Origin());
+ gp_Pnt aRightPoint (gp::Origin());
+ const gp_Dir& aPlane = GetPlane().Axis().Direction();
+
+ PointsForArrow (theLocation, theDirection, aPlane, aLength, anAngle, aLeftPoint, aRightPoint);
+
Handle(Graphic3d_ArrayOfTriangles) anArrow = new Graphic3d_ArrayOfTriangles(3);
- gp_Pnt aLeftPoint (theLocation.Translated (anArrowDir.Rotated (myWorkingPlane.Axis(), M_PI / 9.0) * theCathetusLength));
- gp_Pnt aRightPoint (theLocation.Translated (anArrowDir.Rotated (myWorkingPlane.Axis(), M_PI * 17.0 / 9.0) * theCathetusLength));
anArrow->AddVertex (aLeftPoint);
anArrow->AddVertex (theLocation);
aShadeMat.SetReflectionModeOff (Graphic3d_TOR_AMBIENT);
aShadeMat.SetReflectionModeOff (Graphic3d_TOR_DIFFUSE);
aShadeMat.SetReflectionModeOff (Graphic3d_TOR_SPECULAR);
- myDrawer->ShadingAspect()->Aspect()->SetInteriorColor (aColor);
- myDrawer->ShadingAspect()->Aspect()->SetBackInteriorColor (aColor);
- myDrawer->ShadingAspect()->SetMaterial (aShadeMat);
- Prs3d_Root::CurrentGroup(thePresentation)->SetGroupPrimitivesAspect (myDrawer->ShadingAspect()->Aspect());
- Prs3d_Root::CurrentGroup(thePresentation)->AddPrimitiveArray (anArrow);
+
+ Handle(Prs3d_ShadingAspect) aShadingStyle = new Prs3d_ShadingAspect();
+ aShadingStyle->SetColor (aColor);
+ aShadingStyle->SetMaterial (aShadeMat);
+
+ 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
+//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)
+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 aTextWidth;
- // Creating new group for text
- Prs3d_Root::NewGroup (thePresentation);
-
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();
-
- // Creating TopoDS_Shape for text
- Font_BRepFont aFont (aFontName, aFontAspect, aHeight);
- NCollection_String aText = (Standard_Utf16Char* )theText.ToExtString();
- TopoDS_Shape aTextShape = aFont.RenderText (aText);
-
- // 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;
- gp_Dir aTextDir (theTextDir);
- Standard_Real aHorizontalOffset (0.0), aVerticalOffset (0.0);
- switch (myDrawer->DimensionAspect()->HorizontalTextAlignment())
+ Standard_Real aFontHeight = myDrawer->DimensionAspect()->TextAspect()->Height();
+
+ // creating TopoDS_Shape for text
+ Font_BRepFont aFont (aFontName, aFontAspect, aFontHeight);
+ NCollection_Utf8String anUTFString = (Standard_Utf16Char* )theText.ToExtString();
+ TopoDS_Shape aTextShape = aFont.RenderText (anUTFString);
+
+ // 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 = aFontHeight * THE_3D_TEXT_MARGIN;
+ Standard_Real aCenterHOffset = 0.0;
+ Standard_Real aCenterVOffset = 0.0;
+ switch (aHLabelPos)
{
- case Prs3d_HTA_Left:
- aTextDir.Reverse();
- aHorizontalOffset = -aTextWidth;
- break;
- case Prs3d_HTA_Center:
- aHorizontalOffset = -(aTextWidth / 2.0);
- break;
- case Prs3d_HTA_Right:
- aHorizontalOffset = 0.0;
- break;
+ case LabelPosition_HCenter : aCenterHOffset = 0.0; break;
+ case LabelPosition_Right : aCenterHOffset = aTextWidth / 2.0 + aMarginSize; break;
+ case LabelPosition_Left : aCenterHOffset = -aTextWidth / 2.0 - aMarginSize; break;
}
- switch (myDrawer->DimensionAspect()->VerticalTextAlignment())
+ switch (aVLabelPos)
{
- case Prs3d_VTA_Top:
- aVerticalOffset = 0.0;
- break;
- case Prs3d_VTA_Center:
- aVerticalOffset = -(aTextHeight / 2.0);
- break;
- case Prs3d_VTA_Bottom:
- aVerticalOffset = -aTextHeight;
- break;
+ case LabelPosition_VCenter : aCenterVOffset = 0.0; break;
+ case LabelPosition_Above : aCenterVOffset = aTextHeight / 2.0 + aMarginSize; break;
+ case LabelPosition_Below : aCenterVOffset = -aTextHeight / 2.0 - aMarginSize; break;
}
- gp_Trsf aTrsf;
- aTrsf.SetTranslation (gp_Pnt (), gp_Pnt (aHorizontalOffset, aVerticalOffset, 0.0));
- aTextShape.Move (aTrsf);
-
- // Transform text to myWorkingPlane coordinate system
- gp_Ax3 aPenAx3 (myGeom.myTextPosition, myWorkingPlane.Axis().Direction(), aTextDir);
- aTrsf.SetTransformation (aPenAx3, gp_Ax3 (gp::XOY()));
- aTextShape.Move (aTrsf);
-
- // Set display parameters for advanced selection
- BRepBndLib::AddClose (aTextShape, myGeom.myTextBndBox);
- // Drawing text
- gp_Pnt aTextCenter = myGeom.myTextPosition.Translated (gp_Vec (theTextDir) * aTextWidth * 0.5);
- Prs3d_Root::CurrentGroup (thePresentation)->SetFlippingOptions (Standard_True, gp_Ax2 (aTextCenter, myWorkingPlane.Axis().Direction(), aTextDir));
+
+ // compute shape offset transformation
+ 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 (theTextPos, GetPlane().Axis().Direction(), aTextDir);
+ gp_Trsf aTextPlaneTrsf;
+ aTextPlaneTrsf.SetTransformation (aTextCoordSystem, gp_Ax3 (gp::XOY()));
+ aTextShape.Move (aTextPlaneTrsf);
+
+ // set text flipping anchors
+ gp_Trsf aCenterOffsetTrsf;
+ gp_Pnt aCenterOffset (aCenterHOffset, aCenterVOffset, 0.0);
+ aCenterOffsetTrsf.SetTranslation (gp::Origin(), aCenterOffset);
+
+ gp_Pnt aCenterOfLabel (gp::Origin());
+ aCenterOfLabel.Transform (aCenterOffsetTrsf);
+ aCenterOfLabel.Transform (aTextPlaneTrsf);
+
+ gp_Ax2 aFlippingAxes (aCenterOfLabel, GetPlane().Axis().Direction(), aTextDir);
+ Prs3d_Root::CurrentGroup (thePresentation)->SetFlippingOptions (Standard_True, aFlippingAxes);
+
+ // 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);
}
- // Creating new group for lines
- Prs3d_Root::CurrentGroup (thePresentation)->SetFlippingOptions (Standard_False, aPenAx3.Ax2());
- Prs3d_Root::NewGroup (thePresentation);
- }
- else
- {
- myDrawer->DimensionAspect()->TextAspect()->Aspect()->SetDisplayType (Aspect_TODT_DIMENSION);
- Prs3d_Text::Draw (thePresentation,
- myDrawer->DimensionAspect()->TextAspect(),
- theText,
- myGeom.myTextPosition);
-
- // 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.
- }
+ Prs3d_Root::CurrentGroup (thePresentation)->SetFlippingOptions (Standard_False, gp_Ax2());
- return aTextWidth;
-}
-
- //=======================================================================
-//function : drawExtensionWithText
-//purpose :
-//=======================================================================
+ mySelectionGeom.TextPos = aCenterOfLabel;
+ mySelectionGeom.TextDir = aTextDir;
+ mySelectionGeom.TextWidth = aTextWidth + aMarginSize * 2.0;
+ mySelectionGeom.TextHeight = aTextHeight;
-void AIS_Dimension::drawExtensionWithText (const Handle(Prs3d_Presentation)& thePresentation,
- const gp_Pnt& theStartPoint,
- const gp_Lin& theDimensionLine,
- const TCollection_ExtendedString& theValueString,
- const AIS_DimensionDisplayMode theMode)
-{
- Handle(SelectMgr_EntityOwner) anEmptyOwner;
- Standard_Boolean isGapInCenter = (myDrawer->DimensionAspect()->VerticalTextAlignment() == Prs3d_VTA_Center
- && myDrawer->DimensionAspect()->IsText3d());
-
- Handle(Graphic3d_ArrayOfSegments) aPrimSegments = new Graphic3d_ArrayOfSegments (isGapInCenter ? 4 : 2);
-
- gp_Dir anAttachPointsVector = myWorkingPlane.Axis().Direction() ^ gce_MakeDir (myFirstPoint, mySecondPoint);
- Standard_Real aGap = 1.;
- Standard_Real aStartParam = ElCLib::Parameter (theDimensionLine, theStartPoint);
-
- // Text
- Standard_Real aTextParam = isGapInCenter ? aStartParam + myTextOffset + aGap : aStartParam + myTextOffset;
- myGeom.myTextPosition = ElCLib::Value (aTextParam, theDimensionLine);
- Standard_Real aTextWidth = drawText (thePresentation,
- myIsTextReversed ? theDimensionLine.Direction().Reversed()
- : theDimensionLine.Direction(),
- theValueString,
- theMode);
- gp_Pnt aFirstPoint, aLastPoint;
- aFirstPoint = theStartPoint;
- Standard_Real aParam = isGapInCenter ? aTextParam + aTextWidth + aGap : aTextParam + aTextWidth;
-
- // If text separates dimension line into two parts (4 points)
- if (isGapInCenter)
- {
- aLastPoint = ElCLib::Value (aStartParam + myTextOffset, theDimensionLine);
- aPrimSegments->AddVertex (aFirstPoint);
- aPrimSegments->AddVertex (aLastPoint);
- myGeom.mySensitiveSegments.Append (new Select3D_SensitiveSegment (anEmptyOwner, aFirstPoint, aLastPoint));
- aFirstPoint = ElCLib::Value (aParam, theDimensionLine);
+ return;
}
- // Draw additional line segment only after 3D text
- if (myDrawer->DimensionAspect()->IsText3d())
- {
- aParam += myTextOffset;
- }
+ // generate primitives for 2D text
+ myDrawer->DimensionAspect()->TextAspect()->Aspect()->SetDisplayType (Aspect_TODT_DIMENSION);
- aLastPoint = ElCLib::Value (aParam, theDimensionLine);
- aPrimSegments->AddVertex (aFirstPoint);
- aPrimSegments->AddVertex (aLastPoint);
- myGeom.mySensitiveSegments.Append (new Select3D_SensitiveSegment (anEmptyOwner, aFirstPoint, aLastPoint));
+ Prs3d_Text::Draw (thePresentation,
+ myDrawer->DimensionAspect()->TextAspect(),
+ theText,
+ theTextPos);
- // Extension line in the same group
- if (theMode != AIS_DDM_Text)
- {
- if (!myDrawer->DimensionAspect()->IsText3d() && theMode == AIS_DDM_All)
- {
- Prs3d_Root::CurrentGroup (thePresentation)->SetStencilTestOptions (Standard_True);
- }
- Prs3d_Root::CurrentGroup (thePresentation)->SetPrimitivesAspect (myDrawer->DimensionAspect()->LineAspect()->Aspect());
- Prs3d_Root::CurrentGroup (thePresentation)->AddPrimitiveArray (aPrimSegments);
- if (!myDrawer->DimensionAspect()->IsText3d() && theMode == AIS_DDM_All)
- {
- Prs3d_Root::CurrentGroup (thePresentation)->SetStencilTestOptions (Standard_False);
- }
- }
+ mySelectionGeom.TextPos = theTextPos;
+ mySelectionGeom.TextDir = theTextDir;
+ mySelectionGeom.TextWidth = 0.0;
+ mySelectionGeom.TextHeight = 0.0;
}
//=======================================================================
-//function : SetDimensionAspect
+//function : DrawExtension
//purpose :
//=======================================================================
-
-void AIS_Dimension::SetDimensionAspect (const Handle(Prs3d_DimensionAspect)& theDimensionAspect)
+void AIS_Dimension::DrawExtension (const Handle(Prs3d_Presentation)& thePresentation,
+ const Standard_Real theExtensionSize,
+ const gp_Pnt& theExtensionStart,
+ const gp_Dir& theExtensionDir,
+ const TCollection_ExtendedString& theLabelString,
+ const Standard_Real theLabelWidth,
+ const Standard_Integer theMode,
+ const Standard_Integer theLabelPosition)
{
- myDrawer->SetDimensionAspect (theDimensionAspect);
-}
+ // reference line for extension starting at its connection point
+ gp_Lin anExtensionLine (theExtensionStart, theExtensionDir);
-//=======================================================================
-//function : DimensionAspect
-//purpose :
-//=======================================================================
+ Standard_Boolean hasLabel = theLabelString.Length() > 0;
+ if (hasLabel && (theMode == ComputeMode_All || theMode == ComputeMode_Text))
+ {
+ // compute text primitives; get its model width
+ gp_Pnt aTextPos = ElCLib::Value (theExtensionSize, anExtensionLine);
+ gp_Dir aTextDir = theExtensionDir;
+
+ DrawText (thePresentation,
+ aTextPos,
+ aTextDir,
+ theLabelString,
+ theLabelPosition);
+ }
-Handle(Prs3d_DimensionAspect) AIS_Dimension::DimensionAspect() const
-{
- return myDrawer->DimensionAspect();
-}
+ if (theMode != ComputeMode_All && theMode != ComputeMode_Line)
+ {
+ return;
+ }
-//=======================================================================
-//function : SetTextOffset
-//purpose :
-//=======================================================================
+ Standard_Boolean isShortLine = !myDrawer->DimensionAspect()->IsText3d()
+ || theLabelPosition & LabelPosition_VCenter;
-void AIS_Dimension::SetTextOffset (const Standard_Real theOffset)
-{
- myTextOffset = theOffset;
-}
+ // compute graphical primitives and sensitives for extension line
+ gp_Pnt anExtStart = theExtensionStart;
+ gp_Pnt anExtEnd = !hasLabel || isShortLine
+ ? ElCLib::Value (theExtensionSize, anExtensionLine)
+ : ElCLib::Value (theExtensionSize + theLabelWidth, anExtensionLine);
-//=======================================================================
-//function : TextOffset
-//purpose :
-//=======================================================================
+ // add graphical primitives
+ Handle(Graphic3d_ArrayOfSegments) anExtPrimitive = new Graphic3d_ArrayOfSegments (2);
+ anExtPrimitive->AddVertex (anExtStart);
+ anExtPrimitive->AddVertex (anExtEnd);
-Standard_Real AIS_Dimension::TextOffset() const
-{
- return myTextOffset;
+ // add selection primitives
+ SelectionGeometry::Curve& aSensitiveCurve = mySelectionGeom.NewCurve();
+ aSensitiveCurve.Append (anExtStart);
+ aSensitiveCurve.Append (anExtEnd);
+
+ 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 == ComputeMode_All)
+ {
+ Prs3d_Root::CurrentGroup (thePresentation)->SetStencilTestOptions (Standard_False);
+ }
}
//=======================================================================
-//function : drawLinearDimension
+//function : DrawLinearDimension
//purpose :
//=======================================================================
-
-void AIS_Dimension::drawLinearDimension (const Handle(Prs3d_Presentation)& thePresentation,
- const gp_Pnt& theFirstAttach,
- const gp_Pnt& theSecondAttach,
- const AIS_DimensionDisplayMode theMode,
- const Standard_Boolean isOneSideDimension/* = Standard_False*/)
+void AIS_Dimension::DrawLinearDimension (const Handle(Prs3d_Presentation)& thePresentation,
+ const Standard_Integer theMode,
+ const gp_Pnt& theFirstPoint,
+ const gp_Pnt& theSecondPoint,
+ const Standard_Boolean theIsOneSide)
{
- // Don't build any dimension for equal points
- if (myFirstPoint.IsEqual (mySecondPoint, Precision::Confusion()))
+ // do not build any dimension for equal points
+ if (theFirstPoint.IsEqual (theSecondPoint, Precision::Confusion()))
{
- setComputed (Standard_False);
- return;
+ Standard_ProgramError::Raise ("Can not build presentation for equal points.");
}
- Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
- Handle(SelectMgr_EntityOwner) anEmptyOwner;
- myGeom.mySensitiveSegments.Clear();
- gp_Dir aAttachPointsVector = GetWorkingPlane().Axis().Direction()^gce_MakeDir (myFirstPoint, mySecondPoint);
- // Get line of the dimension
- gp_Lin aDimensionLine = gce_MakeLin (theFirstAttach, theSecondAttach);
+ Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
- // Get parameters on dimension line of two layout points
- Standard_Real aParam1 = ElCLib::Parameter (aDimensionLine, theFirstAttach);
- Standard_Real aParam2 = ElCLib::Parameter (aDimensionLine, theSecondAttach);
+ // For extensions we need to know arrow size, text size and extension size: get it from aspect
+ Quantity_Length anArrowLength = aDimensionAspect->ArrowAspect()->Length();
+ Standard_Real anExtensionSize = aDimensionAspect->ExtensionSize();
+ // prepare label string and compute its geometrical width
+ Standard_Real aLabelWidth;
+ TCollection_ExtendedString aLabelString = GetValueString (aLabelWidth);
- // For extensions we need to know arrow size and text size, get it from aspect
- Quantity_Length anArrowLength = aDimensionAspect->ArrowAspect()->Length();
- // Set line parameters
- Standard_Real aGap = 0.; // gap between line and text if AIS_VTA_Center
- if (!myIsValueCustom)
+ // add margins to cut dimension lines for 3d text
+ if (aDimensionAspect->IsText3d())
{
- computeValue();
+ aLabelWidth += aDimensionAspect->TextAspect()->Height() * THE_3D_TEXT_MARGIN * 2.0;
}
- TCollection_ExtendedString aValueString;
- Standard_Real aTextLength;
- getTextWidthAndString (aTextLength, aValueString);
+ // handle user-defined and automatic arrow placement
+ Standard_Boolean isArrowsExternal = Standard_False;
+ Standard_Integer aLabelPosition = LabelPosition_None;
- // Automatical text and arrow placement
- Standard_Real aValue = myFirstPoint.Distance (mySecondPoint);
- if (aDimensionAspect->HorizontalTextAlignment() == Prs3d_HTA_Center)
+ Prs3d_DimensionTextHorizontalPosition aHorisontalTextPos = aDimensionAspect->TextHorizontalPosition();
+ if (IsTextPositionCustom())
{
- aDimensionAspect->SetArrowOrientation (Prs3d_DAO_Internal);
- if (aValue < aTextLength + (isOneSideDimension ? anArrowLength : 2.0 * anArrowLength))
+ if (!AdjustParametersForLinear (myFixedTextPosition, theFirstPoint, theSecondPoint,
+ anExtensionSize, aHorisontalTextPos, myFlyout, myPlane, myIsPlaneCustom))
{
- aDimensionAspect->SetArrowOrientation (Prs3d_DAO_External);
- aDimensionAspect->SetHorizontalTextAlignment (Prs3d_HTA_Left);
+ Standard_ProgramError::Raise ("Can not adjust plane to the custom label position.");
}
}
- else
- {
- aDimensionAspect->SetArrowOrientation (Prs3d_DAO_External);
- }
- // Arrows positions and directions
- gp_Pnt aFirstArrowPosition = ElCLib::Value (aParam1, aDimensionLine);
- gp_Pnt aSecondArrowPosition = ElCLib::Value (aParam2, aDimensionLine);
- gp_Dir aFirstArrowDir = aDimensionLine.Direction();
- gp_Dir aSecondArrowDir = aDimensionLine.Direction().Reversed();
- Standard_Real aFirstArrowBegin, aFirstArrowEnd, aSecondArrowBegin, aSecondArrowEnd;
+ FitTextAlignmentForLinear (theFirstPoint, theSecondPoint, theIsOneSide, aHorisontalTextPos,
+ aLabelPosition, isArrowsExternal);
- if (aDimensionAspect->GetArrowOrientation() == Prs3d_DAO_External)
+ // compute dimension line points
+ gp_Ax1 aPlaneNormal = GetPlane().Axis();
+ gp_Dir aTargetPointsVector = gce_MakeDir (theFirstPoint, theSecondPoint);
+
+ // compute flyout direction vector
+ gp_Dir aFlyoutVector = aPlaneNormal.Direction() ^ aTargetPointsVector;
+
+ // create lines for layouts
+ gp_Lin aLine1 (theFirstPoint, aFlyoutVector);
+ gp_Lin aLine2 (theSecondPoint, aFlyoutVector);
+
+ // Get flyout end points
+ gp_Pnt aLineBegPoint = ElCLib::Value (ElCLib::Parameter (aLine1, theFirstPoint) + GetFlyout(), aLine1);
+ gp_Pnt aLineEndPoint = ElCLib::Value (ElCLib::Parameter (aLine2, theSecondPoint) + GetFlyout(), aLine2);
+
+ gp_Lin aDimensionLine = gce_MakeLin (aLineBegPoint, aLineEndPoint);
+
+ // compute arrows positions and directions
+ gp_Dir aFirstArrowDir = aDimensionLine.Direction().Reversed();
+ gp_Dir aSecondArrowDir = aDimensionLine.Direction();
+ gp_Dir aFirstExtensionDir = aDimensionLine.Direction().Reversed();
+ gp_Dir aSecondExtensionDir = aDimensionLine.Direction();
+
+ 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)
{
aFirstArrowDir.Reverse();
aSecondArrowDir.Reverse();
-
- aFirstArrowBegin = aParam1 - anArrowLength;
- aFirstArrowEnd = aParam1;
- aSecondArrowBegin = aParam2;
- aSecondArrowEnd = aParam2 + anArrowLength;
- }
- else
- {
- aFirstArrowBegin = aParam1;
- aFirstArrowEnd = aParam1 + anArrowLength;
- aSecondArrowBegin = aParam2 - anArrowLength;
- aSecondArrowEnd = aParam2;
}
- Handle(Graphic3d_ArrayOfSegments) aPrimSegments;
- gp_Pnt aFirstPoint, aLastPoint;
- // Take into account vertical text alignment:
- // only for 3D text! subtract the text length if it is in the center.
- Standard_Boolean isGapInCenter = (aDimensionAspect->VerticalTextAlignment() == Prs3d_VTA_Center
- && aDimensionAspect->IsText3d());
- if (isGapInCenter)
- {
- aGap = 1.0;
- }
+ aFirstArrowBegin = aLineBegPoint;
+ aSecondArrowBegin = aLineEndPoint;
+ aFirstArrowEnd = aLineBegPoint.Translated (-gp_Vec (aFirstArrowDir).Scaled (anArrowLength));
+ aSecondArrowEnd = aLineEndPoint.Translated (-gp_Vec (aSecondArrowDir).Scaled (anArrowLength));
+
+ gp_Pnt aCenterLineBegin = isArrowsExternal
+ ? aLineBegPoint : aFirstArrowEnd;
+
+ gp_Pnt aCenterLineEnd = isArrowsExternal || theIsOneSide
+ ? aLineEndPoint : aSecondArrowEnd;
- switch (aDimensionAspect->HorizontalTextAlignment())
+
+ switch (aLabelPosition & LabelPosition_HMask)
{
- // Default case - text is to be in the center of length dimension line
- case Prs3d_HTA_Center:
+ // ------------------------------------------------------------------------ //
+ // CENTER //
+ // -------------------------------------------------------------------------//
+ case LabelPosition_HCenter:
{
- // Group1: arrows
- if (theMode != AIS_DDM_Text)
- {
- drawArrow (thePresentation, aFirstArrowPosition, aFirstArrowDir);
- if (!isOneSideDimension)
- {
- drawArrow (thePresentation, aSecondArrowPosition, aSecondArrowDir);
- }
- }
-
- // Group 2: Text and dimension line
- aPrimSegments = new Graphic3d_ArrayOfSegments (isGapInCenter ? 4 : 2);
- myGeom.myTextPosition = ElCLib::Value ((aParam1 + aParam2) / 2.0, aDimensionLine);
+ // add label on dimension or extension line to presentation
+ Prs3d_Root::NewGroup (thePresentation);
- gp_Vec aTextDir (myFirstPoint, mySecondPoint);
- Standard_Real aTextWidth = drawText (thePresentation,
- myIsTextReversed ? aTextDir.Reversed() : aTextDir,
- aValueString,
- theMode);
+ gp_Pnt aTextPos = IsTextPositionCustom() ? myFixedTextPosition
+ : (aCenterLineBegin.XYZ() + aCenterLineEnd.XYZ()) * 0.5;
+ gp_Dir aTextDir = aDimensionLine.Direction();
- aFirstPoint = ElCLib::Value (aFirstArrowEnd, aDimensionLine);
- if (isGapInCenter)
- {
- aLastPoint = ElCLib::Value (ElCLib::Parameter (aDimensionLine,myGeom.myTextPosition) - aGap - (aTextWidth / 2.0), aDimensionLine);
- aPrimSegments->AddVertex (aFirstPoint);
- aPrimSegments->AddVertex (aLastPoint);
- myGeom.mySensitiveSegments.Append (new Select3D_SensitiveSegment (anEmptyOwner,aFirstPoint,aLastPoint));
- aFirstPoint = ElCLib::Value (ElCLib::Parameter(aDimensionLine,myGeom.myTextPosition) + (aTextWidth / 2.0) + aGap, aDimensionLine);
- }
- else if (aDimensionAspect->VerticalTextAlignment() == Prs3d_VTA_Top)
+ // add text primitives
+ if (theMode == ComputeMode_All || theMode == ComputeMode_Text)
{
- aDimensionAspect->TextAspect()->SetVerticalJustification (Graphic3d_VTA_BOTTOM);
+ DrawText (thePresentation,
+ aTextPos,
+ aTextDir,
+ aLabelString,
+ aLabelPosition);
}
- else if (aDimensionAspect->VerticalTextAlignment() == Prs3d_VTA_Bottom)
+
+ // add dimension line primitives
+ if (theMode == ComputeMode_All || theMode == ComputeMode_Line)
{
- aDimensionAspect->TextAspect()->SetVerticalJustification(Graphic3d_VTA_TOP);
- }
+ Standard_Boolean isLineBreak = aDimensionAspect->TextVerticalPosition() == Prs3d_DTVP_Center
+ && aDimensionAspect->IsText3d();
- aLastPoint = isOneSideDimension ? theSecondAttach : ElCLib::Value (aSecondArrowBegin, aDimensionLine);
+ Handle(Graphic3d_ArrayOfSegments) aPrimSegments = new Graphic3d_ArrayOfSegments (isLineBreak ? 4 : 2);
+
+ // 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);
- aPrimSegments->AddVertex (aFirstPoint);
- aPrimSegments->AddVertex (aLastPoint);
- myGeom.mySensitiveSegments.Append (new Select3D_SensitiveSegment (anEmptyOwner, aFirstPoint, aLastPoint));
+ SelectionGeometry::Curve& aSensitiveCurve = mySelectionGeom.NewCurve();
+ aSensitiveCurve.Append (aCenterLineBegin);
+ aSensitiveCurve.Append (aCenterLineEnd);
+ }
- // Main dimension line, short extension
- if (theMode != AIS_DDM_Text)
- {
- if (!aDimensionAspect->IsText3d() && theMode == AIS_DDM_All)
+ // 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 == 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 == AIS_DDM_All)
+ if (!aDimensionAspect->IsText3d() && theMode == ComputeMode_All)
{
Prs3d_Root::CurrentGroup (thePresentation)->SetStencilTestOptions (Standard_False);
}
- }
- break;
- }
- // Text is disposed from the left side of length dimension (after the left flyout line)
- // Needs to create extensions: left for text and right for proper view of dimensions.
- case Prs3d_HTA_Left:
- {
- aPrimSegments = new Graphic3d_ArrayOfSegments (4);
- gp_Pnt aFirstArrowBeginPnt = ElCLib::Value (aFirstArrowBegin, aDimensionLine);
- gp_Lin aLongExtLine (aDimensionLine.Location(), aDimensionLine.Direction().Reversed());
- gp_Pnt aStartPoint = ElCLib::Value (aFirstArrowBegin, aDimensionLine);
- // Left extension with the text
- drawExtensionWithText (thePresentation, aStartPoint, aLongExtLine, aValueString, theMode);
+ // add arrows to presentation
+ Prs3d_Root::NewGroup (thePresentation);
- // Central(main) dimension line
- aFirstPoint = ElCLib::Value (aFirstArrowEnd, aDimensionLine);
- aLastPoint = isOneSideDimension ? theSecondAttach : ElCLib::Value (aSecondArrowBegin, aDimensionLine);
- aPrimSegments->AddVertex (aFirstPoint);
- aPrimSegments->AddVertex (aLastPoint);
- myGeom.mySensitiveSegments.Append (new Select3D_SensitiveSegment (anEmptyOwner, aFirstPoint, aLastPoint));
+ DrawArrow (thePresentation, aFirstArrowBegin, aFirstArrowDir);
+ if (!theIsOneSide)
+ {
+ DrawArrow (thePresentation, aSecondArrowBegin, aSecondArrowDir);
+ }
- // Right extension
- if (!isOneSideDimension)
- {
- aFirstPoint = ElCLib::Value (aSecondArrowEnd, aDimensionLine);
- aLastPoint = ElCLib::Value (aSecondArrowEnd + anArrowLength, aDimensionLine);
- aPrimSegments->AddVertex (aFirstPoint);
- aPrimSegments->AddVertex (aLastPoint);
- myGeom.mySensitiveSegments.Append(new Select3D_SensitiveSegment (anEmptyOwner, aFirstPoint, aLastPoint));
+ if (!isArrowsExternal)
+ {
+ break;
+ }
+
+ // add arrow extension lines to presentation
+ Prs3d_Root::NewGroup (thePresentation);
+
+ DrawExtension (thePresentation, aDimensionAspect->ArrowTailSize(),
+ aFirstArrowEnd, aFirstExtensionDir,
+ THE_EMPTY_LABEL, 0.0, theMode, LabelPosition_None);
+ if (!theIsOneSide)
+ {
+ DrawExtension (thePresentation, aDimensionAspect->ArrowTailSize(),
+ aSecondArrowEnd, aSecondExtensionDir,
+ THE_EMPTY_LABEL, 0.0, theMode, LabelPosition_None);
+ }
}
- if (theMode != AIS_DDM_Text)
+
+ break;
+ }
+ // ------------------------------------------------------------------------ //
+ // LEFT //
+ // -------------------------------------------------------------------------//
+
+ case LabelPosition_Left:
+ {
+ // add label on dimension or extension line to presentation
+ Prs3d_Root::NewGroup (thePresentation);
+
+ // Left extension with the text
+ DrawExtension (thePresentation, anExtensionSize,
+ isArrowsExternal
+ ? aFirstArrowEnd
+ : aFirstArrowBegin,
+ aFirstExtensionDir,
+ aLabelString,
+ aLabelWidth,
+ theMode,
+ aLabelPosition);
+
+ // add dimension line primitives
+ if (theMode == ComputeMode_All || theMode == ComputeMode_Line)
{
- // Main dimension line, short extension
- Prs3d_Root::NewGroup (thePresentation)->SetPrimitivesAspect (aDimensionAspect->LineAspect()->Aspect());
+ // 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);
- // Group1: Add arrows to a group
- drawArrow (thePresentation, aFirstArrowPosition, aFirstArrowDir);
- if (!isOneSideDimension)
+
+ // add selection primitives
+ SelectionGeometry::Curve& aSensitiveCurve = mySelectionGeom.NewCurve();
+ aSensitiveCurve.Append (aCenterLineBegin);
+ aSensitiveCurve.Append (aCenterLineEnd);
+
+ // add arrows to presentation
+ Prs3d_Root::NewGroup (thePresentation);
+
+ DrawArrow (thePresentation, aFirstArrowBegin, aFirstArrowDir);
+ if (!theIsOneSide)
{
- drawArrow (thePresentation, aSecondArrowPosition, aSecondArrowDir);
+ DrawArrow (thePresentation, aSecondArrowBegin, aSecondArrowDir);
}
+
+ if (!isArrowsExternal || theIsOneSide)
+ {
+ break;
+ }
+
+ // add extension lines for external arrows
+ Prs3d_Root::NewGroup (thePresentation);
+
+ DrawExtension (thePresentation, aDimensionAspect->ArrowTailSize(),
+ aSecondArrowEnd, aSecondExtensionDir,
+ THE_EMPTY_LABEL, 0.0, theMode, LabelPosition_None);
}
+
break;
}
- case Prs3d_HTA_Right:
+ // ------------------------------------------------------------------------ //
+ // RIGHT //
+ // -------------------------------------------------------------------------//
+
+ case LabelPosition_Right:
{
- aPrimSegments = new Graphic3d_ArrayOfSegments (4);
- // Left extension
- if (!isOneSideDimension)
+ // add label on dimension or extension line to presentation
+ Prs3d_Root::NewGroup (thePresentation);
+
+ // Right extension with text
+ DrawExtension (thePresentation, anExtensionSize,
+ isArrowsExternal
+ ? aSecondArrowEnd
+ : aSecondArrowBegin,
+ aSecondExtensionDir,
+ aLabelString, aLabelWidth,
+ theMode,
+ aLabelPosition);
+
+ if (theMode == ComputeMode_All || theMode == ComputeMode_Line)
{
- aFirstPoint = ElCLib::Value (aFirstArrowBegin - anArrowLength, aDimensionLine);
- aLastPoint = ElCLib::Value (aFirstArrowEnd, aDimensionLine);
- aPrimSegments->AddVertex (aFirstPoint);
- aPrimSegments->AddVertex (aLastPoint);
- myGeom.mySensitiveSegments.Append (new Select3D_SensitiveSegment (anEmptyOwner, aFirstPoint, aLastPoint));
- }
+ // add central dimension line
+ Prs3d_Root::NewGroup (thePresentation);
- // Central(main) dimension line
- aFirstPoint = isOneSideDimension ? theFirstAttach : ElCLib::Value (aFirstArrowEnd, aDimensionLine);
- aLastPoint = ElCLib::Value (aSecondArrowBegin, aDimensionLine);
- aPrimSegments->AddVertex (aFirstPoint);
- aPrimSegments->AddVertex (aLastPoint);
- myGeom.mySensitiveSegments.Append (new Select3D_SensitiveSegment (anEmptyOwner, aFirstPoint, aLastPoint));
+ // 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);
- // Right extension with text
- aFirstPoint = ElCLib::Value (aSecondArrowEnd, aDimensionLine);
- drawExtensionWithText (thePresentation, aFirstPoint, aDimensionLine, aValueString, theMode);
+ // add selection primitives
+ SelectionGeometry::Curve& aSensitiveCurve = mySelectionGeom.NewCurve();
+ aSensitiveCurve.Append (aCenterLineBegin);
+ aSensitiveCurve.Append (aCenterLineEnd);
- if (theMode != AIS_DDM_Text)
- {
- // Main dimension line, short extension
- Prs3d_Root::NewGroup(thePresentation)->SetPrimitivesAspect (aDimensionAspect->LineAspect()->Aspect());
- Prs3d_Root::CurrentGroup(thePresentation)->AddPrimitiveArray (aPrimSegments);
- // Group1, 2: Add arrows to a group
- if (!isOneSideDimension)
+ // add arrows to presentation
+ Prs3d_Root::NewGroup (thePresentation);
+
+ DrawArrow (thePresentation, aSecondArrowBegin, aSecondArrowDir);
+ if (!theIsOneSide)
+ {
+ DrawArrow (thePresentation, aFirstArrowBegin, aFirstArrowDir);
+ }
+
+ if (!isArrowsExternal || theIsOneSide)
{
- drawArrow (thePresentation, aFirstArrowPosition, aFirstArrowDir);
+ break;
}
- drawArrow (thePresentation, aSecondArrowPosition, aSecondArrowDir);
+ // add extension lines for external arrows
+ Prs3d_Root::NewGroup (thePresentation);
+
+ DrawExtension (thePresentation, aDimensionAspect->ArrowTailSize(),
+ aFirstArrowEnd, aFirstExtensionDir,
+ THE_EMPTY_LABEL, 0.0, theMode, LabelPosition_None);
}
+
break;
}
}
- setComputed (Standard_True);
-}
+ // add flyout lines to presentation
+ if (theMode == ComputeMode_All)
+ {
+ Prs3d_Root::NewGroup (thePresentation);
-//=======================================================================
-//function : SetFirstPoint
-//purpose :
-//=======================================================================
+ Handle(Graphic3d_ArrayOfSegments) aPrimSegments = new Graphic3d_ArrayOfSegments(4);
+ aPrimSegments->AddVertex (theFirstPoint);
+ aPrimSegments->AddVertex (aLineBegPoint);
-void AIS_Dimension::SetFirstPoint (const gp_Pnt& thePoint)
-{
- myFirstPoint = thePoint;
-}
+ aPrimSegments->AddVertex (theSecondPoint);
+ aPrimSegments->AddVertex (aLineEndPoint);
-//=======================================================================
-//function : SetSecondPoint
-//purpose :
-//=======================================================================
+ Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
+ Prs3d_Root::CurrentGroup (thePresentation)->SetPrimitivesAspect (aDimensionAspect->LineAspect()->Aspect());
+ Prs3d_Root::CurrentGroup (thePresentation)->AddPrimitiveArray (aPrimSegments);
+ }
-void AIS_Dimension::SetSecondPoint (const gp_Pnt& thePoint)
-{
- mySecondPoint = thePoint;
+ mySelectionGeom.IsComputed = Standard_True;
}
//=======================================================================
-//function : Type
+//function : ComputeLinearFlyouts
//purpose :
//=======================================================================
-
-AIS_KindOfInteractive AIS_Dimension::Type() const
+void AIS_Dimension::ComputeLinearFlyouts (const Handle(SelectMgr_Selection)& theSelection,
+ const Handle(SelectMgr_EntityOwner)& theOwner,
+ const gp_Pnt& theFirstPoint,
+ const gp_Pnt& theSecondPoint)
{
- return AIS_KOI_Relation;
+ // count flyout direction
+ gp_Ax1 aPlaneNormal = GetPlane().Axis();
+ gp_Dir aTargetPointsVector = gce_MakeDir (theFirstPoint, theSecondPoint);
+
+ // count a flyout direction vector.
+ gp_Dir aFlyoutVector = aPlaneNormal.Direction() ^ aTargetPointsVector;
+
+ // create lines for layouts
+ gp_Lin aLine1 (theFirstPoint, aFlyoutVector);
+ gp_Lin aLine2 (theSecondPoint, aFlyoutVector);
+
+ // get flyout end points
+ gp_Pnt aFlyoutEnd1 = ElCLib::Value (ElCLib::Parameter (aLine1, theFirstPoint) + GetFlyout(), aLine1);
+ gp_Pnt aFlyoutEnd2 = ElCLib::Value (ElCLib::Parameter (aLine2, theSecondPoint) + GetFlyout(), aLine2);
+
+ // fill sensitive entity for flyouts
+ Handle(Select3D_SensitiveGroup) aSensitiveEntity = new Select3D_SensitiveGroup (theOwner);
+ aSensitiveEntity->Add (new Select3D_SensitiveSegment (theOwner, theFirstPoint, aFlyoutEnd1));
+ aSensitiveEntity->Add (new Select3D_SensitiveSegment (theOwner, theSecondPoint, aFlyoutEnd2));
+ theSelection->Add (aSensitiveEntity);
}
//=======================================================================
-//function : circleFromPlanarFace
+//function : CircleFromPlanarFace
//purpose : if possible computes circle from planar face
//=======================================================================
-
-Standard_Boolean AIS_Dimension::circleFromPlanarFace (const TopoDS_Face& theFace,
+Standard_Boolean AIS_Dimension::CircleFromPlanarFace (const TopoDS_Face& theFace,
Handle(Geom_Curve)& theCurve,
- gp_Pnt & theFirstPoint,
- gp_Pnt & theLastPoint)
+ gp_Pnt& theFirstPoint,
+ gp_Pnt& theLastPoint)
{
TopExp_Explorer anIt (theFace, TopAbs_EDGE);
for ( ; anIt.More(); anIt.Next())
}
//=======================================================================
-//function : initCircularDimension
-//purpose : if it's possible computes circle from planar face
+//function : CircleFromEdge
+//purpose : if possible computes circle from edge
//=======================================================================
+Standard_Boolean AIS_Dimension::CircleFromEdge (const TopoDS_Edge& theEdge,
+ gp_Circ& theCircle,
+ gp_Pnt& theFirstPoint,
+ gp_Pnt& theLastPoint)
+{
+ BRepAdaptor_Curve anAdaptedCurve (theEdge);
+ switch (anAdaptedCurve.GetType())
+ {
+ case GeomAbs_Circle:
+ {
+ theCircle = anAdaptedCurve.Circle();
+ break;
+ }
+ case GeomAbs_Ellipse:
+ {
+ gp_Elips anEll = anAdaptedCurve.Ellipse();
+ if ((anEll.MinorRadius() - anEll.MajorRadius()) >= Precision::Confusion())
+ {
+ return Standard_False;
+ }
+ theCircle = gp_Circ(anEll.Position(),anEll.MinorRadius());
+ break;
+ }
+ case GeomAbs_Line:
+ case GeomAbs_Hyperbola:
+ case GeomAbs_Parabola:
+ case GeomAbs_BezierCurve:
+ case GeomAbs_BSplineCurve:
+ case GeomAbs_OtherCurve:
+ default:
+ return Standard_False;
+ }
-Standard_Boolean AIS_Dimension::initCircularDimension (const TopoDS_Shape& theShape,
+ theFirstPoint = anAdaptedCurve.Value (anAdaptedCurve.FirstParameter());
+ theLastPoint = anAdaptedCurve.Value (anAdaptedCurve.LastParameter());
+ return Standard_True;
+}
+
+//=======================================================================
+//function : InitCircularDimension
+//purpose :
+//=======================================================================
+Standard_Boolean AIS_Dimension::InitCircularDimension (const TopoDS_Shape& theShape,
gp_Circ& theCircle,
gp_Pnt& theMiddleArcPoint,
- gp_Pnt& theOppositeDiameterPoint)
+ Standard_Boolean& theIsClosed)
{
gp_Pln aPln;
Handle(Geom_Surface) aBasisSurf;
Standard_Real anOffset = 0.0;
Standard_Real aFirstParam = 0.0;
Standard_Real aLastParam = 0.0;
- Standard_Boolean isAnArc = Standard_False;
- if (theShape.ShapeType() == TopAbs_FACE)
+ // Discover circular geometry
+ switch (theShape.ShapeType())
{
- AIS::GetPlaneFromFace (TopoDS::Face (theShape), aPln, aBasisSurf, aSurfType, anOffset);
-
- if (aSurfType == AIS_KOS_Plane)
+ case TopAbs_FACE:
{
- Handle(Geom_Curve) aCurve;
- if (!circleFromPlanarFace (TopoDS::Face (theShape), aCurve, aFirstPoint, aLastPoint))
- {
- Standard_ConstructionError::Raise ("AIS_Dimension:: Curve is not a circle or is Null") ;
- return Standard_False;
- }
+ AIS::GetPlaneFromFace (TopoDS::Face (theShape), aPln, aBasisSurf, aSurfType, anOffset);
- theCircle = Handle(Geom_Circle)::DownCast (aCurve)->Circ();
- isAnArc = !(aFirstPoint.IsEqual (aLastPoint, Precision::Confusion()));
- }
- else
- {
- gp_Pnt aCurPos;
- BRepAdaptor_Surface aSurf1 (TopoDS::Face (theShape));
- Standard_Real aFirstU = aSurf1.FirstUParameter();
- Standard_Real aLastU = aSurf1.LastUParameter();
- Standard_Real aFirstV = aSurf1.FirstVParameter();
- Standard_Real aLastV = aSurf1.LastVParameter();
- Standard_Real aMidU = (aFirstU + aLastU) * 0.5;
- Standard_Real aMidV = (aFirstV + aLastV) * 0.5;
- aSurf1.D0(aMidU, aMidV, aCurPos);
- Handle (Adaptor3d_HCurve) aBasisCurve;
- Standard_Boolean isExpectedType = Standard_False;
- if (aSurfType == AIS_KOS_Cylinder)
+ if (aSurfType == AIS_KOS_Plane)
{
- isExpectedType = Standard_True;
+ Handle(Geom_Curve) aCurve;
+ if (!CircleFromPlanarFace (TopoDS::Face (theShape), aCurve, aFirstPoint, aLastPoint))
+ {
+ return Standard_False;
+ }
+
+ theCircle = Handle(Geom_Circle)::DownCast (aCurve)->Circ();
}
else
{
- if (aSurfType == AIS_KOS_Revolution)
+ gp_Pnt aCurPos;
+ BRepAdaptor_Surface aSurf1 (TopoDS::Face (theShape));
+ Standard_Real aFirstU = aSurf1.FirstUParameter();
+ Standard_Real aLastU = aSurf1.LastUParameter();
+ Standard_Real aFirstV = aSurf1.FirstVParameter();
+ Standard_Real aLastV = aSurf1.LastVParameter();
+ Standard_Real aMidU = (aFirstU + aLastU) * 0.5;
+ Standard_Real aMidV = (aFirstV + aLastV) * 0.5;
+ aSurf1.D0 (aMidU, aMidV, aCurPos);
+ Handle (Adaptor3d_HCurve) aBasisCurve;
+ Standard_Boolean isExpectedType = Standard_False;
+ if (aSurfType == AIS_KOS_Cylinder)
{
- aBasisCurve = aSurf1.BasisCurve();
- if (aBasisCurve->GetType() == GeomAbs_Line)
+ isExpectedType = Standard_True;
+ }
+ else
+ {
+ if (aSurfType == AIS_KOS_Revolution)
{
- isExpectedType = Standard_True;
+ aBasisCurve = aSurf1.BasisCurve();
+ if (aBasisCurve->GetType() == GeomAbs_Line)
+ {
+ isExpectedType = Standard_True;
+ }
+ }
+ else if (aSurfType == AIS_KOS_Extrusion)
+ {
+ aBasisCurve = aSurf1.BasisCurve();
+ if (aBasisCurve->GetType() == GeomAbs_Circle)
+ {
+ isExpectedType = Standard_True;
+ }
}
}
- else if (aSurfType == AIS_KOS_Extrusion)
+
+ if (!isExpectedType)
+ {
+ return Standard_False;
+ }
+
+ Handle(Geom_Curve) aCurve = aBasisSurf->VIso(aMidV);
+ if (aCurve->DynamicType() == STANDARD_TYPE (Geom_Circle))
{
- aBasisCurve = aSurf1.BasisCurve();
- if (aBasisCurve->GetType() == GeomAbs_Circle)
+ theCircle = Handle(Geom_Circle)::DownCast (aCurve)->Circ();
+ }
+ else if (aCurve->DynamicType() == STANDARD_TYPE (Geom_TrimmedCurve))
+ {
+ Handle(Geom_TrimmedCurve) aTrimmedCurve = Handle(Geom_TrimmedCurve)::DownCast (aCurve);
+ aFirstU = aTrimmedCurve->FirstParameter();
+ aLastU = aTrimmedCurve->LastParameter();
+ if (aTrimmedCurve->BasisCurve()->DynamicType() == STANDARD_TYPE (Geom_Circle))
{
- isExpectedType = Standard_True;
+ theCircle = Handle(Geom_Circle)::DownCast(aTrimmedCurve->BasisCurve())->Circ();
}
}
- }
-
- if (!isExpectedType)
- {
- Standard_ConstructionError::Raise ("AIS_Dimension:: Unexpected type of surface") ;
- return Standard_False;
- }
- Handle(Geom_Curve) aCurve;
- aCurve = aBasisSurf->VIso(aMidV);
- if (aCurve->DynamicType() == STANDARD_TYPE (Geom_Circle))
- {
- theCircle = Handle(Geom_Circle)::DownCast (aCurve)->Circ();
- }
- else if (aCurve->DynamicType() == STANDARD_TYPE (Geom_TrimmedCurve))
- {
- Handle(Geom_TrimmedCurve) aTrimmedCurve = Handle(Geom_TrimmedCurve)::DownCast (aCurve);
- aFirstU = aTrimmedCurve->FirstParameter();
- aLastU = aTrimmedCurve->LastParameter();
- if (aTrimmedCurve->DynamicType() == STANDARD_TYPE (Geom_Circle))
+ else
{
- theCircle = Handle(Geom_Circle)::DownCast(aTrimmedCurve)->Circ();
+ // Compute a circle from 3 points on "aCurve"
+ gp_Pnt aP1, aP2;
+ aSurf1.D0 (aFirstU, aMidV, aP1);
+ aSurf1.D0 (aLastU, aMidV, aP2);
+ GC_MakeCircle aMkCirc (aP1, aCurPos, aP2);
+ theCircle = aMkCirc.Value()->Circ();
}
- }
- else
- {
- // Compute a circle from 3 points on "aCurve"
- gp_Pnt aP1, aP2;
- aSurf1.D0 (aFirstU, aMidV, aP1);
- aSurf1.D0 (aLastU, aMidV, aP2);
- GC_MakeCircle aMkCirc (aP1, aCurPos, aP2);
- theCircle = aMkCirc.Value()->Circ();
- }
- gp_Vec aVec = gp_Vec (theCircle.Location(), aCurPos).Normalized();
- aFirstPoint = ElCLib::Value (aFirstU, theCircle);
- aLastPoint = ElCLib::Value (aLastU, theCircle);
+ aFirstPoint = ElCLib::Value (aFirstU, theCircle);
+ aLastPoint = ElCLib::Value (aLastU, theCircle);
+ }
+ break;
}
- }
- else // TopAbs_EDGE | TopAbs_WIRE
- {
- TopoDS_Edge anEdge;
- if (theShape.ShapeType() == TopAbs_WIRE)
+ case TopAbs_WIRE:
{
+ TopoDS_Edge anEdge;
TopExp_Explorer anIt (theShape, TopAbs_EDGE);
if (anIt.More())
{
anEdge = TopoDS::Edge (anIt.Current());
}
+ if (!AIS_Dimension::CircleFromEdge (anEdge, theCircle, aFirstPoint, aLastPoint))
+ {
+ return Standard_False;
+ }
+ break;
}
- else if (theShape.ShapeType() == TopAbs_EDGE)
- {
- anEdge = TopoDS::Edge (theShape);
- }
- else // Unexpected type of shape
+ case TopAbs_EDGE:
{
- Standard_ConstructionError::Raise ("AIS_Dimension:: Unexpected type of shape");
- return Standard_False;
+ TopoDS_Edge anEdge = TopoDS::Edge (theShape);
+ if (!AIS_Dimension::CircleFromEdge (anEdge, theCircle, aFirstPoint, aLastPoint))
+ {
+ return Standard_False;
+ }
+ break;
}
- BRepAdaptor_Curve anAdaptedCurve (anEdge);
- if (!anAdaptedCurve.GetType() == GeomAbs_Circle)
- {
+ case TopAbs_COMPOUND:
+ case TopAbs_COMPSOLID:
+ case TopAbs_SOLID:
+ case TopAbs_SHELL:
+ case TopAbs_VERTEX:
+ case TopAbs_SHAPE:
+ default:
return Standard_False;
- }
- theCircle = anAdaptedCurve.Circle();
- aFirstPoint = anAdaptedCurve.Value (anAdaptedCurve.FirstParameter());
- aLastPoint = anAdaptedCurve.Value (anAdaptedCurve.LastParameter());
}
- // Get <theMiddleArcPoint> and <theOppositeDiameterPoint> values from <theCircle>
- isAnArc = !(aFirstPoint.IsEqual (aLastPoint, Precision::Confusion()));
+
+ theIsClosed = aFirstPoint.IsEqual (aLastPoint, Precision::Confusion());
+
gp_Pnt aCenter = theCircle.Location();
- if (!isAnArc)
+
+ if (theIsClosed) // Circle
{
- // Circle
gp_Dir anXDir = theCircle.XAxis().Direction();
theMiddleArcPoint = aCenter.Translated (gp_Vec (anXDir) * theCircle.Radius());
- theOppositeDiameterPoint = aCenter.Translated (-gp_Vec (anXDir) * theCircle.Radius());
}
- else
+ else // Arc
{
- // Arc
aFirstParam = ElCLib::Parameter (theCircle, aFirstPoint);
aLastParam = ElCLib::Parameter (theCircle, aLastPoint);
if (aFirstParam > aLastParam)
{
aFirstParam -= 2.0 * M_PI;
}
+
Standard_Real aParCurPos = (aFirstParam + aLastParam) * 0.5;
gp_Vec aVec = gp_Vec (aCenter, ElCLib::Value (aParCurPos, theCircle)).Normalized () * theCircle.Radius ();
theMiddleArcPoint = aCenter.Translated (aVec);
- theOppositeDiameterPoint = aCenter.Translated (-aVec);
}
return Standard_True;
}
//=======================================================================
-//function : SetDisplaySpecialSymbol
-//purpose : specifies dimension special symbol display options
+//function : ComputeSelection
+//purpose :
//=======================================================================
-
-void AIS_Dimension::SetDisplaySpecialSymbol (const AIS_DisplaySpecialSymbol theDisplaySpecSymbol)
+void AIS_Dimension::ComputeSelection (const Handle(SelectMgr_Selection)& theSelection,
+ const Standard_Integer theMode)
{
- myDisplaySpecialSymbol = theDisplaySpecSymbol;
-}
+ if (!mySelectionGeom.IsComputed)
+ {
+ return;
+ }
-//=======================================================================
-//function : DisplaySpecialSymbol
-//purpose : shows dimension special symbol display options
-//=======================================================================
+ AIS_DimensionSelectionMode aSelectionMode = (AIS_DimensionSelectionMode)theMode;
-AIS_DisplaySpecialSymbol AIS_Dimension::DisplaySpecialSymbol() const
-{
- return myDisplaySpecialSymbol;
-}
+ // init appropriate entity owner
+ Handle(SelectMgr_EntityOwner) aSensitiveOwner;
-//=======================================================================
-//function : SetSpecialSymbol
-//purpose : specifies special symbol
-//=======================================================================
+ switch (aSelectionMode)
+ {
+ // neutral selection owner
+ case AIS_DSM_All :
+ aSensitiveOwner = new SelectMgr_EntityOwner (this, THE_NEUTRAL_SEL_PRIORITY);
+ break;
-void AIS_Dimension::SetSpecialSymbol (const Standard_ExtCharacter theSpecialSymbol)
-{
- mySpecialSymbol = theSpecialSymbol;
-}
+ // local selection owners
+ case AIS_DSM_Line :
+ case AIS_DSM_Text :
+ aSensitiveOwner = new AIS_DimensionOwner (this, aSelectionMode, THE_LOCAL_SEL_PRIORITY);
+ break;
+ }
-//=======================================================================
-//function : SpecialSymbol
-//purpose : returns special symbol
-//=======================================================================
+ if (aSelectionMode == AIS_DSM_All || aSelectionMode == AIS_DSM_Line)
+ {
+ // sensitives for dimension line segments
+ Handle(Select3D_SensitiveGroup) aGroupOfSensitives = new Select3D_SensitiveGroup (aSensitiveOwner);
-Standard_ExtCharacter AIS_Dimension::SpecialSymbol() const
-{
- return mySpecialSymbol;
-}
+ SelectionGeometry::SeqOfCurves::Iterator aCurveIt (mySelectionGeom.DimensionLine);
+ for (; aCurveIt.More(); aCurveIt.Next())
+ {
+ const SelectionGeometry::HCurve& aCurveData = aCurveIt.Value();
-//=======================================================================
-//function : IsUnitsDisplayed
-//purpose : shows if Units are to be displayed along with dimension value
-//=======================================================================
+ TColgp_Array1OfPnt aSensitivePnts (1, aCurveData->Length());
+ for (Standard_Integer aPntIt = 1; aPntIt <= aCurveData->Length(); ++aPntIt)
+ {
+ aSensitivePnts.ChangeValue (aPntIt) = aCurveData->Value (aPntIt);
+ }
-Standard_Boolean AIS_Dimension::IsUnitsDisplayed() const
-{
- return myToDisplayUnits;
-}
+ aGroupOfSensitives->Add (new Select3D_SensitiveCurve (aSensitiveOwner, aSensitivePnts));
+ }
-//=======================================================================
-//function : MakeUnitsDisplayed
-//purpose : sets to display units along with the dimension value or no
-//=======================================================================
+ Quantity_Length anArrowLength = myDrawer->DimensionAspect()->ArrowAspect()->Length();
+ Standard_Real anArrowAngle = myDrawer->DimensionAspect()->ArrowAspect()->Angle();
-void AIS_Dimension::MakeUnitsDisplayed (const Standard_Boolean toDisplayUnits)
-{
- myToDisplayUnits = toDisplayUnits;
-}
+ // sensitives for arrows
+ SelectionGeometry::SeqOfArrows::Iterator anArrowIt (mySelectionGeom.Arrows);
+ for (; anArrowIt.More(); anArrowIt.Next())
+ {
+ const SelectionGeometry::HArrow& anArrow = anArrowIt.Value();
-//=======================================================================
-//function : MakeUnitsDisplayed
-//purpose : returns the current type of units
-//=======================================================================
+ gp_Pnt aSidePnt1 (gp::Origin());
+ gp_Pnt aSidePnt2 (gp::Origin());
+ const gp_Dir& aPlane = GetPlane().Axis().Direction();
+ const gp_Pnt& aPeak = anArrow->Position;
+ const gp_Dir& aDir = anArrow->Direction;
-TCollection_AsciiString AIS_Dimension::UnitsQuantity() const
-{
- return myUnitsQuantity;
-}
+ // compute points for arrow in plane
+ PointsForArrow (aPeak, aDir, aPlane, anArrowLength, anArrowAngle, aSidePnt1, aSidePnt2);
-//=======================================================================
-//function : SetUnitsQuantity
-//purpose : sets the current type of units
-//=======================================================================
+ aGroupOfSensitives->Add (new Select3D_SensitiveTriangle (aSensitiveOwner, aPeak, aSidePnt1, aSidePnt2));
-void AIS_Dimension::SetUnitsQuantity (const TCollection_AsciiString& theUnitsQuantity)
-{
- myUnitsQuantity = theUnitsQuantity;
-}
+ if (!myDrawer->DimensionAspect()->IsArrows3d())
+ {
+ continue;
+ }
-//=======================================================================
-//function : ModelUnits
-//purpose : returns the current model units
-//=======================================================================
+ // compute points for orthogonal sensitive plane
+ gp_Dir anOrthoPlane = anArrow->Direction.Crossed (aPlane);
-TCollection_AsciiString AIS_Dimension::ModelUnits() const
-{
- return myModelUnits;
-}
+ PointsForArrow (aPeak, aDir, anOrthoPlane, anArrowLength, anArrowAngle, aSidePnt1, aSidePnt2);
-//=======================================================================
-//function : SetModelUnits
-//purpose : sets the current model units
-//=======================================================================
+ aGroupOfSensitives->Add (new Select3D_SensitiveTriangle (aSensitiveOwner, aPeak, aSidePnt1, aSidePnt2));
+ }
-void AIS_Dimension::SetModelUnits (const TCollection_AsciiString& theUnits)
-{
- myModelUnits = theUnits;
-}
+ theSelection->Add (aGroupOfSensitives);
+ }
-//=======================================================================
-//function : DisplayUnits
-//purpose : returns the current display units
-//=======================================================================
+ // sensitives for text element
+ if (aSelectionMode == AIS_DSM_All || aSelectionMode == AIS_DSM_Text)
+ {
+ Handle(Select3D_SensitiveEntity) aTextSensitive;
-TCollection_AsciiString AIS_Dimension::DisplayUnits() const
-{
- return myDisplayUnits;
-}
+ gp_Ax2 aTextAxes (mySelectionGeom.TextPos,
+ GetPlane().Axis().Direction(),
+ mySelectionGeom.TextDir);
-//=======================================================================
-//function : SetDisplayUnits
-//purpose : sets the current display units
-//=======================================================================
+ if (myDrawer->DimensionAspect()->IsText3d())
+ {
+ // sensitive planar rectangle for text
+ Standard_Real aDx = mySelectionGeom.TextWidth * 0.5;
+ Standard_Real aDy = mySelectionGeom.TextHeight * 0.5;
-void AIS_Dimension::SetDisplayUnits (const TCollection_AsciiString& theUnits)
-{
- myDisplayUnits = theUnits;
-}
+ gp_Trsf aLabelPlane;
+ aLabelPlane.SetTransformation (aTextAxes, gp::XOY());
-//=======================================================================
-//function : isComputed
-//purpose :
-//=======================================================================
+ 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);
-Standard_Boolean AIS_Dimension::isComputed() const
-{
- return myGeom.myIsComputed;
-}
+ Poly_Array1OfTriangle aTriangles(1, 2);
+ aTriangles.ChangeValue(1) = Poly_Triangle(1, 2, 3);
+ aTriangles.ChangeValue(2) = Poly_Triangle(1, 3, 4);
-//=======================================================================
-//function : setComputed
-//purpose :
-//=======================================================================
+ Handle(Poly_Triangulation) aRectanglePoly =
+ new Poly_Triangulation(aRectanglePoints, aTriangles);
-void AIS_Dimension::setComputed (Standard_Boolean isComputed)
-{
- myGeom.myIsComputed = isComputed;
-}
+ aTextSensitive =
+ new Select3D_SensitiveTriangulation (aSensitiveOwner, aRectanglePoly, TopLoc_Location(), Standard_True);
+ }
+ else
+ {
+ gp_Circ aTextGeom (aTextAxes, mySelToleranceForText2d != 0.0
+ ? mySelToleranceForText2d : 1.0);
-//=======================================================================
-//function : textPosition
-//purpose :
-//=======================================================================
+ Handle(Geom_Circle) aSensGeom = new Geom_Circle (aTextGeom);
-gp_Pnt AIS_Dimension::textPosition() const
-{
- return myGeom.myTextPosition;
-}
+ aTextSensitive = new Select3D_SensitiveCircle (aSensitiveOwner, aSensGeom, Standard_True);
+ }
-//=======================================================================
-//function : setTextPosition
-//purpose :
-//=======================================================================
+ theSelection->Add (aTextSensitive);
+ }
-void AIS_Dimension::setTextPosition (const gp_Pnt thePosition)
-{
- myGeom.myTextPosition = thePosition;
+ // callback for flyout sensitive calculation
+ if (aSelectionMode == AIS_DSM_All)
+ {
+ ComputeFlyoutSelection (theSelection, aSensitiveOwner);
+ }
}
//=======================================================================
-//function : resetGeom
-//purpose :
+//function : PointsForArrow
+//purpose :
//=======================================================================
-
-void AIS_Dimension::resetGeom()
+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)
{
- setComputed (Standard_False);
-}
+ gp_Lin anArrowLin (thePeakPnt, theDirection.Reversed());
+ gp_Pnt anArrowEnd = ElCLib::Value (theArrowLength, anArrowLin);
+ gp_Lin anEdgeLin (anArrowEnd, theDirection.Crossed (thePlane));
-//=======================================================================
-//function : IsTextReversed
-//purpose :
-//=======================================================================
+ Standard_Real anEdgeLength = Tan (theArrowAngle) * theArrowLength;
-Standard_Boolean AIS_Dimension::IsTextReversed() const
-{
- return myIsTextReversed;
+ theSidePnt1 = ElCLib::Value ( anEdgeLength, anEdgeLin);
+ theSidePnt2 = ElCLib::Value (-anEdgeLength, anEdgeLin);
}
//=======================================================================
-//function : MakeTextReversed
-//purpose :
+//function : GetTextPositionForLinear
+//purpose :
//=======================================================================
-
-void AIS_Dimension::MakeTextReversed (const Standard_Boolean isTextReversed)
+gp_Pnt AIS_Dimension::GetTextPositionForLinear (const gp_Pnt& theFirstPoint,
+ const gp_Pnt& theSecondPoint,
+ const Standard_Boolean theIsOneSide) const
{
- myIsTextReversed = isTextReversed;
-}
+ if (!IsValid())
+ {
+ return gp::Origin();
+ }
-//=======================================================================
-//function : SetSelToleranceForText2d
-//purpose :
-//=======================================================================
+ gp_Pnt aTextPosition (gp::Origin());
-void AIS_Dimension::SetSelToleranceForText2d (const Standard_Real theTol)
-{
- myGeom.mySelToleranceForText2d = theTol;
-}
+ Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
-//=======================================================================
-//function : SelToleranceForText2d
-//purpose :
-//=======================================================================
+ // Get label alignment and arrow orientation.
+ Standard_Integer aLabelPosition = 0;
+ Standard_Boolean isArrowsExternal = Standard_False;
+ FitTextAlignmentForLinear (theFirstPoint, theSecondPoint, theIsOneSide,
+ aDimensionAspect->TextHorizontalPosition(),
+ aLabelPosition, isArrowsExternal);
+
+ // Compute dimension line points.
+ gp_Dir aPlaneNormal = GetPlane().Axis().Direction();
+ gp_Vec aTargetPointsVec (theFirstPoint, theSecondPoint);
+
+ // Compute flyout direction vector
+ gp_Dir aFlyoutVector = aPlaneNormal ^ gp_Dir (aTargetPointsVec);
+
+ // create lines for layouts
+ gp_Lin aLine1 (theFirstPoint, aFlyoutVector);
+ gp_Lin aLine2 (theSecondPoint, aFlyoutVector);
+ // Get flyout end points
+ gp_Pnt aLineBegPoint = ElCLib::Value (ElCLib::Parameter (aLine1, theFirstPoint) + GetFlyout(), aLine1);
+ gp_Pnt aLineEndPoint = ElCLib::Value (ElCLib::Parameter (aLine2, theSecondPoint) + GetFlyout(), aLine2);
+
+ // Get text position.
+ switch (aLabelPosition & LabelPosition_HMask)
+ {
+ case LabelPosition_Left:
+ {
+ gp_Dir aTargetPointsDir = gce_MakeDir (theFirstPoint, theSecondPoint);
+ Standard_Real anExtensionSize = aDimensionAspect->ExtensionSize();
+
+ Standard_Real anOffset = isArrowsExternal
+ ? anExtensionSize + aDimensionAspect->ArrowAspect()->Length()
+ : anExtensionSize;
+ gp_Vec anExtensionVec = gp_Vec (aTargetPointsDir) * -anOffset;
+ aTextPosition = aLineEndPoint.Translated (anExtensionVec);
+ }
+ break;
+ case LabelPosition_Right:
+ {
+ gp_Dir aTargetPointsDir = gce_MakeDir (theFirstPoint, theSecondPoint);
+ Standard_Real anExtensionSize = aDimensionAspect->ExtensionSize();
+
+ Standard_Real anOffset = isArrowsExternal
+ ? anExtensionSize + aDimensionAspect->ArrowAspect()->Length()
+ : anExtensionSize;
+ gp_Vec anExtensionVec = gp_Vec (aTargetPointsDir) * anOffset;
+ aTextPosition = aLineBegPoint.Translated (anExtensionVec);
+ }
+ break;
+ case LabelPosition_HCenter:
+ {
+ aTextPosition = (aLineBegPoint.XYZ() + aLineEndPoint.XYZ()) * 0.5;
+ }
+ break;
+ }
-Standard_Real AIS_Dimension::SelToleranceForText2d() const
-{
- return myGeom.mySelToleranceForText2d;
+ return aTextPosition;
}
//=======================================================================
-//function : SetFlyout
+//function : AdjustParametersForLinear
//purpose :
//=======================================================================
-
-void AIS_Dimension::SetFlyout (const Standard_Real theFlyout)
+Standard_Boolean AIS_Dimension::AdjustParametersForLinear (const gp_Pnt& theTextPos,
+ const gp_Pnt& theFirstPoint,
+ const gp_Pnt& theSecondPoint,
+ Standard_Real& theExtensionSize,
+ Prs3d_DimensionTextHorizontalPosition& theAlignment,
+ Standard_Real& theFlyout,
+ gp_Pln& thePlane,
+ Standard_Boolean& theIsPlaneOld) const
{
- myFlyout = theFlyout;
-}
+ Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
+ Standard_Real anArrowLength = aDimensionAspect->ArrowAspect()->Length();
-//=======================================================================
-//function : GetFlyout
-//purpose :
-//=======================================================================
+ gp_Dir aTargetPointsDir = gce_MakeDir (theFirstPoint, theSecondPoint);
+ gp_Vec aTargetPointsVec (theFirstPoint, theSecondPoint);
-Standard_Real AIS_Dimension::GetFlyout () const
-{
- return myFlyout;
-}
+ // Don't set new plane if the text position lies on the attachment points line.
+ gp_Lin aTargetPointsLin (theFirstPoint, aTargetPointsDir);
+ if (!aTargetPointsLin.Contains (theTextPos, Precision::Confusion()))
+ {
+ //Set new automatic plane.
+ thePlane = gce_MakePln (theTextPos, theFirstPoint, theSecondPoint);
+ theIsPlaneOld = Standard_False;
+ }
-//=======================================================================
-//function : computeFlyoutSelection
-//purpose : computes selection for flyouts
-//=======================================================================
+ // Compute flyout direction vector.
+ gp_Dir aPlaneNormal = GetPlane().Axis().Direction();
+ gp_Dir aPositiveFlyout = aPlaneNormal ^ aTargetPointsDir;
-void AIS_Dimension::computeFlyoutSelection (const Handle(SelectMgr_Selection)& theSelection,
- const Handle(AIS_DimensionOwner)& 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;
- // Create lines for layouts
- gp_Lin aLine1 (myFirstPoint, aFlyoutVector);
- gp_Lin aLine2 (mySecondPoint, aFlyoutVector);
- // Get flyout end points
- gp_Pnt aFlyoutEnd1 = ElCLib::Value (ElCLib::Parameter (aLine1, myFirstPoint) + GetFlyout(), aLine1);
- gp_Pnt aFlyoutEnd2 = ElCLib::Value (ElCLib::Parameter (aLine2, mySecondPoint) + GetFlyout(), aLine2);
-
- // Fill sensitive entity for flyouts
- Handle(Select3D_SensitiveGroup) aSensitiveEntity = new Select3D_SensitiveGroup (theOwner);
- aSensitiveEntity->Add (new Select3D_SensitiveSegment (theOwner, myFirstPoint, aFlyoutEnd1));
- aSensitiveEntity->Add (new Select3D_SensitiveSegment (theOwner, mySecondPoint, aFlyoutEnd2));
- theSelection->Add (aSensitiveEntity);
+ // Additional check of collinearity of the plane normal and attachment points vector.
+ if (aPlaneNormal.IsParallel (aTargetPointsDir, Precision::Angular()))
+ {
+ return Standard_False;
+ }
+
+ // Set flyout.
+ gp_Vec aFirstToTextVec (theFirstPoint, theTextPos);
+
+ Standard_Real aCos = aFirstToTextVec.Normalized() * gp_Vec (aTargetPointsDir);
+
+ gp_Pnt aTextPosProj = theFirstPoint.Translated
+ (gp_Vec (aTargetPointsDir) * aFirstToTextVec.Magnitude() * aCos);
+
+ // Compute flyout value and direction.
+ gp_Vec aFlyoutVector = gp_Vec (aTextPosProj, theTextPos);
+
+ theFlyout = 0.0;
+ if (aFlyoutVector.Magnitude() > Precision::Confusion())
+ {
+ theFlyout = gp_Dir (aFlyoutVector).IsOpposite (aPositiveFlyout, Precision::Angular())
+ ? -aFlyoutVector.Magnitude()
+ : aFlyoutVector.Magnitude();
+ }
+
+ // Compute attach points (through which main dimension line passes).
+ gp_Pnt aFirstAttach = theFirstPoint.Translated (aFlyoutVector);
+ gp_Pnt aSecondAttach = theSecondPoint.Translated (aFlyoutVector);
+
+ // Set horizontal text alignment.
+ if (aCos < 0.0)
+ {
+ theAlignment = Prs3d_DTHP_Left;
+
+ Standard_Real aNewExtSize = theTextPos.Distance (aFirstAttach) - anArrowLength;
+ theExtensionSize = aNewExtSize < 0.0 ? 0.0 : aNewExtSize;
+ }
+ else if (aTextPosProj.Distance (theFirstPoint) > theFirstPoint.Distance (theSecondPoint))
+ {
+ theAlignment = Prs3d_DTHP_Right;
+
+ Standard_Real aNewExtSize = theTextPos.Distance (aSecondAttach) - anArrowLength;
+ theExtensionSize = aNewExtSize < 0.0 ? 0.0 : aNewExtSize;
+ }
+ else
+ {
+ theAlignment = Prs3d_DTHP_Center;
+ }
+ return Standard_True;
}
//=======================================================================
-//function : ComputeSelection
+//function : FitTextAlignmentForLinear
//purpose :
//=======================================================================
-
-void AIS_Dimension::ComputeSelection (const Handle(SelectMgr_Selection)& theSelection,
- const Standard_Integer theMode)
+void AIS_Dimension::FitTextAlignmentForLinear (const gp_Pnt& theFirstPoint,
+ const gp_Pnt& theSecondPoint,
+ const Standard_Boolean theIsOneSide,
+ const Prs3d_DimensionTextHorizontalPosition& theHorizontalTextPos,
+ Standard_Integer& theLabelPosition,
+ Standard_Boolean& theIsArrowsExternal) const
{
- if (!isComputed())
- {
- return;
- }
+ theLabelPosition = LabelPosition_None;
+ theIsArrowsExternal = Standard_False;
+
+ // Compute dimension line points
+ gp_Ax1 aPlaneNormal = GetPlane().Axis();
+ gp_Dir aTargetPointsVector = gce_MakeDir (theFirstPoint, theSecondPoint);
+
+ // compute flyout direction vector
+ gp_Dir aFlyoutVector = aPlaneNormal.Direction() ^ aTargetPointsVector;
+
+ // create lines for layouts
+ gp_Lin aLine1 (theFirstPoint, aFlyoutVector);
+ gp_Lin aLine2 (theSecondPoint, aFlyoutVector);
+
+ // Get flyout end points
+ gp_Pnt aLineBegPoint = ElCLib::Value (ElCLib::Parameter (aLine1, theFirstPoint) + GetFlyout(), aLine1);
+ gp_Pnt aLineEndPoint = ElCLib::Value (ElCLib::Parameter (aLine2, theSecondPoint) + GetFlyout(), aLine2);
+
+ Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
- Handle(Select3D_SensitiveGroup) aSensitiveForLine;
- Handle(Select3D_SensitiveEntity) aSensitiveForText;
- Select3D_ListOfSensitive aSensitiveList;
- aSensitiveList.Assign (myGeom.mySensitiveSegments);
+ // For extensions we need to know arrow size, text size and extension size: get it from aspect
+ Quantity_Length anArrowLength = aDimensionAspect->ArrowAspect()->Length();
+
+ // prepare label string and compute its geometrical width
+ Standard_Real aLabelWidth;
+ TCollection_ExtendedString aLabelString = GetValueString (aLabelWidth);
- // 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())
+ // Add margins to cut dimension lines for 3d text
+ if (aDimensionAspect->IsText3d())
{
- anIt.Value()->Set (anOwner);
+ aLabelWidth += aDimensionAspect->TextAspect()->Height() * THE_3D_TEXT_MARGIN * 2.0;
}
- aSensitiveForLine = new Select3D_SensitiveGroup (anOwner, aSensitiveList);
- // Text
- if (myDrawer->DimensionAspect()->IsText3d())
+ // Handle user-defined and automatic arrow placement
+ switch (aDimensionAspect->ArrowOrientation())
{
- aSensitiveForText = new Select3D_SensitiveBox (anOwner,myGeom.myTextBndBox);
+ case Prs3d_DAO_External: theIsArrowsExternal = true; break;
+ case Prs3d_DAO_Internal: theIsArrowsExternal = 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 = theIsOneSide
+ ? anArrowLength + anArrowMargin
+ : (anArrowLength + anArrowMargin) * 2.0;
+
+ theIsArrowsExternal = aDimensionWidth < aLabelWidth + anArrowsWidth;
+ break;
+ }
}
- else
+
+ // Handle user-defined and automatic text placement
+ switch (theHorizontalTextPos)
{
- 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);
+ 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:
+ {
+ Standard_Real aDimensionWidth = aLineBegPoint.Distance (aLineEndPoint);
+ Standard_Real anArrowsWidth = theIsOneSide ? anArrowLength : 2.0 * anArrowLength;
+ Standard_Real aContentWidth = theIsArrowsExternal ? aLabelWidth : aLabelWidth + anArrowsWidth;
+
+ theLabelPosition |= aDimensionWidth < aContentWidth ? LabelPosition_Left : LabelPosition_HCenter;
+ break;
+ }
}
- if (theMode > 0)
+
+ // Handle vertical text placement options
+ switch (aDimensionAspect->TextVerticalPosition())
{
- anOwner->SetDisplayMode (AIS_DDM_Line);
- Handle(AIS_DimensionOwner) aTextOwner = new AIS_DimensionOwner (this, AIS_DDM_Text, 7);
- aSensitiveForText->Set (aTextOwner);
+ case Prs3d_DTVP_Above : theLabelPosition |= LabelPosition_Above; break;
+ case Prs3d_DTVP_Below : theLabelPosition |= LabelPosition_Below; break;
+ case Prs3d_DTVP_Center : theLabelPosition |= LabelPosition_VCenter; break;
}
- else
- computeFlyoutSelection (theSelection, anOwner);
+}
- theSelection->Add (aSensitiveForLine);
- theSelection->Add (aSensitiveForText);
+//=======================================================================
+//function : UnsetFixedTextPosition
+//purpose :
+//=======================================================================
+void AIS_Dimension::UnsetFixedTextPosition()
+{
+ myIsTextPositionFixed = Standard_False;
+ myFixedTextPosition = gp::Origin();
}