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 <BRepBuilderAPI_MakeFace.hxx>
21 #include <BRepAdaptor_Curve.hxx>
22 #include <BRepAdaptor_Surface.hxx>
23 #include <BRepLib_MakeVertex.hxx>
24 #include <BRep_Tool.hxx>
26 #include <GCPnts_UniformAbscissa.hxx>
27 #include <GC_MakeArcOfCircle.hxx>
28 #include <gce_MakeLin2d.hxx>
29 #include <gce_MakeLin.hxx>
30 #include <gce_MakeCirc.hxx>
31 #include <gce_MakeCone.hxx>
32 #include <gce_MakePln.hxx>
33 #include <gce_MakeDir.hxx>
34 #include <Geom_Circle.hxx>
35 #include <Geom_TrimmedCurve.hxx>
36 #include <Geom_ConicalSurface.hxx>
37 #include <Geom_SurfaceOfRevolution.hxx>
38 #include <Geom_OffsetSurface.hxx>
39 #include <Graphic3d_ArrayOfSegments.hxx>
40 #include <Graphic3d_Group.hxx>
41 #include <Graphic3d_ArrayOfPolylines.hxx>
42 #include <IntAna2d_AnaIntersection.hxx>
43 #include <ProjLib.hxx>
44 #include <Prs3d_Root.hxx>
45 #include <Prs3d_ShadingAspect.hxx>
46 #include <PrsMgr_PresentationManager3d.hxx>
47 #include <Select3D_SensitiveGroup.hxx>
48 #include <Select3D_SensitiveSegment.hxx>
49 #include <SelectMgr_Selection.hxx>
50 #include <Standard_ProgramError.hxx>
51 #include <UnitsAPI.hxx>
53 IMPLEMENT_STANDARD_HANDLE (AIS_AngleDimension, AIS_Dimension)
54 IMPLEMENT_STANDARD_RTTIEXT (AIS_AngleDimension, AIS_Dimension)
58 static const TCollection_ExtendedString THE_EMPTY_LABEL_STRING;
59 static const Standard_Real THE_EMPTY_LABEL_WIDTH = 0.0;
60 static const Standard_ExtCharacter THE_DEGREE_SYMBOL (0x00B0);
61 static const Standard_Real THE_3D_TEXT_MARGIN = 0.1;
64 //=======================================================================
65 //function : Constructor
67 //=======================================================================
68 AIS_AngleDimension::AIS_AngleDimension (const TopoDS_Edge& theFirstEdge,
69 const TopoDS_Edge& theSecondEdge)
70 : AIS_Dimension (AIS_KOD_PLANEANGLE)
73 SetMeasuredGeometry (theFirstEdge, theSecondEdge);
76 //=======================================================================
77 //function : Constructor
79 //=======================================================================
80 AIS_AngleDimension::AIS_AngleDimension (const gp_Pnt& theFirstPoint,
81 const gp_Pnt& theSecondPoint,
82 const gp_Pnt& theThirdPoint)
83 : AIS_Dimension (AIS_KOD_PLANEANGLE)
86 SetMeasuredGeometry (theFirstPoint, theSecondPoint, theThirdPoint);
89 //=======================================================================
90 //function : Constructor
92 //=======================================================================
93 AIS_AngleDimension::AIS_AngleDimension (const TopoDS_Vertex& theFirstVertex,
94 const TopoDS_Vertex& theSecondVertex,
95 const TopoDS_Vertex& theThirdVertex)
96 : AIS_Dimension (AIS_KOD_PLANEANGLE)
99 SetMeasuredGeometry (theFirstVertex, theSecondVertex, theThirdVertex);
102 //=======================================================================
103 //function : Constructor
105 //=======================================================================
106 AIS_AngleDimension::AIS_AngleDimension (const TopoDS_Face& theCone)
107 : AIS_Dimension (AIS_KOD_PLANEANGLE)
110 SetMeasuredGeometry (theCone);
113 //=======================================================================
114 //function : Constructor
116 //=======================================================================
117 AIS_AngleDimension::AIS_AngleDimension (const TopoDS_Face& theFirstFace,
118 const TopoDS_Face& theSecondFace)
119 : AIS_Dimension (AIS_KOD_PLANEANGLE)
122 SetMeasuredGeometry (theFirstFace, theSecondFace);
125 //=======================================================================
126 //function : Constructor
128 //=======================================================================
129 AIS_AngleDimension::AIS_AngleDimension (const TopoDS_Face& theFirstFace,
130 const TopoDS_Face& theSecondFace,
131 const gp_Pnt& thePoint)
132 : AIS_Dimension (AIS_KOD_PLANEANGLE)
135 SetMeasuredGeometry (theFirstFace, theSecondFace, thePoint);
138 //=======================================================================
139 //function : SetMeasuredGeometry
141 //=======================================================================
142 void AIS_AngleDimension::SetMeasuredGeometry (const TopoDS_Edge& theFirstEdge,
143 const TopoDS_Edge& theSecondEdge)
145 gp_Pln aComputedPlane;
147 myFirstShape = theFirstEdge;
148 mySecondShape = theSecondEdge;
149 myThirdShape = TopoDS_Shape();
150 myGeometryType = GeometryType_Edges;
151 myIsGeometryValid = InitTwoEdgesAngle (aComputedPlane);
153 if (myIsGeometryValid && !myIsPlaneCustom)
161 //=======================================================================
162 //function : SetMeasuredGeometry
164 //=======================================================================
165 void AIS_AngleDimension::SetMeasuredGeometry (const gp_Pnt& theFirstPoint,
166 const gp_Pnt& theSecondPoint,
167 const gp_Pnt& theThirdPoint)
169 myFirstPoint = theFirstPoint;
170 myCenterPoint = theSecondPoint;
171 mySecondPoint = theThirdPoint;
172 myFirstShape = BRepLib_MakeVertex (myFirstPoint);
173 mySecondShape = BRepLib_MakeVertex (myCenterPoint);
174 myThirdShape = BRepLib_MakeVertex (mySecondPoint);
175 myGeometryType = GeometryType_Points;
176 myIsGeometryValid = IsValidPoints (myFirstPoint, myCenterPoint, mySecondPoint);
178 if (myIsGeometryValid && !myIsPlaneCustom)
186 //=======================================================================
187 //function : SetMeasuredGeometry
189 //=======================================================================
190 void AIS_AngleDimension::SetMeasuredGeometry (const TopoDS_Vertex& theFirstVertex,
191 const TopoDS_Vertex& theSecondVertex,
192 const TopoDS_Vertex& theThirdVertex)
194 myFirstShape = theFirstVertex;
195 mySecondShape = theSecondVertex;
196 myThirdShape = theThirdVertex;
197 myFirstPoint = BRep_Tool::Pnt (theFirstVertex);
198 myCenterPoint = BRep_Tool::Pnt (theSecondVertex);
199 mySecondPoint = BRep_Tool::Pnt (theThirdVertex);
200 myGeometryType = GeometryType_Points;
201 myIsGeometryValid = IsValidPoints (myFirstPoint, myCenterPoint, mySecondPoint);
203 if (myIsGeometryValid && !myIsPlaneCustom)
211 //=======================================================================
212 //function : SetMeasuredGeometry
214 //=======================================================================
215 void AIS_AngleDimension::SetMeasuredGeometry (const TopoDS_Face& theCone)
217 myFirstShape = theCone;
218 mySecondShape = TopoDS_Shape();
219 myThirdShape = TopoDS_Shape();
220 myGeometryType = GeometryType_Face;
221 myIsGeometryValid = InitConeAngle();
223 if (myIsGeometryValid && !myIsPlaneCustom)
231 //=======================================================================
232 //function : SetMeasuredGeometry
234 //=======================================================================
235 void AIS_AngleDimension::SetMeasuredGeometry (const TopoDS_Face& theFirstFace,
236 const TopoDS_Face& theSecondFace)
238 myFirstShape = theFirstFace;
239 mySecondShape = theSecondFace;
240 myThirdShape = TopoDS_Shape();
241 myGeometryType = GeometryType_Faces;
242 myIsGeometryValid = InitTwoFacesAngle();
244 if (myIsGeometryValid && !myIsPlaneCustom)
252 //=======================================================================
253 //function : SetMeasuredGeometry
255 //=======================================================================
256 void AIS_AngleDimension::SetMeasuredGeometry (const TopoDS_Face& theFirstFace,
257 const TopoDS_Face& theSecondFace,
258 const gp_Pnt& thePoint)
260 myFirstShape = theFirstFace;
261 mySecondShape = theSecondFace;
262 myThirdShape = TopoDS_Shape();
263 myGeometryType = GeometryType_Faces;
264 myIsGeometryValid = InitTwoFacesAngle (thePoint);
266 if (myIsGeometryValid && !myIsPlaneCustom)
274 //=======================================================================
277 //=======================================================================
278 void AIS_AngleDimension::Init()
280 SetGeometryOrientedAngle (Standard_False, Standard_False);
281 SetArrowVisible(Standard_True, Standard_True);
282 SetSpecialSymbol (THE_DEGREE_SYMBOL);
283 SetDisplaySpecialSymbol (AIS_DSS_After);
287 //=======================================================================
288 //function: GetCenterOnArc
290 //=======================================================================
291 gp_Pnt AIS_AngleDimension::GetCenterOnArc (const gp_Pnt& theFirstAttach,
292 const gp_Pnt& theSecondAttach,
293 const gp_Pnt& theCenter) const
295 // construct plane where the circle and the arc are located
296 gce_MakePln aConstructPlane (theFirstAttach, theSecondAttach, theCenter);
297 if (!aConstructPlane.IsDone())
302 gp_Pln aPlane = aConstructPlane.Value();
304 Standard_Real aRadius = theFirstAttach.Distance (theCenter);
306 // construct circle forming the arc
307 gce_MakeCirc aConstructCircle (theCenter, aPlane, aRadius);
308 if (!aConstructCircle.IsDone())
313 gp_Circ aCircle = aConstructCircle.Value();
315 // compute angle parameters of arc end-points on circle
316 Standard_Real aParamBeg = ElCLib::Parameter (aCircle, theFirstAttach);
317 Standard_Real aParamEnd = ElCLib::Parameter (aCircle, theSecondAttach);
318 ElCLib::AdjustPeriodic (0.0, M_PI * 2, Precision::PConfusion(), aParamBeg, aParamEnd);
320 return ElCLib::Value ((aParamBeg + aParamEnd) * 0.5, aCircle);
323 //=======================================================================
325 //purpose : draws the arc between two attach points
326 //=======================================================================
327 void AIS_AngleDimension::DrawArc (const Handle(Prs3d_Presentation)& thePresentation,
328 const gp_Pnt& theFirstAttach,
329 const gp_Pnt& theSecondAttach,
330 const gp_Pnt& theCenter,
331 const Standard_Real theRadius,
332 const Standard_Integer theMode)
334 // construct plane where the circle and the arc are located
335 gce_MakePln aConstructPlane (theFirstAttach, theSecondAttach, theCenter);
336 if (!aConstructPlane.IsDone())
341 gp_Pln aPlane = aConstructPlane.Value();
342 if (myGeometryOrientedAngle) {
343 gp_Dir aCPlaneDir = GetPlane().Axis().Direction();
344 bool aCPlaneDirToReverse = !(aCPlaneDir.X() < 0 || aCPlaneDir.Y() < 0 || aCPlaneDir.Z() < 0);
345 // have similar direction for all cases
346 if (!aCPlaneDirToReverse && myUseReverse) {
347 gp_Ax1 anAxis = aPlane.Axis();
348 gp_Dir aDir = anAxis.Direction();
350 aPlane.SetAxis(gp_Ax1(anAxis.Location(), aDir));
353 if (aCPlaneDirToReverse && !myUseReverse) {
354 gp_Ax1 anAxis = aPlane.Axis();
355 gp_Dir aDir = anAxis.Direction();
357 aPlane.SetAxis(gp_Ax1(anAxis.Location(), aDir));
361 // construct circle forming the arc
362 gce_MakeCirc aConstructCircle (theCenter, aPlane, theRadius);
363 if (!aConstructCircle.IsDone())
368 gp_Circ aCircle = aConstructCircle.Value();
371 GC_MakeArcOfCircle aConstructArc(aCircle, theFirstAttach, theSecondAttach, Standard_True);
372 if (!aConstructArc.IsDone())
377 // generate points with specified deflection
378 const Handle(Geom_TrimmedCurve)& anArcCurve = aConstructArc.Value();
380 GeomAdaptor_Curve anArcAdaptor (anArcCurve, anArcCurve->FirstParameter(), anArcCurve->LastParameter());
382 // compute number of discretization elements in old-fanshioned way
383 gp_Vec aCenterToFirstVec (theCenter, theFirstAttach);
384 gp_Vec aCenterToSecondVec (theCenter, theSecondAttach);
385 const Standard_Real anAngle = aCenterToFirstVec.Angle (aCenterToSecondVec);
386 const Standard_Integer aNbPoints = myGeometryOrientedAngle ? 40 :
387 Max (4, Standard_Integer (50.0 * anAngle / M_PI));
389 GCPnts_UniformAbscissa aMakePnts (anArcAdaptor, aNbPoints);
390 if (!aMakePnts.IsDone())
395 // init data arrays for graphical and selection primitives
396 Handle(Graphic3d_ArrayOfPolylines) aPrimSegments = new Graphic3d_ArrayOfPolylines (aNbPoints);
398 SelectionGeometry::Curve& aSensitiveCurve = mySelectionGeom.NewCurve();
400 // load data into arrays
401 for (Standard_Integer aPntIt = 1; aPntIt <= aMakePnts.NbPoints(); ++aPntIt)
403 gp_Pnt aPnt = anArcAdaptor.Value (aMakePnts.Parameter (aPntIt));
405 aPrimSegments->AddVertex (aPnt);
407 aSensitiveCurve.Append (aPnt);
410 // add display presentation
411 if (!myDrawer->DimensionAspect()->IsText3d() && theMode == ComputeMode_All)
413 Prs3d_Root::CurrentGroup (thePresentation)->SetStencilTestOptions (Standard_True);
415 Handle(Graphic3d_AspectLine3d) aDimensionLineStyle = myDrawer->DimensionAspect()->LineAspect()->Aspect();
416 Prs3d_Root::CurrentGroup (thePresentation)->SetPrimitivesAspect (aDimensionLineStyle);
417 Prs3d_Root::CurrentGroup (thePresentation)->AddPrimitiveArray (aPrimSegments);
418 if (!myDrawer->DimensionAspect()->IsText3d() && theMode == ComputeMode_All)
420 Prs3d_Root::CurrentGroup (thePresentation)->SetStencilTestOptions (Standard_False);
424 //=======================================================================
425 //function: DrawArcWithText
427 //=======================================================================
428 void AIS_AngleDimension::DrawArcWithText (const Handle(Prs3d_Presentation)& thePresentation,
429 const gp_Pnt& theFirstAttach,
430 const gp_Pnt& theSecondAttach,
431 const gp_Pnt& theCenter,
432 const TCollection_ExtendedString& theText,
433 const Standard_Real theTextWidth,
434 const Standard_Integer theMode,
435 const Standard_Integer theLabelPosition)
437 // construct plane where the circle and the arc are located
438 gce_MakePln aConstructPlane (theFirstAttach, theSecondAttach, theCenter);
439 if (!aConstructPlane.IsDone())
444 gp_Pln aPlane = aConstructPlane.Value();
446 Standard_Real aRadius = theFirstAttach.Distance (myCenterPoint);
448 // construct circle forming the arc
449 gce_MakeCirc aConstructCircle (theCenter, aPlane, aRadius);
450 if (!aConstructCircle.IsDone())
455 gp_Circ aCircle = aConstructCircle.Value();
457 // compute angle parameters of arc end-points on circle
458 Standard_Real aParamBeg = ElCLib::Parameter (aCircle, theFirstAttach);
459 Standard_Real aParamEnd = ElCLib::Parameter (aCircle, theSecondAttach);
460 ElCLib::AdjustPeriodic (0.0, M_PI * 2, Precision::PConfusion(), aParamBeg, aParamEnd);
462 // middle point of arc parameter on circle
463 Standard_Real aParamMid = (aParamBeg + aParamEnd) * 0.5;
465 // add text graphical primitives
466 if (theMode == ComputeMode_All || theMode == ComputeMode_Text)
468 gp_Pnt aTextPos = ElCLib::Value (aParamMid, aCircle);
469 gp_Dir aTextDir = gce_MakeDir (theFirstAttach, theSecondAttach);
472 DrawText (thePresentation,
479 if (theMode != ComputeMode_All && theMode != ComputeMode_Line)
484 Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
486 Standard_Boolean isLineBreak = aDimensionAspect->TextVerticalPosition() == Prs3d_DTVP_Center
487 && aDimensionAspect->IsText3d();
491 // compute gap for label as parameteric size of sector on circle segment
492 Standard_Real aSectorOnCircle = theTextWidth / aRadius;
494 gp_Pnt aTextPntBeg = ElCLib::Value (aParamMid - aSectorOnCircle * 0.5, aCircle);
495 gp_Pnt aTextPntEnd = ElCLib::Value (aParamMid + aSectorOnCircle * 0.5, aCircle);
498 DrawArc (thePresentation, theFirstAttach, aTextPntBeg, theCenter, aRadius, theMode);
499 DrawArc (thePresentation, theSecondAttach, aTextPntEnd, theCenter, aRadius, theMode);
503 DrawArc (thePresentation, theFirstAttach, theSecondAttach, theCenter, aRadius, theMode);
507 //=======================================================================
508 //function : CheckPlane
510 //=======================================================================
511 Standard_Boolean AIS_AngleDimension::CheckPlane (const gp_Pln& thePlane)const
513 if (!thePlane.Contains (myFirstPoint, Precision::Confusion()) &&
514 !thePlane.Contains (mySecondPoint, Precision::Confusion()) &&
515 !thePlane.Contains (myCenterPoint, Precision::Confusion()))
517 return Standard_False;
520 return Standard_True;
523 //=======================================================================
524 //function : ComputePlane
526 //=======================================================================
527 void AIS_AngleDimension::ComputePlane()
529 if (!myIsGeometryValid)
534 gp_Vec aFirstVec = gp_Vec (myCenterPoint, myFirstPoint).Normalized();
535 gp_Vec aSecondVec = gp_Vec (myCenterPoint, mySecondPoint).Normalized();
536 gp_Vec aDirectionN = aSecondVec.Crossed (aFirstVec).Normalized();
537 gp_Vec aDirectionY = (aFirstVec + aSecondVec).Normalized();
538 gp_Vec aDirectionX = aDirectionY.Crossed (aDirectionN).Normalized();
540 myPlane = gp_Pln (gp_Ax3 (myCenterPoint, gp_Dir (aDirectionN), gp_Dir (aDirectionX)));
543 //=======================================================================
544 //function : GetModelUnits
546 //=======================================================================
547 const TCollection_AsciiString& AIS_AngleDimension::GetModelUnits() const
549 return myDrawer->DimAngleModelUnits();
552 //=======================================================================
553 //function : GetDisplayUnits
555 //=======================================================================
556 const TCollection_AsciiString& AIS_AngleDimension::GetDisplayUnits() const
558 return myDrawer->DimAngleDisplayUnits();
561 //=======================================================================
562 //function : SetModelUnits
564 //=======================================================================
565 void AIS_AngleDimension::SetModelUnits (const TCollection_AsciiString& theUnits)
567 myDrawer->SetDimAngleModelUnits (theUnits);
570 //=======================================================================
571 //function : SetDisplayUnits
573 //=======================================================================
574 void AIS_AngleDimension::SetDisplayUnits (const TCollection_AsciiString& theUnits)
576 myDrawer->SetDimAngleDisplayUnits (theUnits);
579 //=======================================================================
580 //function : ComputeValue
582 //=======================================================================
583 Standard_Real AIS_AngleDimension::ComputeValue() const
590 gp_Vec aVec1 (myCenterPoint, myFirstPoint);
591 gp_Vec aVec2 (myCenterPoint, mySecondPoint);
593 Standard_Real anAngle = aVec2.AngleWithRef (aVec1, GetPlane().Axis().Direction());
595 return anAngle > 0.0 ? anAngle : (2.0 * M_PI + anAngle);
598 //=======================================================================
600 //purpose : Having three gp_Pnt points compute presentation
601 //=======================================================================
602 void AIS_AngleDimension::Compute (const Handle(PrsMgr_PresentationManager3d)& /*thePM*/,
603 const Handle(Prs3d_Presentation)& thePresentation,
604 const Standard_Integer theMode)
606 thePresentation->Clear();
607 mySelectionGeom.Clear (theMode);
614 // Parameters for presentation
615 Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
617 Prs3d_Root::CurrentGroup(thePresentation)->SetPrimitivesAspect (aDimensionAspect->LineAspect()->Aspect());
619 Quantity_Length anArrowLength = aDimensionAspect->ArrowAspect()->Length();
621 // prepare label string and compute its geometrical width
622 Standard_Real aLabelWidth;
623 TCollection_ExtendedString aLabelString = GetValueString (aLabelWidth);
625 // add margins to label width
626 if (aDimensionAspect->IsText3d())
628 aLabelWidth += aDimensionAspect->TextAspect()->Height() * THE_3D_TEXT_MARGIN * 2.0;
631 // Get parameters from aspect or adjust it according with custom text position
632 Standard_Real anExtensionSize = aDimensionAspect->ExtensionSize();
633 Prs3d_DimensionTextHorizontalPosition aHorisontalTextPos = aDimensionAspect->TextHorizontalPosition();
635 if (IsTextPositionCustom())
637 AdjustParameters (myFixedTextPosition,anExtensionSize, aHorisontalTextPos, myFlyout);
640 // Handle user-defined and automatic arrow placement
641 Standard_Boolean isArrowsExternal = Standard_False;
642 Standard_Integer aLabelPosition = LabelPosition_None;
644 FitTextAlignment (aHorisontalTextPos, aLabelPosition, isArrowsExternal);
646 gp_Pnt aFirstAttach = myCenterPoint.Translated (gp_Vec(myCenterPoint, myFirstPoint).Normalized() * GetFlyout());
647 gp_Pnt aSecondAttach = myCenterPoint.Translated (gp_Vec(myCenterPoint, mySecondPoint).Normalized() * GetFlyout());
649 //Arrows positions and directions
650 gp_Vec aWPDir = gp_Vec (GetPlane().Axis().Direction());
652 gp_Dir aFirstExtensionDir = aWPDir ^ gp_Vec (myCenterPoint, aFirstAttach);
653 gp_Dir aSecondExtensionDir = aWPDir.Reversed() ^ gp_Vec (myCenterPoint, aSecondAttach);
655 gp_Vec aFirstArrowVec = gp_Vec (aFirstExtensionDir) * anArrowLength;
656 gp_Vec aSecondArrowVec = gp_Vec (aSecondExtensionDir) * anArrowLength;
658 gp_Pnt aFirstArrowBegin (0.0, 0.0, 0.0);
659 gp_Pnt aFirstArrowEnd (0.0, 0.0, 0.0);
660 gp_Pnt aSecondArrowBegin (0.0, 0.0, 0.0);
661 gp_Pnt aSecondArrowEnd (0.0, 0.0, 0.0);
663 if (isArrowsExternal)
665 aFirstArrowVec.Reverse();
666 aSecondArrowVec.Reverse();
669 aFirstArrowBegin = aFirstAttach;
670 aSecondArrowBegin = aSecondAttach;
671 aFirstArrowEnd = aFirstAttach.Translated (-aFirstArrowVec);
672 aSecondArrowEnd = aSecondAttach.Translated (-aSecondArrowVec);
674 // Group1: stenciling text and the angle dimension arc
675 Prs3d_Root::NewGroup (thePresentation);
677 Standard_Integer aHPosition = aLabelPosition & LabelPosition_HMask;
682 case LabelPosition_HCenter :
684 Standard_Boolean isLineBreak = aDimensionAspect->TextVerticalPosition() == Prs3d_DTVP_Center
685 && aDimensionAspect->IsText3d();
689 DrawArcWithText (thePresentation,
700 // compute text primitives
701 if (theMode == ComputeMode_All || theMode == ComputeMode_Text)
703 gp_Vec aDimensionDir (aFirstAttach, aSecondAttach);
704 gp_Pnt aTextPos = IsTextPositionCustom() ? myFixedTextPosition
705 : GetCenterOnArc (aFirstAttach, aSecondAttach, myCenterPoint);
706 gp_Dir aTextDir = aDimensionDir;
708 DrawText (thePresentation,
715 if (theMode == ComputeMode_All || theMode == ComputeMode_Line)
717 DrawArc (thePresentation,
718 (isArrowsExternal || !myFirstArrowVisible) ? aFirstAttach : aFirstArrowEnd,
719 (isArrowsExternal || !mySecondArrowVisible) ? aSecondAttach : aSecondArrowEnd,
727 case LabelPosition_Left :
729 DrawExtension (thePresentation,
731 (isArrowsExternal && myFirstArrowVisible) ? aFirstArrowEnd : aFirstAttach,
740 case LabelPosition_Right :
742 DrawExtension (thePresentation,
744 (isArrowsExternal && mySecondArrowVisible) ? aSecondArrowEnd : aSecondAttach,
754 // dimension arc without text
755 if ((theMode == ComputeMode_All || theMode == ComputeMode_Line) && aHPosition != LabelPosition_HCenter)
757 Prs3d_Root::NewGroup (thePresentation);
759 DrawArc (thePresentation,
760 (isArrowsExternal || !myFirstArrowVisible) ? aFirstAttach : aFirstArrowEnd,
761 (isArrowsExternal || !mySecondArrowVisible) ? aSecondAttach : aSecondArrowEnd,
767 // arrows and arrow extensions
768 if (theMode == ComputeMode_All || theMode == ComputeMode_Line)
770 Prs3d_Root::NewGroup (thePresentation);
772 if (myFirstArrowVisible)
773 DrawArrow (thePresentation, aFirstArrowBegin, gp_Dir (aFirstArrowVec));
774 if (mySecondArrowVisible)
775 DrawArrow (thePresentation, aSecondArrowBegin, gp_Dir (aSecondArrowVec));
778 if ((theMode == ComputeMode_All || theMode == ComputeMode_Line) && isArrowsExternal)
780 Prs3d_Root::NewGroup (thePresentation);
782 if (aHPosition != LabelPosition_Left && myFirstArrowVisible)
784 DrawExtension (thePresentation,
785 aDimensionAspect->ArrowTailSize(),
788 THE_EMPTY_LABEL_STRING,
789 THE_EMPTY_LABEL_WIDTH,
794 if (aHPosition != LabelPosition_Right && mySecondArrowVisible)
796 DrawExtension (thePresentation,
797 aDimensionAspect->ArrowTailSize(),
800 THE_EMPTY_LABEL_STRING,
801 THE_EMPTY_LABEL_WIDTH,
808 if (theMode == ComputeMode_All)
810 Prs3d_Root::NewGroup (thePresentation);
812 Handle(Graphic3d_ArrayOfSegments) aPrimSegments = new Graphic3d_ArrayOfSegments (4);
813 aPrimSegments->AddVertex (myCenterPoint);
814 aPrimSegments->AddVertex (aFirstAttach);
815 aPrimSegments->AddVertex (myCenterPoint);
816 aPrimSegments->AddVertex (aSecondAttach);
818 Handle(Graphic3d_AspectLine3d) aFlyoutStyle = myDrawer->DimensionAspect()->LineAspect()->Aspect();
819 Prs3d_Root::CurrentGroup (thePresentation)->SetPrimitivesAspect (aFlyoutStyle);
820 Prs3d_Root::CurrentGroup (thePresentation)->AddPrimitiveArray (aPrimSegments);
823 mySelectionGeom.IsComputed = Standard_True;
826 //=======================================================================
827 //function : ComputeFlyoutSelection
828 //purpose : computes selection for flyouts
829 //=======================================================================
830 void AIS_AngleDimension::ComputeFlyoutSelection (const Handle(SelectMgr_Selection)& theSelection,
831 const Handle(SelectMgr_EntityOwner)& theOwner)
833 gp_Pnt aFirstAttach = myCenterPoint.Translated (gp_Vec (myCenterPoint, myFirstPoint).Normalized() * GetFlyout());
834 gp_Pnt aSecondAttach = myCenterPoint.Translated (gp_Vec (myCenterPoint, mySecondPoint).Normalized() * GetFlyout());
836 Handle(Select3D_SensitiveGroup) aSensitiveEntity = new Select3D_SensitiveGroup (theOwner);
837 aSensitiveEntity->Add (new Select3D_SensitiveSegment (theOwner, myCenterPoint, aFirstAttach));
838 aSensitiveEntity->Add (new Select3D_SensitiveSegment (theOwner, myCenterPoint, aSecondAttach));
840 theSelection->Add (aSensitiveEntity);
843 //=======================================================================
844 //function : InitTwoEdgesAngle
846 //=======================================================================
847 Standard_Boolean AIS_AngleDimension::InitTwoEdgesAngle (gp_Pln& theComputedPlane)
849 TopoDS_Edge aFirstEdge = TopoDS::Edge (myFirstShape);
850 TopoDS_Edge aSecondEdge = TopoDS::Edge (mySecondShape);
852 BRepAdaptor_Curve aMakeFirstLine (aFirstEdge);
853 BRepAdaptor_Curve aMakeSecondLine (aSecondEdge);
855 if (aMakeFirstLine.GetType() != GeomAbs_Line || aMakeSecondLine.GetType() != GeomAbs_Line)
857 return Standard_False;
860 Handle(Geom_Line) aFirstLine = new Geom_Line (aMakeFirstLine.Line());
861 Handle(Geom_Line) aSecondLine = new Geom_Line (aMakeSecondLine.Line());
863 gp_Lin aFirstLin = aFirstLine->Lin();
864 gp_Lin aSecondLin = aSecondLine->Lin();
866 Standard_Boolean isParallelLines = Abs (aFirstLin.Angle (aSecondLin) - M_PI) <= Precision::Angular();
868 gp_Pnt aPoint = aFirstLine->Value (0.0);
869 gp_Dir aNormal = isParallelLines
870 ? gp_Vec (aSecondLin.Normal (aPoint).Direction()) ^ gp_Vec (aSecondLin.Direction())
871 : gp_Vec (aFirstLin.Direction()) ^ gp_Vec (aSecondLin.Direction());
873 theComputedPlane = gp_Pln (aPoint, aNormal);
875 // Compute geometry for this plane and edges
876 Standard_Boolean isInfinite1,isInfinite2;
877 gp_Pnt aFirstPoint1, aLastPoint1, aFirstPoint2, aLastPoint2;
878 gp_Lin2d aFirstLin2d, aSecondLin2d;
880 if (!AIS::ComputeGeometry (aFirstEdge, aSecondEdge,
881 aFirstLine, aSecondLine,
882 aFirstPoint1, aLastPoint1,
883 aFirstPoint2, aLastPoint2,
884 isInfinite1, isInfinite2))
886 return Standard_False;
889 if (aFirstLin.Direction().IsParallel (aSecondLin.Direction(), Precision::Angular()))
891 myFirstPoint = aFirstLin.Location();
892 mySecondPoint = ElCLib::Value (ElCLib::Parameter (aFirstLin, myFirstPoint), aSecondLin);
894 if (mySecondPoint.Distance (myFirstPoint) <= Precision::Confusion())
896 mySecondPoint.Translate (gp_Vec (aSecondLin.Direction()) * Abs (GetFlyout()));
899 myCenterPoint.SetXYZ ((myFirstPoint.XYZ() + mySecondPoint.XYZ()) / 2.0);
904 gp_Lin2d aFirstLin2d = ProjLib::Project (theComputedPlane, aFirstLin);
905 gp_Lin2d aSecondLin2d = ProjLib::Project (theComputedPlane, aSecondLin);
907 IntAna2d_AnaIntersection anInt2d (aFirstLin2d, aSecondLin2d);
908 gp_Pnt2d anIntersectPoint;
909 if (!anInt2d.IsDone() || anInt2d.IsEmpty())
911 return Standard_False;
914 anIntersectPoint = gp_Pnt2d (anInt2d.Point(1).Value());
915 myCenterPoint = ElCLib::To3d (theComputedPlane.Position().Ax2(), anIntersectPoint);
917 if (isInfinite1 || isInfinite2)
919 myFirstPoint = myCenterPoint.Translated (gp_Vec (aFirstLin.Direction()) * Abs (GetFlyout()));
920 mySecondPoint = myCenterPoint.Translated (gp_Vec (aSecondLin.Direction()) * Abs (GetFlyout()));
922 return IsValidPoints (myFirstPoint, myCenterPoint, mySecondPoint);
926 // | <- dimension should be here
928 myFirstPoint = myCenterPoint.Distance (aFirstPoint1) > myCenterPoint.Distance (aLastPoint1)
932 mySecondPoint = myCenterPoint.Distance (aFirstPoint2) > myCenterPoint.Distance (aLastPoint2)
937 return IsValidPoints (myFirstPoint, myCenterPoint, mySecondPoint);
940 //=======================================================================
941 //function : InitTwoFacesAngle
942 //purpose : initialization of angle dimension between two faces
943 //=======================================================================
944 Standard_Boolean AIS_AngleDimension::InitTwoFacesAngle()
946 TopoDS_Face aFirstFace = TopoDS::Face (myFirstShape);
947 TopoDS_Face aSecondFace = TopoDS::Face (mySecondShape);
949 gp_Dir aFirstDir, aSecondDir;
950 gp_Pln aFirstPlane, aSecondPlane;
951 Handle(Geom_Surface) aFirstBasisSurf, aSecondBasisSurf;
952 AIS_KindOfSurface aFirstSurfType, aSecondSurfType;
953 Standard_Real aFirstOffset, aSecondOffset;
955 AIS::GetPlaneFromFace (aFirstFace, aFirstPlane,
956 aFirstBasisSurf,aFirstSurfType,aFirstOffset);
958 AIS::GetPlaneFromFace (aSecondFace, aSecondPlane,
959 aSecondBasisSurf, aSecondSurfType, aSecondOffset);
961 if (aFirstSurfType == AIS_KOS_Plane && aSecondSurfType == AIS_KOS_Plane)
964 Handle(Geom_Plane) aFirstPlane = Handle(Geom_Plane)::DownCast (aFirstBasisSurf);
965 Handle(Geom_Plane) aSecondPlane = Handle(Geom_Plane)::DownCast (aSecondBasisSurf);
966 return AIS::InitAngleBetweenPlanarFaces (aFirstFace,
971 && IsValidPoints (myFirstPoint,
977 // Curvilinear faces angle
978 return AIS::InitAngleBetweenCurvilinearFaces (aFirstFace,
985 && IsValidPoints (myFirstPoint,
991 //=======================================================================
992 //function : InitTwoFacesAngle
993 //purpose : initialization of angle dimension between two faces
994 //=======================================================================
995 Standard_Boolean AIS_AngleDimension::InitTwoFacesAngle (const gp_Pnt thePointOnFirstFace)
997 TopoDS_Face aFirstFace = TopoDS::Face (myFirstShape);
998 TopoDS_Face aSecondFace = TopoDS::Face (mySecondShape);
1000 gp_Dir aFirstDir, aSecondDir;
1001 gp_Pln aFirstPlane, aSecondPlane;
1002 Handle(Geom_Surface) aFirstBasisSurf, aSecondBasisSurf;
1003 AIS_KindOfSurface aFirstSurfType, aSecondSurfType;
1004 Standard_Real aFirstOffset, aSecondOffset;
1006 AIS::GetPlaneFromFace (aFirstFace, aFirstPlane,
1007 aFirstBasisSurf,aFirstSurfType,aFirstOffset);
1009 AIS::GetPlaneFromFace (aSecondFace, aSecondPlane,
1010 aSecondBasisSurf, aSecondSurfType, aSecondOffset);
1012 myFirstPoint = thePointOnFirstFace;
1013 if (aFirstSurfType == AIS_KOS_Plane && aSecondSurfType == AIS_KOS_Plane)
1015 //Planar faces angle
1016 Handle(Geom_Plane) aFirstPlane = Handle(Geom_Plane)::DownCast (aFirstBasisSurf);
1017 Handle(Geom_Plane) aSecondPlane = Handle(Geom_Plane)::DownCast (aSecondBasisSurf);
1018 return AIS::InitAngleBetweenPlanarFaces (aFirstFace,
1024 && IsValidPoints (myFirstPoint,
1030 // Curvilinear faces angle
1031 return AIS::InitAngleBetweenCurvilinearFaces (aFirstFace,
1039 && IsValidPoints (myFirstPoint,
1045 //=======================================================================
1046 //function : InitConeAngle
1047 //purpose : initialization of the cone angle
1048 //=======================================================================
1049 Standard_Boolean AIS_AngleDimension::InitConeAngle()
1051 if (myFirstShape.IsNull())
1053 return Standard_False;
1056 TopoDS_Face aConeShape = TopoDS::Face (myFirstShape);
1060 // A surface from the Face
1061 Handle(Geom_Surface) aSurf;
1062 Handle(Geom_OffsetSurface) aOffsetSurf;
1063 Handle(Geom_ConicalSurface) aConicalSurf;
1064 Handle(Geom_SurfaceOfRevolution) aRevSurf;
1065 Handle(Geom_Line) aLine;
1066 BRepAdaptor_Surface aConeAdaptor (aConeShape);
1068 AIS_KindOfSurface aSurfType;
1069 Standard_Real anOffset = 0.;
1070 Handle(Standard_Type) aType;
1072 Standard_Real aMaxV = aConeAdaptor.FirstVParameter();
1073 Standard_Real aMinV = aConeAdaptor.LastVParameter();
1075 AIS::GetPlaneFromFace (aConeShape, aPln, aSurf, aSurfType, anOffset);
1077 if (aSurfType == AIS_KOS_Revolution)
1079 // Surface of revolution
1080 aRevSurf = Handle(Geom_SurfaceOfRevolution)::DownCast(aSurf);
1081 gp_Lin aLin (aRevSurf->Axis());
1082 Handle(Geom_Curve) aBasisCurve = aRevSurf->BasisCurve();
1083 //Must be a part of line (basis curve should be linear)
1084 if (aBasisCurve ->DynamicType() != STANDARD_TYPE(Geom_Line))
1085 return Standard_False;
1087 gp_Pnt aFirst1 = aConeAdaptor.Value (0., aMinV);
1088 gp_Pnt aLast1 = aConeAdaptor.Value (0., aMaxV);
1089 gp_Vec aVec1 (aFirst1, aLast1);
1091 //Projection <aFirst> on <aLin>
1092 gp_Pnt aFirst2 = ElCLib::Value (ElCLib::Parameter (aLin, aFirst1), aLin);
1093 // Projection <aLast> on <aLin>
1094 gp_Pnt aLast2 = ElCLib::Value (ElCLib::Parameter (aLin, aLast1), aLin);
1096 gp_Vec aVec2 (aFirst2, aLast2);
1098 // Check if two parts of revolution are parallel (it's a cylinder) or normal (it's a circle).
1099 if (aVec1.IsParallel (aVec2, Precision::Angular())
1100 || aVec1.IsNormal (aVec2,Precision::Angular()))
1101 return Standard_False;
1103 gce_MakeCone aMkCone (aRevSurf->Axis(), aFirst1, aLast1);
1104 aCone = aMkCone.Value();
1105 myCenterPoint = aCone.Apex();
1109 aType = aSurf->DynamicType();
1110 if (aType == STANDARD_TYPE(Geom_OffsetSurface) || anOffset > 0.01)
1113 aOffsetSurf = new Geom_OffsetSurface (aSurf, anOffset);
1114 aSurf = aOffsetSurf->Surface();
1115 BRepBuilderAPI_MakeFace aMkFace(aSurf, Precision::Confusion());
1117 if (!aMkFace.IsDone())
1118 return Standard_False;
1119 aConeAdaptor.Initialize (aMkFace.Face());
1121 aCone = aConeAdaptor.Cone();
1122 aConicalSurf = Handle(Geom_ConicalSurface)::DownCast (aSurf);
1123 myCenterPoint = aConicalSurf->Apex();
1126 // A circle where the angle is drawn
1127 Handle(Geom_Curve) aCurve;
1128 Standard_Real aMidV = ( aMinV + aMaxV ) / 2.5;
1129 aCurve = aSurf->VIso (aMidV);
1130 aCircle = Handle(Geom_Circle)::DownCast (aCurve)->Circ();
1132 aCurve = aSurf->VIso(aMaxV);
1133 gp_Circ aCircVmax = Handle(Geom_Circle)::DownCast(aCurve)->Circ();
1134 aCurve = aSurf->VIso(aMinV);
1135 gp_Circ aCircVmin = Handle(Geom_Circle)::DownCast(aCurve)->Circ();
1137 if (aCircVmax.Radius() < aCircVmin.Radius())
1139 gp_Circ aTmpCirc = aCircVmax;
1140 aCircVmax = aCircVmin;
1141 aCircVmin = aTmpCirc;
1144 myFirstPoint = ElCLib::Value (0, aCircle);
1145 mySecondPoint = ElCLib::Value (M_PI, aCircle);
1146 return Standard_True;
1149 //=======================================================================
1150 //function : IsValidPoints
1152 //=======================================================================
1153 Standard_Boolean AIS_AngleDimension::IsValidPoints (const gp_Pnt& theFirstPoint,
1154 const gp_Pnt& theCenterPoint,
1155 const gp_Pnt& theSecondPoint) const
1157 return theFirstPoint.Distance (theCenterPoint) > Precision::Confusion()
1158 && theSecondPoint.Distance (theCenterPoint) > Precision::Confusion()
1159 && gp_Vec (theCenterPoint, theFirstPoint).Angle (
1160 gp_Vec (theCenterPoint, theSecondPoint)) > Precision::Angular();
1163 //=======================================================================
1164 //function : GetTextPosition
1166 //=======================================================================
1167 const gp_Pnt AIS_AngleDimension::GetTextPosition() const
1171 return gp::Origin();
1174 if (IsTextPositionCustom())
1176 return myFixedTextPosition;
1179 // Counts text position according to the dimension parameters
1180 gp_Pnt aTextPosition (gp::Origin());
1182 Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
1184 // Prepare label string and compute its geometrical width
1185 Standard_Real aLabelWidth;
1186 TCollection_ExtendedString aLabelString = GetValueString (aLabelWidth);
1188 gp_Pnt aFirstAttach = myCenterPoint.Translated (gp_Vec(myCenterPoint, myFirstPoint).Normalized() * GetFlyout());
1189 gp_Pnt aSecondAttach = myCenterPoint.Translated (gp_Vec(myCenterPoint, mySecondPoint).Normalized() * GetFlyout());
1191 // Handle user-defined and automatic arrow placement
1192 Standard_Boolean isArrowsExternal = Standard_False;
1193 Standard_Integer aLabelPosition = LabelPosition_None;
1194 FitTextAlignment (aDimensionAspect->TextHorizontalPosition(),
1195 aLabelPosition, isArrowsExternal);
1197 // Get text position
1198 switch (aLabelPosition & LabelPosition_HMask)
1200 case LabelPosition_HCenter:
1202 aTextPosition = GetCenterOnArc (aFirstAttach, aSecondAttach, myCenterPoint);
1205 case LabelPosition_Left:
1207 gp_Dir aPlaneNormal = gp_Vec (aFirstAttach, aSecondAttach) ^ gp_Vec (myCenterPoint, aFirstAttach);
1208 gp_Dir anExtensionDir = aPlaneNormal ^ gp_Vec (myCenterPoint, aFirstAttach);
1209 Standard_Real anExtensionSize = aDimensionAspect->ExtensionSize();
1210 Standard_Real anOffset = isArrowsExternal
1211 ? anExtensionSize + aDimensionAspect->ArrowAspect()->Length()
1213 gp_Vec anExtensionVec = gp_Vec (anExtensionDir) * -anOffset;
1214 aTextPosition = aFirstAttach.Translated (anExtensionVec);
1217 case LabelPosition_Right:
1219 gp_Dir aPlaneNormal = gp_Vec (aFirstAttach, aSecondAttach) ^ gp_Vec (myCenterPoint, aFirstAttach);
1220 gp_Dir anExtensionDir = aPlaneNormal ^ gp_Vec (myCenterPoint, aSecondAttach);
1221 Standard_Real anExtensionSize = aDimensionAspect->ExtensionSize();
1222 Standard_Real anOffset = isArrowsExternal
1223 ? anExtensionSize + aDimensionAspect->ArrowAspect()->Length()
1225 gp_Vec anExtensionVec = gp_Vec (anExtensionDir) * anOffset;
1226 aTextPosition = aSecondAttach.Translated (anExtensionVec);
1231 return aTextPosition;
1234 //=======================================================================
1235 //function : SetTextPosition
1237 //=======================================================================
1238 void AIS_AngleDimension::SetTextPosition (const gp_Pnt& theTextPos)
1245 // The text position point for angle dimension should belong to the working plane.
1246 if (!GetPlane().Contains (theTextPos, Precision::Confusion()))
1248 Standard_ProgramError::Raise ("The text position point for angle dimension doesn't belong to the working plane.");
1251 myIsTextPositionFixed = Standard_True;
1252 myFixedTextPosition = theTextPos;
1255 //=======================================================================
1256 //function : SetGeometryOrientedAngle
1258 //=======================================================================
1259 void AIS_AngleDimension::SetGeometryOrientedAngle(const Standard_Boolean& theState,
1260 const Standard_Boolean& theUseReverse)
1262 myGeometryOrientedAngle = theState;
1263 myUseReverse = theUseReverse;
1266 //=======================================================================
1267 //function : SetArrowVisible
1269 //=======================================================================
1270 void AIS_AngleDimension::SetArrowVisible(const Standard_Boolean& theFirstArrowVisible,
1271 const Standard_Boolean& theSecondArrowVisible)
1273 myFirstArrowVisible = theFirstArrowVisible;
1274 mySecondArrowVisible = theSecondArrowVisible;
1277 //=======================================================================
1278 //function : AdjustParameters
1280 //=======================================================================
1281 void AIS_AngleDimension::AdjustParameters (const gp_Pnt& theTextPos,
1282 Standard_Real& theExtensionSize,
1283 Prs3d_DimensionTextHorizontalPosition& theAlignment,
1284 Standard_Real& theFlyout) const
1286 Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
1287 Standard_Real anArrowLength = aDimensionAspect->ArrowAspect()->Length();
1289 // Build circle with radius that is equal to distance from text position to the center point.
1290 Standard_Real aRadius = gp_Vec (myCenterPoint, theTextPos).Magnitude();
1292 // Set attach points in positive direction of the flyout.
1293 gp_Pnt aFirstAttach = myCenterPoint.Translated (gp_Vec (myCenterPoint, myFirstPoint).Normalized() * aRadius);
1294 gp_Pnt aSecondAttach = myCenterPoint.Translated (gp_Vec (myCenterPoint, mySecondPoint).Normalized() * aRadius);
1296 gce_MakeCirc aConstructCircle (myCenterPoint, GetPlane(), aRadius);
1297 if (!aConstructCircle.IsDone())
1301 gp_Circ aCircle = aConstructCircle.Value();
1304 theExtensionSize = aDimensionAspect->ArrowAspect()->Length();
1305 theAlignment = Prs3d_DTHP_Center;
1307 Standard_Real aParamBeg = ElCLib::Parameter (aCircle, aFirstAttach);
1308 Standard_Real aParamEnd = ElCLib::Parameter (aCircle, aSecondAttach);
1309 if (aParamEnd < aParamBeg)
1311 Standard_Real aParam = aParamEnd;
1312 aParamEnd = aParamBeg;
1316 ElCLib::AdjustPeriodic (0.0, M_PI * 2, Precision::PConfusion(), aParamBeg, aParamEnd);
1317 Standard_Real aTextPar = ElCLib::Parameter (aCircle , theTextPos);
1319 // Horizontal center
1320 if (aTextPar > aParamBeg && aTextPar < aParamEnd)
1322 theFlyout = aRadius;
1328 ElCLib::AdjustPeriodic (0.0, M_PI * 2, Precision::PConfusion(), aParamBeg, aParamEnd);
1330 if (aTextPar > aParamBeg && aTextPar < aParamEnd)
1332 theFlyout = -aRadius;
1336 // Text on the extensions
1337 gp_Lin aFirstLine = gce_MakeLin (myCenterPoint, myFirstPoint);
1338 gp_Lin aSecondLine = gce_MakeLin (myCenterPoint, mySecondPoint);
1339 gp_Pnt aFirstTextProj = AIS::Nearest (aFirstLine, theTextPos);
1340 gp_Pnt aSecondTextProj = AIS::Nearest (aSecondLine, theTextPos);
1341 Standard_Real aFirstDist = aFirstTextProj.Distance (theTextPos);
1342 Standard_Real aSecondDist = aSecondTextProj.Distance (theTextPos);
1344 if (aFirstDist <= aSecondDist)
1346 aRadius = myCenterPoint.Distance (aFirstTextProj);
1347 Standard_Real aNewExtensionSize = aFirstDist - anArrowLength;
1348 theExtensionSize = aNewExtensionSize < 0.0 ? 0.0 : aNewExtensionSize;
1350 theAlignment = Prs3d_DTHP_Left;
1352 gp_Vec aPosFlyoutDir = gp_Vec (myCenterPoint, myFirstPoint).Normalized().Scaled (aRadius);
1354 theFlyout = aFirstTextProj.Distance (myCenterPoint.Translated (aPosFlyoutDir)) > Precision::Confusion()
1355 ? -aRadius : aRadius;
1359 aRadius = myCenterPoint.Distance (aSecondTextProj);
1361 Standard_Real aNewExtensionSize = aSecondDist - anArrowLength;
1363 theExtensionSize = aNewExtensionSize < 0.0 ? 0.0 : aNewExtensionSize;
1365 theAlignment = Prs3d_DTHP_Right;
1367 gp_Vec aPosFlyoutDir = gp_Vec (myCenterPoint, mySecondPoint).Normalized().Scaled (aRadius);
1369 theFlyout = aSecondTextProj.Distance (myCenterPoint.Translated (aPosFlyoutDir)) > Precision::Confusion()
1370 ? -aRadius : aRadius;
1374 //=======================================================================
1375 //function : FitTextAlignment
1377 //=======================================================================
1378 void AIS_AngleDimension::FitTextAlignment (const Prs3d_DimensionTextHorizontalPosition& theHorizontalTextPos,
1379 Standard_Integer& theLabelPosition,
1380 Standard_Boolean& theIsArrowsExternal) const
1382 Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
1384 Quantity_Length anArrowLength = aDimensionAspect->ArrowAspect()->Length();
1386 // Prepare label string and compute its geometrical width
1387 Standard_Real aLabelWidth;
1388 TCollection_ExtendedString aLabelString = GetValueString (aLabelWidth);
1390 // add margins to label width
1391 if (aDimensionAspect->IsText3d())
1393 aLabelWidth += aDimensionAspect->TextAspect()->Height() * THE_3D_TEXT_MARGIN * 2.0;
1396 gp_Pnt aFirstAttach = myCenterPoint.Translated (gp_Vec (myCenterPoint, myFirstPoint).Normalized() * GetFlyout());
1397 gp_Pnt aSecondAttach = myCenterPoint.Translated (gp_Vec (myCenterPoint, mySecondPoint).Normalized() * GetFlyout());
1399 // Handle user-defined and automatic arrow placement
1400 switch (aDimensionAspect->ArrowOrientation())
1402 case Prs3d_DAO_External: theIsArrowsExternal = true; break;
1403 case Prs3d_DAO_Internal: theIsArrowsExternal = false; break;
1406 gp_Vec anAttachVector (aFirstAttach, aSecondAttach);
1407 Standard_Real aDimensionWidth = anAttachVector.Magnitude();
1409 // Add margin to ensure a small tail between text and arrow
1410 Standard_Real anArrowMargin = aDimensionAspect->IsText3d()
1411 ? aDimensionAspect->TextAspect()->Height() * THE_3D_TEXT_MARGIN
1414 Standard_Real anArrowsWidth = (anArrowLength + anArrowMargin) * 2.0;
1416 theIsArrowsExternal = aDimensionWidth < aLabelWidth + anArrowsWidth;
1421 // Handle user-defined and automatic text placement
1422 switch (theHorizontalTextPos)
1424 case Prs3d_DTHP_Left : theLabelPosition |= LabelPosition_Left; break;
1425 case Prs3d_DTHP_Right : theLabelPosition |= LabelPosition_Right; break;
1426 case Prs3d_DTHP_Center: theLabelPosition |= LabelPosition_HCenter; break;
1427 case Prs3d_DTHP_Fit:
1429 gp_Vec anAttachVector (aFirstAttach, aSecondAttach);
1430 Standard_Real aDimensionWidth = anAttachVector.Magnitude();
1431 Standard_Real anArrowsWidth = anArrowLength * 2.0;
1432 Standard_Real aContentWidth = theIsArrowsExternal ? aLabelWidth : aLabelWidth + anArrowsWidth;
1434 theLabelPosition |= aDimensionWidth < aContentWidth ? LabelPosition_Left : LabelPosition_HCenter;
1439 switch (aDimensionAspect->TextVerticalPosition())
1441 case Prs3d_DTVP_Above : theLabelPosition |= LabelPosition_Above; break;
1442 case Prs3d_DTVP_Below : theLabelPosition |= LabelPosition_Below; break;
1443 case Prs3d_DTVP_Center : theLabelPosition |= LabelPosition_VCenter; break;