1 // Created on: 1996-12-05
2 // Created by: Arnaud BOUZY/Odile Olivier
3 // Copyright (c) 1996-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
6 // This file is part of Open CASCADE Technology software library.
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
17 #include <AIS_AngleDimension.hxx>
20 #include <AIS_Drawer.hxx>
21 #include <BRepBuilderAPI_MakeFace.hxx>
22 #include <BRepAdaptor_Curve.hxx>
23 #include <BRepAdaptor_Surface.hxx>
24 #include <BRepLib_MakeVertex.hxx>
25 #include <BRep_Tool.hxx>
27 #include <GCPnts_UniformAbscissa.hxx>
28 #include <GC_MakeArcOfCircle.hxx>
29 #include <gce_MakeLin2d.hxx>
30 #include <gce_MakeLin.hxx>
31 #include <gce_MakeCirc.hxx>
32 #include <gce_MakeCone.hxx>
33 #include <gce_MakePln.hxx>
34 #include <gce_MakeDir.hxx>
35 #include <Geom_Circle.hxx>
36 #include <Geom_TrimmedCurve.hxx>
37 #include <Geom_ConicalSurface.hxx>
38 #include <Geom_SurfaceOfRevolution.hxx>
39 #include <Geom_OffsetSurface.hxx>
40 #include <Graphic3d_ArrayOfSegments.hxx>
41 #include <Graphic3d_Group.hxx>
42 #include <Graphic3d_ArrayOfPolylines.hxx>
43 #include <IntAna2d_AnaIntersection.hxx>
44 #include <ProjLib.hxx>
45 #include <Prs3d_Root.hxx>
46 #include <Prs3d_ShadingAspect.hxx>
47 #include <PrsMgr_PresentationManager3d.hxx>
48 #include <Select3D_SensitiveGroup.hxx>
49 #include <Select3D_SensitiveSegment.hxx>
50 #include <SelectMgr_Selection.hxx>
51 #include <Standard_ProgramError.hxx>
52 #include <UnitsAPI.hxx>
54 IMPLEMENT_STANDARD_HANDLE (AIS_AngleDimension, AIS_Dimension)
55 IMPLEMENT_STANDARD_RTTIEXT (AIS_AngleDimension, AIS_Dimension)
59 static const TCollection_ExtendedString THE_EMPTY_LABEL_STRING;
60 static const Standard_Real THE_EMPTY_LABEL_WIDTH = 0.0;
61 static const Standard_ExtCharacter THE_DEGREE_SYMBOL (0x00B0);
62 static const Standard_Real THE_3D_TEXT_MARGIN = 0.1;
65 //=======================================================================
66 //function : Constructor
68 //=======================================================================
69 AIS_AngleDimension::AIS_AngleDimension (const TopoDS_Edge& theFirstEdge,
70 const TopoDS_Edge& theSecondEdge)
71 : AIS_Dimension (AIS_KOD_PLANEANGLE)
74 SetMeasuredGeometry (theFirstEdge, theSecondEdge);
77 //=======================================================================
78 //function : Constructor
80 //=======================================================================
81 AIS_AngleDimension::AIS_AngleDimension (const gp_Pnt& theFirstPoint,
82 const gp_Pnt& theSecondPoint,
83 const gp_Pnt& theThirdPoint)
84 : AIS_Dimension (AIS_KOD_PLANEANGLE)
87 SetMeasuredGeometry (theFirstPoint, theSecondPoint, theThirdPoint);
90 //=======================================================================
91 //function : Constructor
93 //=======================================================================
94 AIS_AngleDimension::AIS_AngleDimension (const TopoDS_Vertex& theFirstVertex,
95 const TopoDS_Vertex& theSecondVertex,
96 const TopoDS_Vertex& theThirdVertex)
97 : AIS_Dimension (AIS_KOD_PLANEANGLE)
100 SetMeasuredGeometry (theFirstVertex, theSecondVertex, theThirdVertex);
103 //=======================================================================
104 //function : Constructor
106 //=======================================================================
107 AIS_AngleDimension::AIS_AngleDimension (const TopoDS_Face& theCone)
108 : AIS_Dimension (AIS_KOD_PLANEANGLE)
111 SetMeasuredGeometry (theCone);
114 //=======================================================================
115 //function : Constructor
117 //=======================================================================
118 AIS_AngleDimension::AIS_AngleDimension (const TopoDS_Face& theFirstFace,
119 const TopoDS_Face& theSecondFace)
120 : AIS_Dimension (AIS_KOD_PLANEANGLE)
123 SetMeasuredGeometry (theFirstFace, theSecondFace);
126 //=======================================================================
127 //function : Constructor
129 //=======================================================================
130 AIS_AngleDimension::AIS_AngleDimension (const TopoDS_Face& theFirstFace,
131 const TopoDS_Face& theSecondFace,
132 const gp_Pnt& thePoint)
133 : AIS_Dimension (AIS_KOD_PLANEANGLE)
136 SetMeasuredGeometry (theFirstFace, theSecondFace, thePoint);
139 //=======================================================================
140 //function : SetMeasuredGeometry
142 //=======================================================================
143 void AIS_AngleDimension::SetMeasuredGeometry (const TopoDS_Edge& theFirstEdge,
144 const TopoDS_Edge& theSecondEdge)
146 gp_Pln aComputedPlane;
148 myFirstShape = theFirstEdge;
149 mySecondShape = theSecondEdge;
150 myThirdShape = TopoDS_Shape();
151 myGeometryType = GeometryType_Edges;
152 myIsValid = InitTwoEdgesAngle (aComputedPlane);
154 if (myIsValid && !myIsPlaneCustom)
159 myIsValid &= CheckPlane (myPlane);
164 //=======================================================================
165 //function : SetMeasuredGeometry
167 //=======================================================================
168 void AIS_AngleDimension::SetMeasuredGeometry (const gp_Pnt& theFirstPoint,
169 const gp_Pnt& theSecondPoint,
170 const gp_Pnt& theThirdPoint)
172 myFirstPoint = theFirstPoint;
173 myCenterPoint = theSecondPoint;
174 mySecondPoint = theThirdPoint;
175 myFirstShape = BRepLib_MakeVertex (myFirstPoint);
176 mySecondShape = BRepLib_MakeVertex (myCenterPoint);
177 myThirdShape = BRepLib_MakeVertex (mySecondPoint);
178 myGeometryType = GeometryType_Points;
179 myIsValid = IsValidPoints (myFirstPoint, myCenterPoint, mySecondPoint);
181 if (myIsValid && !myIsPlaneCustom)
186 myIsValid &= CheckPlane (myPlane);
191 //=======================================================================
192 //function : SetMeasuredGeometry
194 //=======================================================================
195 void AIS_AngleDimension::SetMeasuredGeometry (const TopoDS_Vertex& theFirstVertex,
196 const TopoDS_Vertex& theSecondVertex,
197 const TopoDS_Vertex& theThirdVertex)
199 myFirstShape = theFirstVertex;
200 mySecondShape = theSecondVertex;
201 myThirdShape = theThirdVertex;
202 myFirstPoint = BRep_Tool::Pnt (theFirstVertex);
203 myCenterPoint = BRep_Tool::Pnt (theSecondVertex);
204 mySecondPoint = BRep_Tool::Pnt (theThirdVertex);
205 myGeometryType = GeometryType_Points;
206 myIsValid = IsValidPoints (myFirstPoint, myCenterPoint, mySecondPoint);
208 if (myIsValid && !myIsPlaneCustom)
213 myIsValid &= CheckPlane (myPlane);
218 //=======================================================================
219 //function : SetMeasuredGeometry
221 //=======================================================================
222 void AIS_AngleDimension::SetMeasuredGeometry (const TopoDS_Face& theCone)
224 myFirstShape = theCone;
225 mySecondShape = TopoDS_Shape();
226 myThirdShape = TopoDS_Shape();
227 myGeometryType = GeometryType_Face;
228 myIsValid = InitConeAngle();
230 if (myIsValid && !myIsPlaneCustom)
235 myIsValid &= CheckPlane (myPlane);
240 //=======================================================================
241 //function : SetMeasuredGeometry
243 //=======================================================================
244 void AIS_AngleDimension::SetMeasuredGeometry (const TopoDS_Face& theFirstFace,
245 const TopoDS_Face& theSecondFace)
247 myFirstShape = theFirstFace;
248 mySecondShape = theSecondFace;
249 myThirdShape = TopoDS_Shape();
250 myGeometryType = GeometryType_Faces;
251 myIsValid = InitTwoFacesAngle();
253 if (myIsValid && !myIsPlaneCustom)
258 myIsValid &= CheckPlane (myPlane);
263 //=======================================================================
264 //function : SetMeasuredGeometry
266 //=======================================================================
267 void AIS_AngleDimension::SetMeasuredGeometry (const TopoDS_Face& theFirstFace,
268 const TopoDS_Face& theSecondFace,
269 const gp_Pnt& thePoint)
271 myFirstShape = theFirstFace;
272 mySecondShape = theSecondFace;
273 myThirdShape = TopoDS_Shape();
274 myGeometryType = GeometryType_Faces;
275 myIsValid = InitTwoFacesAngle (thePoint);
277 if (myIsValid && !myIsPlaneCustom)
282 myIsValid &= CheckPlane (myPlane);
287 //=======================================================================
290 //=======================================================================
291 void AIS_AngleDimension::Init()
293 SetSpecialSymbol (THE_DEGREE_SYMBOL);
294 SetDisplaySpecialSymbol (AIS_DSS_After);
298 //=======================================================================
299 //function: GetCenterOnArc
301 //=======================================================================
302 gp_Pnt AIS_AngleDimension::GetCenterOnArc (const gp_Pnt& theFirstAttach,
303 const gp_Pnt& theSecondAttach,
304 const gp_Pnt& theCenter) const
306 // construct plane where the circle and the arc are located
307 gce_MakePln aConstructPlane (theFirstAttach, theSecondAttach, theCenter);
308 if (!aConstructPlane.IsDone())
313 gp_Pln aPlane = aConstructPlane.Value();
315 Standard_Real aRadius = theFirstAttach.Distance (theCenter);
317 // construct circle forming the arc
318 gce_MakeCirc aConstructCircle (theCenter, aPlane, aRadius);
319 if (!aConstructCircle.IsDone())
324 gp_Circ aCircle = aConstructCircle.Value();
326 // compute angle parameters of arc end-points on circle
327 Standard_Real aParamBeg = ElCLib::Parameter (aCircle, theFirstAttach);
328 Standard_Real aParamEnd = ElCLib::Parameter (aCircle, theSecondAttach);
329 ElCLib::AdjustPeriodic (0.0, M_PI * 2, Precision::PConfusion(), aParamBeg, aParamEnd);
331 return ElCLib::Value ((aParamBeg + aParamEnd) * 0.5, aCircle);
334 //=======================================================================
336 //purpose : draws the arc between two attach points
337 //=======================================================================
338 void AIS_AngleDimension::DrawArc (const Handle(Prs3d_Presentation)& thePresentation,
339 const gp_Pnt& theFirstAttach,
340 const gp_Pnt& theSecondAttach,
341 const gp_Pnt& theCenter,
342 const Standard_Real theRadius,
343 const Standard_Integer theMode)
345 // construct plane where the circle and the arc are located
346 gce_MakePln aConstructPlane (theFirstAttach, theSecondAttach, theCenter);
347 if (!aConstructPlane.IsDone())
352 gp_Pln aPlane = aConstructPlane.Value();
354 // construct circle forming the arc
355 gce_MakeCirc aConstructCircle (theCenter, aPlane, theRadius);
356 if (!aConstructCircle.IsDone())
361 gp_Circ aCircle = aConstructCircle.Value();
364 GC_MakeArcOfCircle aConstructArc (aCircle, theFirstAttach, theSecondAttach, Standard_True);
365 if (!aConstructArc.IsDone())
370 // generate points with specified deflection
371 const Handle(Geom_TrimmedCurve)& anArcCurve = aConstructArc.Value();
373 GeomAdaptor_Curve anArcAdaptor (anArcCurve, anArcCurve->FirstParameter(), anArcCurve->LastParameter());
375 // compute number of discretization elements in old-fanshioned way
376 gp_Vec aCenterToFirstVec (theCenter, theFirstAttach);
377 gp_Vec aCenterToSecondVec (theCenter, theSecondAttach);
378 const Standard_Real anAngle = aCenterToFirstVec.Angle (aCenterToSecondVec);
379 const Standard_Integer aNbPoints = Max (4, Standard_Integer (50.0 * anAngle / M_PI));
381 GCPnts_UniformAbscissa aMakePnts (anArcAdaptor, aNbPoints);
382 if (!aMakePnts.IsDone())
387 // init data arrays for graphical and selection primitives
388 Handle(Graphic3d_ArrayOfPolylines) aPrimSegments = new Graphic3d_ArrayOfPolylines (aNbPoints);
390 SelectionGeometry::Curve& aSensitiveCurve = mySelectionGeom.NewCurve();
392 // load data into arrays
393 for (Standard_Integer aPntIt = 1; aPntIt <= aMakePnts.NbPoints(); ++aPntIt)
395 gp_Pnt aPnt = anArcAdaptor.Value (aMakePnts.Parameter (aPntIt));
397 aPrimSegments->AddVertex (aPnt);
399 aSensitiveCurve.Append (aPnt);
402 // add display presentation
403 if (!myDrawer->DimensionAspect()->IsText3d() && theMode == ComputeMode_All)
405 Prs3d_Root::CurrentGroup (thePresentation)->SetStencilTestOptions (Standard_True);
407 Handle(Graphic3d_AspectLine3d) aDimensionLineStyle = myDrawer->DimensionAspect()->LineAspect()->Aspect();
408 Prs3d_Root::CurrentGroup (thePresentation)->SetPrimitivesAspect (aDimensionLineStyle);
409 Prs3d_Root::CurrentGroup (thePresentation)->AddPrimitiveArray (aPrimSegments);
410 if (!myDrawer->DimensionAspect()->IsText3d() && theMode == ComputeMode_All)
412 Prs3d_Root::CurrentGroup (thePresentation)->SetStencilTestOptions (Standard_False);
416 //=======================================================================
417 //function: DrawArcWithText
419 //=======================================================================
420 void AIS_AngleDimension::DrawArcWithText (const Handle(Prs3d_Presentation)& thePresentation,
421 const gp_Pnt& theFirstAttach,
422 const gp_Pnt& theSecondAttach,
423 const gp_Pnt& theCenter,
424 const TCollection_ExtendedString& theText,
425 const Standard_Real theTextWidth,
426 const Standard_Integer theMode,
427 const Standard_Integer theLabelPosition)
429 // construct plane where the circle and the arc are located
430 gce_MakePln aConstructPlane (theFirstAttach, theSecondAttach, theCenter);
431 if (!aConstructPlane.IsDone())
436 gp_Pln aPlane = aConstructPlane.Value();
438 Standard_Real aRadius = theFirstAttach.Distance (myCenterPoint);
440 // construct circle forming the arc
441 gce_MakeCirc aConstructCircle (theCenter, aPlane, aRadius);
442 if (!aConstructCircle.IsDone())
447 gp_Circ aCircle = aConstructCircle.Value();
449 // compute angle parameters of arc end-points on circle
450 Standard_Real aParamBeg = ElCLib::Parameter (aCircle, theFirstAttach);
451 Standard_Real aParamEnd = ElCLib::Parameter (aCircle, theSecondAttach);
452 ElCLib::AdjustPeriodic (0.0, M_PI * 2, Precision::PConfusion(), aParamBeg, aParamEnd);
454 // middle point of arc parameter on circle
455 Standard_Real aParamMid = (aParamBeg + aParamEnd) * 0.5;
457 // add text graphical primitives
458 if (theMode == ComputeMode_All || theMode == ComputeMode_Text)
460 gp_Pnt aTextPos = ElCLib::Value (aParamMid, aCircle);
461 gp_Dir aTextDir = gce_MakeDir (theFirstAttach, theSecondAttach);
464 DrawText (thePresentation,
471 if (theMode != ComputeMode_All && theMode != ComputeMode_Line)
476 Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
478 Standard_Boolean isLineBreak = aDimensionAspect->TextVerticalPosition() == Prs3d_DTVP_Center
479 && aDimensionAspect->IsText3d();
483 // compute gap for label as parameteric size of sector on circle segment
484 Standard_Real aSectorOnCircle = theTextWidth / aRadius;
486 gp_Pnt aTextPntBeg = ElCLib::Value (aParamMid - aSectorOnCircle * 0.5, aCircle);
487 gp_Pnt aTextPntEnd = ElCLib::Value (aParamMid + aSectorOnCircle * 0.5, aCircle);
490 DrawArc (thePresentation, theFirstAttach, aTextPntBeg, theCenter, aRadius, theMode);
491 DrawArc (thePresentation, theSecondAttach, aTextPntEnd, theCenter, aRadius, theMode);
495 DrawArc (thePresentation, theFirstAttach, theSecondAttach, theCenter, aRadius, theMode);
499 //=======================================================================
500 //function : CheckPlane
502 //=======================================================================
503 Standard_Boolean AIS_AngleDimension::CheckPlane (const gp_Pln& thePlane)const
505 if (!thePlane.Contains (myFirstPoint, Precision::Confusion()) &&
506 !thePlane.Contains (mySecondPoint, Precision::Confusion()) &&
507 !thePlane.Contains (myCenterPoint, Precision::Confusion()))
509 return Standard_False;
512 return Standard_True;
515 //=======================================================================
516 //function : ComputePlane
518 //=======================================================================
519 void AIS_AngleDimension::ComputePlane()
526 gp_Vec aFirstVec = gp_Vec (myCenterPoint, myFirstPoint).Normalized();
527 gp_Vec aSecondVec = gp_Vec (myCenterPoint, mySecondPoint).Normalized();
528 gp_Vec aDirectionN = aSecondVec.Crossed (aFirstVec).Normalized();
529 gp_Vec aDirectionY = (aFirstVec + aSecondVec).Normalized();
530 gp_Vec aDirectionX = aDirectionY.Crossed (aDirectionN).Normalized();
532 myPlane = gp_Pln (gp_Ax3 (myCenterPoint, gp_Dir (aDirectionN), gp_Dir (aDirectionX)));
535 //=======================================================================
536 //function : GetModelUnits
538 //=======================================================================
539 const TCollection_AsciiString& AIS_AngleDimension::GetModelUnits() const
541 return myDrawer->DimAngleModelUnits();
544 //=======================================================================
545 //function : GetDisplayUnits
547 //=======================================================================
548 const TCollection_AsciiString& AIS_AngleDimension::GetDisplayUnits() const
550 return myDrawer->DimAngleDisplayUnits();
553 //=======================================================================
554 //function : SetModelUnits
556 //=======================================================================
557 void AIS_AngleDimension::SetModelUnits (const TCollection_AsciiString& theUnits)
559 myDrawer->SetDimAngleModelUnits (theUnits);
562 //=======================================================================
563 //function : SetDisplayUnits
565 //=======================================================================
566 void AIS_AngleDimension::SetDisplayUnits (const TCollection_AsciiString& theUnits)
568 myDrawer->SetDimAngleDisplayUnits (theUnits);
571 //=======================================================================
572 //function : ComputeValue
574 //=======================================================================
575 Standard_Real AIS_AngleDimension::ComputeValue() const
582 gp_Vec aVec1 (myCenterPoint, myFirstPoint);
583 gp_Vec aVec2 (myCenterPoint, mySecondPoint);
585 Standard_Real anAngle = aVec2.AngleWithRef (aVec1, GetPlane().Axis().Direction());
587 return anAngle > 0.0 ? anAngle : (2.0 * M_PI + anAngle);
590 //=======================================================================
592 //purpose : Having three gp_Pnt points compute presentation
593 //=======================================================================
594 void AIS_AngleDimension::Compute (const Handle(PrsMgr_PresentationManager3d)& /*thePM*/,
595 const Handle(Prs3d_Presentation)& thePresentation,
596 const Standard_Integer theMode)
598 thePresentation->Clear();
599 mySelectionGeom.Clear (theMode);
606 // Parameters for presentation
607 Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
609 Prs3d_Root::CurrentGroup(thePresentation)->SetPrimitivesAspect (aDimensionAspect->LineAspect()->Aspect());
611 Quantity_Length anArrowLength = aDimensionAspect->ArrowAspect()->Length();
613 // prepare label string and compute its geometrical width
614 Standard_Real aLabelWidth;
615 TCollection_ExtendedString aLabelString = GetValueString (aLabelWidth);
617 // add margins to label width
618 if (aDimensionAspect->IsText3d())
620 aLabelWidth += aDimensionAspect->TextAspect()->Height() * THE_3D_TEXT_MARGIN * 2.0;
623 // Get parameters from aspect or adjust it according with custom text position
624 Standard_Real anExtensionSize = aDimensionAspect->ExtensionSize();
625 Prs3d_DimensionTextHorizontalPosition aHorisontalTextPos = aDimensionAspect->TextHorizontalPosition();
627 if (IsTextPositionCustom())
629 AdjustParameters (myFixedTextPosition,anExtensionSize, aHorisontalTextPos);
632 // Handle user-defined and automatic arrow placement
633 Standard_Boolean isArrowsExternal = Standard_False;
634 Standard_Integer aLabelPosition = LabelPosition_None;
636 FitTextAlignment (aHorisontalTextPos, aLabelPosition, isArrowsExternal);
638 gp_Pnt aFirstAttach = myCenterPoint.Translated (gp_Vec(myCenterPoint, myFirstPoint).Normalized() * GetFlyout());
639 gp_Pnt aSecondAttach = myCenterPoint.Translated (gp_Vec(myCenterPoint, mySecondPoint).Normalized() * GetFlyout());
641 //Arrows positions and directions
642 gp_Vec aWPDir = gp_Vec (GetPlane().Axis().Direction());
644 gp_Dir aFirstExtensionDir = aWPDir ^ gp_Vec (myCenterPoint, aFirstAttach);
645 gp_Dir aSecondExtensionDir = aWPDir.Reversed() ^ gp_Vec (myCenterPoint, aSecondAttach);
647 gp_Vec aFirstArrowVec = gp_Vec (aFirstExtensionDir) * anArrowLength;
648 gp_Vec aSecondArrowVec = gp_Vec (aSecondExtensionDir) * anArrowLength;
650 gp_Pnt aFirstArrowBegin (0.0, 0.0, 0.0);
651 gp_Pnt aFirstArrowEnd (0.0, 0.0, 0.0);
652 gp_Pnt aSecondArrowBegin (0.0, 0.0, 0.0);
653 gp_Pnt aSecondArrowEnd (0.0, 0.0, 0.0);
655 if (isArrowsExternal)
657 aFirstArrowVec.Reverse();
658 aSecondArrowVec.Reverse();
661 aFirstArrowBegin = aFirstAttach;
662 aSecondArrowBegin = aSecondAttach;
663 aFirstArrowEnd = aFirstAttach.Translated (-aFirstArrowVec);
664 aSecondArrowEnd = aSecondAttach.Translated (-aSecondArrowVec);
666 // Group1: stenciling text and the angle dimension arc
667 Prs3d_Root::NewGroup (thePresentation);
669 Standard_Integer aHPosition = aLabelPosition & LabelPosition_HMask;
674 case LabelPosition_HCenter :
676 Standard_Boolean isLineBreak = aDimensionAspect->TextVerticalPosition() == Prs3d_DTVP_Center
677 && aDimensionAspect->IsText3d();
681 DrawArcWithText (thePresentation,
692 // compute text primitives
693 if (theMode == ComputeMode_All || theMode == ComputeMode_Text)
695 gp_Vec aDimensionDir (aFirstAttach, aSecondAttach);
696 gp_Pnt aTextPos = IsTextPositionCustom() ? myFixedTextPosition
697 : GetCenterOnArc (aFirstAttach, aSecondAttach, myCenterPoint);
698 gp_Dir aTextDir = aDimensionDir;
700 DrawText (thePresentation,
707 if (theMode == ComputeMode_All || theMode == ComputeMode_Line)
709 DrawArc (thePresentation,
710 isArrowsExternal ? aFirstAttach : aFirstArrowEnd,
711 isArrowsExternal ? aSecondAttach : aSecondArrowEnd,
719 case LabelPosition_Left :
721 DrawExtension (thePresentation,
723 isArrowsExternal ? aFirstArrowEnd : aFirstAttach,
732 case LabelPosition_Right :
734 DrawExtension (thePresentation,
736 isArrowsExternal ? aSecondArrowEnd : aSecondAttach,
746 // dimension arc without text
747 if ((theMode == ComputeMode_All || theMode == ComputeMode_Line) && aHPosition != LabelPosition_HCenter)
749 Prs3d_Root::NewGroup (thePresentation);
751 DrawArc (thePresentation,
752 isArrowsExternal ? aFirstAttach : aFirstArrowEnd,
753 isArrowsExternal ? aSecondAttach : aSecondArrowEnd,
759 // arrows and arrow extensions
760 if (theMode == ComputeMode_All || theMode == ComputeMode_Line)
762 Prs3d_Root::NewGroup (thePresentation);
764 DrawArrow (thePresentation, aFirstArrowBegin, gp_Dir (aFirstArrowVec));
765 DrawArrow (thePresentation, aSecondArrowBegin, gp_Dir (aSecondArrowVec));
768 if ((theMode == ComputeMode_All || theMode == ComputeMode_Line) && isArrowsExternal)
770 Prs3d_Root::NewGroup (thePresentation);
772 if (aHPosition != LabelPosition_Left)
774 DrawExtension (thePresentation,
775 aDimensionAspect->ArrowTailSize(),
778 THE_EMPTY_LABEL_STRING,
779 THE_EMPTY_LABEL_WIDTH,
784 if (aHPosition != LabelPosition_Right)
786 DrawExtension (thePresentation,
787 aDimensionAspect->ArrowTailSize(),
790 THE_EMPTY_LABEL_STRING,
791 THE_EMPTY_LABEL_WIDTH,
798 if (theMode == ComputeMode_All)
800 Prs3d_Root::NewGroup (thePresentation);
802 Handle(Graphic3d_ArrayOfSegments) aPrimSegments = new Graphic3d_ArrayOfSegments (4);
803 aPrimSegments->AddVertex (myCenterPoint);
804 aPrimSegments->AddVertex (aFirstAttach);
805 aPrimSegments->AddVertex (myCenterPoint);
806 aPrimSegments->AddVertex (aSecondAttach);
808 Handle(Graphic3d_AspectLine3d) aFlyoutStyle = myDrawer->DimensionAspect()->LineAspect()->Aspect();
809 Prs3d_Root::CurrentGroup (thePresentation)->SetPrimitivesAspect (aFlyoutStyle);
810 Prs3d_Root::CurrentGroup (thePresentation)->AddPrimitiveArray (aPrimSegments);
813 myIsComputed = Standard_True;
816 //=======================================================================
817 //function : ComputeFlyoutSelection
818 //purpose : computes selection for flyouts
819 //=======================================================================
820 void AIS_AngleDimension::ComputeFlyoutSelection (const Handle(SelectMgr_Selection)& theSelection,
821 const Handle(SelectMgr_EntityOwner)& theOwner)
823 gp_Pnt aFirstAttach = myCenterPoint.Translated (gp_Vec (myCenterPoint, myFirstPoint).Normalized() * GetFlyout());
824 gp_Pnt aSecondAttach = myCenterPoint.Translated (gp_Vec (myCenterPoint, mySecondPoint).Normalized() * GetFlyout());
826 Handle(Select3D_SensitiveGroup) aSensitiveEntity = new Select3D_SensitiveGroup (theOwner);
827 aSensitiveEntity->Add (new Select3D_SensitiveSegment (theOwner, myCenterPoint, aFirstAttach));
828 aSensitiveEntity->Add (new Select3D_SensitiveSegment (theOwner, myCenterPoint, aSecondAttach));
830 theSelection->Add (aSensitiveEntity);
833 //=======================================================================
834 //function : InitTwoEdgesAngle
836 //=======================================================================
837 Standard_Boolean AIS_AngleDimension::InitTwoEdgesAngle (gp_Pln& theComputedPlane)
839 TopoDS_Edge aFirstEdge = TopoDS::Edge (myFirstShape);
840 TopoDS_Edge aSecondEdge = TopoDS::Edge (mySecondShape);
842 BRepAdaptor_Curve aMakeFirstLine (aFirstEdge);
843 BRepAdaptor_Curve aMakeSecondLine (aSecondEdge);
845 if (aMakeFirstLine.GetType() != GeomAbs_Line || aMakeSecondLine.GetType() != GeomAbs_Line)
847 return Standard_False;
850 Handle(Geom_Line) aFirstLine = new Geom_Line (aMakeFirstLine.Line());
851 Handle(Geom_Line) aSecondLine = new Geom_Line (aMakeSecondLine.Line());
853 gp_Lin aFirstLin = aFirstLine->Lin();
854 gp_Lin aSecondLin = aSecondLine->Lin();
856 Standard_Boolean isParallelLines = Abs (aFirstLin.Angle (aSecondLin) - M_PI) <= Precision::Angular();
858 gp_Pnt aPoint = aFirstLine->Value (0.0);
859 gp_Dir aNormal = isParallelLines
860 ? gp_Vec (aSecondLin.Normal (aPoint).Direction()) ^ gp_Vec (aSecondLin.Direction())
861 : gp_Vec (aFirstLin.Direction()) ^ gp_Vec (aSecondLin.Direction());
863 theComputedPlane = gp_Pln (aPoint, aNormal);
865 // Compute geometry for this plane and edges
866 Standard_Boolean isInfinite1,isInfinite2;
867 gp_Pnt aFirstPoint1, aLastPoint1, aFirstPoint2, aLastPoint2;
868 gp_Lin2d aFirstLin2d, aSecondLin2d;
870 if (!AIS::ComputeGeometry (aFirstEdge, aSecondEdge,
871 aFirstLine, aSecondLine,
872 aFirstPoint1, aLastPoint1,
873 aFirstPoint2, aLastPoint2,
874 isInfinite1, isInfinite2))
876 return Standard_False;
879 if (aFirstLin.Direction().IsParallel (aSecondLin.Direction(), Precision::Angular()))
881 myFirstPoint = aFirstLin.Location();
882 mySecondPoint = ElCLib::Value (ElCLib::Parameter (aFirstLin, myFirstPoint), aSecondLin);
884 if (mySecondPoint.Distance (myFirstPoint) <= Precision::Confusion())
886 mySecondPoint.Translate (gp_Vec (aSecondLin.Direction()) * Abs (GetFlyout()));
889 myCenterPoint.SetXYZ ((myFirstPoint.XYZ() + mySecondPoint.XYZ()) / 2.0);
894 gp_Lin2d aFirstLin2d = ProjLib::Project (theComputedPlane, aFirstLin);
895 gp_Lin2d aSecondLin2d = ProjLib::Project (theComputedPlane, aSecondLin);
897 IntAna2d_AnaIntersection anInt2d (aFirstLin2d, aSecondLin2d);
898 gp_Pnt2d anIntersectPoint;
899 if (!anInt2d.IsDone() || anInt2d.IsEmpty())
901 return Standard_False;
904 anIntersectPoint = gp_Pnt2d (anInt2d.Point(1).Value());
905 myCenterPoint = ElCLib::To3d (theComputedPlane.Position().Ax2(), anIntersectPoint);
907 if (isInfinite1 || isInfinite2)
909 myFirstPoint = myCenterPoint.Translated (gp_Vec (aFirstLin.Direction()) * Abs (GetFlyout()));
910 mySecondPoint = myCenterPoint.Translated (gp_Vec (aSecondLin.Direction()) * Abs (GetFlyout()));
912 return IsValidPoints (myFirstPoint, myCenterPoint, mySecondPoint);
916 // | <- dimension should be here
918 myFirstPoint = myCenterPoint.Distance (aFirstPoint1) > myCenterPoint.Distance (aLastPoint1)
922 mySecondPoint = myCenterPoint.Distance (aFirstPoint2) > myCenterPoint.Distance (aLastPoint2)
927 return IsValidPoints (myFirstPoint, myCenterPoint, mySecondPoint);
930 //=======================================================================
931 //function : InitTwoFacesAngle
932 //purpose : initialization of angle dimension between two faces
933 //=======================================================================
934 Standard_Boolean AIS_AngleDimension::InitTwoFacesAngle()
936 TopoDS_Face aFirstFace = TopoDS::Face (myFirstShape);
937 TopoDS_Face aSecondFace = TopoDS::Face (mySecondShape);
939 gp_Dir aFirstDir, aSecondDir;
940 gp_Pln aFirstPlane, aSecondPlane;
941 Handle(Geom_Surface) aFirstBasisSurf, aSecondBasisSurf;
942 AIS_KindOfSurface aFirstSurfType, aSecondSurfType;
943 Standard_Real aFirstOffset, aSecondOffset;
945 AIS::GetPlaneFromFace (aFirstFace, aFirstPlane,
946 aFirstBasisSurf,aFirstSurfType,aFirstOffset);
948 AIS::GetPlaneFromFace (aSecondFace, aSecondPlane,
949 aSecondBasisSurf, aSecondSurfType, aSecondOffset);
951 if (aFirstSurfType == AIS_KOS_Plane && aSecondSurfType == AIS_KOS_Plane)
954 Handle(Geom_Plane) aFirstPlane = Handle(Geom_Plane)::DownCast (aFirstBasisSurf);
955 Handle(Geom_Plane) aSecondPlane = Handle(Geom_Plane)::DownCast (aSecondBasisSurf);
956 return AIS::InitAngleBetweenPlanarFaces (aFirstFace,
961 && IsValidPoints (myFirstPoint,
967 // Curvilinear faces angle
968 return AIS::InitAngleBetweenCurvilinearFaces (aFirstFace,
975 && IsValidPoints (myFirstPoint,
981 //=======================================================================
982 //function : InitTwoFacesAngle
983 //purpose : initialization of angle dimension between two faces
984 //=======================================================================
985 Standard_Boolean AIS_AngleDimension::InitTwoFacesAngle (const gp_Pnt thePointOnFirstFace)
987 TopoDS_Face aFirstFace = TopoDS::Face (myFirstShape);
988 TopoDS_Face aSecondFace = TopoDS::Face (mySecondShape);
990 gp_Dir aFirstDir, aSecondDir;
991 gp_Pln aFirstPlane, aSecondPlane;
992 Handle(Geom_Surface) aFirstBasisSurf, aSecondBasisSurf;
993 AIS_KindOfSurface aFirstSurfType, aSecondSurfType;
994 Standard_Real aFirstOffset, aSecondOffset;
996 AIS::GetPlaneFromFace (aFirstFace, aFirstPlane,
997 aFirstBasisSurf,aFirstSurfType,aFirstOffset);
999 AIS::GetPlaneFromFace (aSecondFace, aSecondPlane,
1000 aSecondBasisSurf, aSecondSurfType, aSecondOffset);
1002 myFirstPoint = thePointOnFirstFace;
1003 if (aFirstSurfType == AIS_KOS_Plane && aSecondSurfType == AIS_KOS_Plane)
1005 //Planar faces angle
1006 Handle(Geom_Plane) aFirstPlane = Handle(Geom_Plane)::DownCast (aFirstBasisSurf);
1007 Handle(Geom_Plane) aSecondPlane = Handle(Geom_Plane)::DownCast (aSecondBasisSurf);
1008 return AIS::InitAngleBetweenPlanarFaces (aFirstFace,
1014 && IsValidPoints (myFirstPoint,
1020 // Curvilinear faces angle
1021 return AIS::InitAngleBetweenCurvilinearFaces (aFirstFace,
1029 && IsValidPoints (myFirstPoint,
1035 //=======================================================================
1036 //function : InitConeAngle
1037 //purpose : initialization of the cone angle
1038 //=======================================================================
1039 Standard_Boolean AIS_AngleDimension::InitConeAngle()
1041 if (myFirstShape.IsNull())
1043 return Standard_False;
1046 TopoDS_Face aConeShape = TopoDS::Face (myFirstShape);
1050 // A surface from the Face
1051 Handle(Geom_Surface) aSurf;
1052 Handle(Geom_OffsetSurface) aOffsetSurf;
1053 Handle(Geom_ConicalSurface) aConicalSurf;
1054 Handle(Geom_SurfaceOfRevolution) aRevSurf;
1055 Handle(Geom_Line) aLine;
1056 BRepAdaptor_Surface aConeAdaptor (aConeShape);
1058 AIS_KindOfSurface aSurfType;
1059 Standard_Real anOffset = 0.;
1060 Handle(Standard_Type) aType;
1062 Standard_Real aMaxV = aConeAdaptor.FirstVParameter();
1063 Standard_Real aMinV = aConeAdaptor.LastVParameter();
1065 AIS::GetPlaneFromFace (aConeShape, aPln, aSurf, aSurfType, anOffset);
1067 if (aSurfType == AIS_KOS_Revolution)
1069 // Surface of revolution
1070 aRevSurf = Handle(Geom_SurfaceOfRevolution)::DownCast(aSurf);
1071 gp_Lin aLin (aRevSurf->Axis());
1072 Handle(Geom_Curve) aBasisCurve = aRevSurf->BasisCurve();
1073 //Must be a part of line (basis curve should be linear)
1074 if (aBasisCurve ->DynamicType() != STANDARD_TYPE(Geom_Line))
1075 return Standard_False;
1077 gp_Pnt aFirst1 = aConeAdaptor.Value (0., aMinV);
1078 gp_Pnt aLast1 = aConeAdaptor.Value (0., aMaxV);
1079 gp_Vec aVec1 (aFirst1, aLast1);
1081 //Projection <aFirst> on <aLin>
1082 gp_Pnt aFirst2 = ElCLib::Value (ElCLib::Parameter (aLin, aFirst1), aLin);
1083 // Projection <aLast> on <aLin>
1084 gp_Pnt aLast2 = ElCLib::Value (ElCLib::Parameter (aLin, aLast1), aLin);
1086 gp_Vec aVec2 (aFirst2, aLast2);
1088 // Check if two parts of revolution are parallel (it's a cylinder) or normal (it's a circle).
1089 if (aVec1.IsParallel (aVec2, Precision::Angular())
1090 || aVec1.IsNormal (aVec2,Precision::Angular()))
1091 return Standard_False;
1093 gce_MakeCone aMkCone (aRevSurf->Axis(), aFirst1, aLast1);
1094 aCone = aMkCone.Value();
1095 myCenterPoint = aCone.Apex();
1099 aType = aSurf->DynamicType();
1100 if (aType == STANDARD_TYPE(Geom_OffsetSurface) || anOffset > 0.01)
1103 aOffsetSurf = new Geom_OffsetSurface (aSurf, anOffset);
1104 aSurf = aOffsetSurf->Surface();
1105 BRepBuilderAPI_MakeFace aMkFace(aSurf, Precision::Confusion());
1107 if (!aMkFace.IsDone())
1108 return Standard_False;
1109 aConeAdaptor.Initialize (aMkFace.Face());
1111 aCone = aConeAdaptor.Cone();
1112 aConicalSurf = Handle(Geom_ConicalSurface)::DownCast (aSurf);
1113 myCenterPoint = aConicalSurf->Apex();
1116 // A circle where the angle is drawn
1117 Handle(Geom_Curve) aCurve;
1118 Standard_Real aMidV = ( aMinV + aMaxV ) / 2.5;
1119 aCurve = aSurf->VIso (aMidV);
1120 aCircle = Handle(Geom_Circle)::DownCast (aCurve)->Circ();
1122 aCurve = aSurf->VIso(aMaxV);
1123 gp_Circ aCircVmax = Handle(Geom_Circle)::DownCast(aCurve)->Circ();
1124 aCurve = aSurf->VIso(aMinV);
1125 gp_Circ aCircVmin = Handle(Geom_Circle)::DownCast(aCurve)->Circ();
1127 if (aCircVmax.Radius() < aCircVmin.Radius())
1129 gp_Circ aTmpCirc = aCircVmax;
1130 aCircVmax = aCircVmin;
1131 aCircVmin = aTmpCirc;
1134 myFirstPoint = ElCLib::Value (0, aCircle);
1135 mySecondPoint = ElCLib::Value (M_PI, aCircle);
1136 return Standard_True;
1139 //=======================================================================
1140 //function : IsValidPoints
1142 //=======================================================================
1143 Standard_Boolean AIS_AngleDimension::IsValidPoints (const gp_Pnt& theFirstPoint,
1144 const gp_Pnt& theCenterPoint,
1145 const gp_Pnt& theSecondPoint) const
1147 return theFirstPoint.Distance (theCenterPoint) > Precision::Confusion()
1148 && theSecondPoint.Distance (theCenterPoint) > Precision::Confusion()
1149 && gp_Vec (theCenterPoint, theFirstPoint).Angle (
1150 gp_Vec (theCenterPoint, theSecondPoint)) > Precision::Angular();
1153 //=======================================================================
1154 //function : GetTextPosition
1156 //=======================================================================
1157 const gp_Pnt AIS_AngleDimension::GetTextPosition() const
1161 return gp::Origin();
1164 if (IsTextPositionCustom())
1166 return myFixedTextPosition;
1169 // Counts text position according to the dimension parameters
1170 gp_Pnt aTextPosition (gp::Origin());
1172 Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
1174 // Prepare label string and compute its geometrical width
1175 Standard_Real aLabelWidth;
1176 TCollection_ExtendedString aLabelString = GetValueString (aLabelWidth);
1178 gp_Pnt aFirstAttach = myCenterPoint.Translated (gp_Vec(myCenterPoint, myFirstPoint).Normalized() * GetFlyout());
1179 gp_Pnt aSecondAttach = myCenterPoint.Translated (gp_Vec(myCenterPoint, mySecondPoint).Normalized() * GetFlyout());
1181 // Handle user-defined and automatic arrow placement
1182 Standard_Boolean isArrowsExternal = Standard_False;
1183 Standard_Integer aLabelPosition = LabelPosition_None;
1184 FitTextAlignment (aDimensionAspect->TextHorizontalPosition(),
1185 aLabelPosition, isArrowsExternal);
1187 // Get text position
1188 switch (aLabelPosition & LabelPosition_HMask)
1190 case LabelPosition_HCenter:
1192 aTextPosition = GetCenterOnArc (aFirstAttach, aSecondAttach, myCenterPoint);
1195 case LabelPosition_Left:
1197 gp_Dir aPlaneNormal = gp_Vec (aFirstAttach, aSecondAttach) ^ gp_Vec (myCenterPoint, aFirstAttach);
1198 gp_Dir anExtensionDir = aPlaneNormal ^ gp_Vec (myCenterPoint, aFirstAttach);
1199 Standard_Real anExtensionSize = aDimensionAspect->ExtensionSize();
1200 Standard_Real anOffset = isArrowsExternal
1201 ? anExtensionSize + aDimensionAspect->ArrowAspect()->Length()
1203 gp_Vec anExtensionVec = gp_Vec (anExtensionDir) * -anOffset;
1204 aTextPosition = aFirstAttach.Translated (anExtensionVec);
1207 case LabelPosition_Right:
1209 gp_Dir aPlaneNormal = gp_Vec (aFirstAttach, aSecondAttach) ^ gp_Vec (myCenterPoint, aFirstAttach);
1210 gp_Dir anExtensionDir = aPlaneNormal ^ gp_Vec (myCenterPoint, aSecondAttach);
1211 Standard_Real anExtensionSize = aDimensionAspect->ExtensionSize();
1212 Standard_Real anOffset = isArrowsExternal
1213 ? anExtensionSize + aDimensionAspect->ArrowAspect()->Length()
1215 gp_Vec anExtensionVec = gp_Vec (anExtensionDir) * anOffset;
1216 aTextPosition = aSecondAttach.Translated (anExtensionVec);
1221 return aTextPosition;
1224 //=======================================================================
1225 //function : SetTextPosition
1227 //=======================================================================
1228 void AIS_AngleDimension::SetTextPosition (const gp_Pnt& theTextPos)
1235 // The text position point for angle dimension should belong to the working plane.
1236 if (!GetPlane().Contains (theTextPos, Precision::Confusion()))
1238 Standard_ProgramError::Raise ("The text position point for angle dimension doesn't belong to the working plane.");
1241 myIsTextPositionFixed = Standard_True;
1242 myFixedTextPosition = theTextPos;
1245 //=======================================================================
1246 //function : AdjustAspectParameters
1248 //=======================================================================
1249 void AIS_AngleDimension::AdjustParameters (const gp_Pnt& theTextPos,
1250 Standard_Real& theExtensionSize,
1251 Prs3d_DimensionTextHorizontalPosition& theAlignment)
1253 Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
1254 Standard_Real anArrowLength = aDimensionAspect->ArrowAspect()->Length();
1256 // Compute flyout direction vector.
1257 gp_Dir aPlaneNormal = GetPlane().Axis().Direction();
1258 gp_Dir aTargetPointsDir = gce_MakeDir (myFirstPoint, mySecondPoint);
1260 // Build circle with radius that is equal to distance from text position to the center point.
1261 Standard_Real aRadius = gp_Vec (myCenterPoint, theTextPos).Magnitude();
1263 // Set attach points in positive direction of the flyout.
1264 gp_Pnt aFirstAttach = myCenterPoint.Translated (gp_Vec (myCenterPoint, myFirstPoint).Normalized() * aRadius);
1265 gp_Pnt aSecondAttach = myCenterPoint.Translated (gp_Vec (myCenterPoint, mySecondPoint).Normalized() * aRadius);
1267 gce_MakeCirc aConstructCircle (myCenterPoint, GetPlane(), aRadius);
1268 if (!aConstructCircle.IsDone())
1272 gp_Circ aCircle = aConstructCircle.Value();
1275 theExtensionSize = aDimensionAspect->ArrowAspect()->Length();
1276 theAlignment = Prs3d_DTHP_Center;
1278 Standard_Real aParamBeg = ElCLib::Parameter (aCircle, aFirstAttach);
1279 Standard_Real aParamEnd = ElCLib::Parameter (aCircle, aSecondAttach);
1280 if (aParamEnd < aParamBeg)
1282 Standard_Real aParam = aParamEnd;
1283 aParamEnd = aParamBeg;
1287 ElCLib::AdjustPeriodic (0.0, M_PI * 2, Precision::PConfusion(), aParamBeg, aParamEnd);
1288 Standard_Real aTextPar = ElCLib::Parameter (aCircle , theTextPos);
1290 // Horizontal center
1291 if (aTextPar > aParamBeg && aTextPar < aParamEnd)
1301 ElCLib::AdjustPeriodic (0.0, M_PI * 2, Precision::PConfusion(), aParamBeg, aParamEnd);
1303 if (aTextPar > aParamBeg && aTextPar < aParamEnd)
1305 myFlyout = -aRadius;
1311 // Text on the extensions
1312 gp_Lin aFirstLine = gce_MakeLin (myCenterPoint, myFirstPoint);
1313 gp_Lin aSecondLine = gce_MakeLin (myCenterPoint, mySecondPoint);
1314 gp_Pnt aFirstTextProj = AIS::Nearest (aFirstLine, theTextPos);
1315 gp_Pnt aSecondTextProj = AIS::Nearest (aSecondLine, theTextPos);
1316 Standard_Real aFirstDist = aFirstTextProj.Distance (theTextPos);
1317 Standard_Real aSecondDist = aSecondTextProj.Distance (theTextPos);
1319 if (aFirstDist <= aSecondDist)
1321 aRadius = myCenterPoint.Distance (aFirstTextProj);
1322 Standard_Real aNewExtensionSize = aFirstDist - anArrowLength;
1323 theExtensionSize = aNewExtensionSize < 0.0 ? 0.0 : aNewExtensionSize;
1325 theAlignment = Prs3d_DTHP_Left;
1327 gp_Vec aPosFlyoutDir = gp_Vec (myCenterPoint, myFirstPoint).Normalized().Scaled (aRadius);
1329 myFlyout = aFirstTextProj.Distance (myCenterPoint.Translated (aPosFlyoutDir)) > Precision::Confusion()
1330 ? -aRadius : aRadius;
1334 aRadius = myCenterPoint.Distance (aSecondTextProj);
1336 Standard_Real aNewExtensionSize = aSecondDist - anArrowLength;
1338 theExtensionSize = aNewExtensionSize < 0.0 ? 0.0 : aNewExtensionSize;
1340 theAlignment = Prs3d_DTHP_Right;
1342 gp_Vec aPosFlyoutDir = gp_Vec (myCenterPoint, mySecondPoint).Normalized().Scaled (aRadius);
1344 myFlyout = aSecondTextProj.Distance (myCenterPoint.Translated (aPosFlyoutDir)) > Precision::Confusion()
1345 ? -aRadius : aRadius;
1349 //=======================================================================
1350 //function : FitTextAlignment
1352 //=======================================================================
1353 void AIS_AngleDimension::FitTextAlignment (const Prs3d_DimensionTextHorizontalPosition& theHorizontalTextPos,
1354 Standard_Integer& theLabelPosition,
1355 Standard_Boolean& theIsArrowsExternal) const
1357 Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
1359 Quantity_Length anArrowLength = aDimensionAspect->ArrowAspect()->Length();
1361 // Prepare label string and compute its geometrical width
1362 Standard_Real aLabelWidth;
1363 TCollection_ExtendedString aLabelString = GetValueString (aLabelWidth);
1365 // add margins to label width
1366 if (aDimensionAspect->IsText3d())
1368 aLabelWidth += aDimensionAspect->TextAspect()->Height() * THE_3D_TEXT_MARGIN * 2.0;
1371 gp_Pnt aFirstAttach = myCenterPoint.Translated (gp_Vec (myCenterPoint, myFirstPoint).Normalized() * GetFlyout());
1372 gp_Pnt aSecondAttach = myCenterPoint.Translated (gp_Vec (myCenterPoint, mySecondPoint).Normalized() * GetFlyout());
1374 // Handle user-defined and automatic arrow placement
1375 switch (aDimensionAspect->ArrowOrientation())
1377 case Prs3d_DAO_External: theIsArrowsExternal = true; break;
1378 case Prs3d_DAO_Internal: theIsArrowsExternal = false; break;
1381 gp_Vec anAttachVector (aFirstAttach, aSecondAttach);
1382 Standard_Real aDimensionWidth = anAttachVector.Magnitude();
1384 // Add margin to ensure a small tail between text and arrow
1385 Standard_Real anArrowMargin = aDimensionAspect->IsText3d()
1386 ? aDimensionAspect->TextAspect()->Height() * THE_3D_TEXT_MARGIN
1389 Standard_Real anArrowsWidth = (anArrowLength + anArrowMargin) * 2.0;
1391 theIsArrowsExternal = aDimensionWidth < aLabelWidth + anArrowsWidth;
1396 // Handle user-defined and automatic text placement
1397 switch (theHorizontalTextPos)
1399 case Prs3d_DTHP_Left : theLabelPosition |= LabelPosition_Left; break;
1400 case Prs3d_DTHP_Right : theLabelPosition |= LabelPosition_Right; break;
1401 case Prs3d_DTHP_Center: theLabelPosition |= LabelPosition_HCenter; break;
1402 case Prs3d_DTHP_Fit:
1404 gp_Vec anAttachVector (aFirstAttach, aSecondAttach);
1405 Standard_Real aDimensionWidth = anAttachVector.Magnitude();
1406 Standard_Real anArrowsWidth = anArrowLength * 2.0;
1407 Standard_Real aContentWidth = theIsArrowsExternal ? aLabelWidth : aLabelWidth + anArrowsWidth;
1409 theLabelPosition |= aDimensionWidth < aContentWidth ? LabelPosition_Left : LabelPosition_HCenter;
1414 switch (aDimensionAspect->TextVerticalPosition())
1416 case Prs3d_DTVP_Above : theLabelPosition |= LabelPosition_Above; break;
1417 case Prs3d_DTVP_Below : theLabelPosition |= LabelPosition_Below; break;
1418 case Prs3d_DTVP_Center : theLabelPosition |= LabelPosition_VCenter; break;