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 const Standard_Boolean& theUseLongestDistance)
71 : AIS_Dimension (AIS_KOD_PLANEANGLE)
74 SetMeasuredGeometry (theFirstEdge, theSecondEdge, theUseLongestDistance);
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,
145 const Standard_Boolean& theUseLongestDistance)
147 gp_Pln aComputedPlane;
149 myFirstShape = theFirstEdge;
150 mySecondShape = theSecondEdge;
151 myThirdShape = TopoDS_Shape();
152 myGeometryType = GeometryType_Edges;
153 myIsGeometryValid = InitTwoEdgesAngle (aComputedPlane, theUseLongestDistance);
155 if (myIsGeometryValid && !myIsPlaneCustom)
163 //=======================================================================
164 //function : SetMeasuredGeometry
166 //=======================================================================
167 void AIS_AngleDimension::SetMeasuredGeometry (const gp_Pnt& theFirstPoint,
168 const gp_Pnt& theSecondPoint,
169 const gp_Pnt& theThirdPoint)
171 myFirstPoint = theFirstPoint;
172 myCenterPoint = theSecondPoint;
173 mySecondPoint = theThirdPoint;
174 myFirstShape = BRepLib_MakeVertex (myFirstPoint);
175 mySecondShape = BRepLib_MakeVertex (myCenterPoint);
176 myThirdShape = BRepLib_MakeVertex (mySecondPoint);
177 myGeometryType = GeometryType_Points;
178 myIsGeometryValid = IsValidPoints (myFirstPoint, myCenterPoint, mySecondPoint);
180 if (myIsGeometryValid && !myIsPlaneCustom)
188 //=======================================================================
189 //function : SetMeasuredGeometry
191 //=======================================================================
192 void AIS_AngleDimension::SetMeasuredGeometry (const TopoDS_Vertex& theFirstVertex,
193 const TopoDS_Vertex& theSecondVertex,
194 const TopoDS_Vertex& theThirdVertex)
196 myFirstShape = theFirstVertex;
197 mySecondShape = theSecondVertex;
198 myThirdShape = theThirdVertex;
199 myFirstPoint = BRep_Tool::Pnt (theFirstVertex);
200 myCenterPoint = BRep_Tool::Pnt (theSecondVertex);
201 mySecondPoint = BRep_Tool::Pnt (theThirdVertex);
202 myGeometryType = GeometryType_Points;
203 myIsGeometryValid = IsValidPoints (myFirstPoint, myCenterPoint, mySecondPoint);
205 if (myIsGeometryValid && !myIsPlaneCustom)
213 //=======================================================================
214 //function : SetMeasuredGeometry
216 //=======================================================================
217 void AIS_AngleDimension::SetMeasuredGeometry (const TopoDS_Face& theCone)
219 myFirstShape = theCone;
220 mySecondShape = TopoDS_Shape();
221 myThirdShape = TopoDS_Shape();
222 myGeometryType = GeometryType_Face;
223 myIsGeometryValid = InitConeAngle();
225 if (myIsGeometryValid && !myIsPlaneCustom)
233 //=======================================================================
234 //function : SetMeasuredGeometry
236 //=======================================================================
237 void AIS_AngleDimension::SetMeasuredGeometry (const TopoDS_Face& theFirstFace,
238 const TopoDS_Face& theSecondFace)
240 myFirstShape = theFirstFace;
241 mySecondShape = theSecondFace;
242 myThirdShape = TopoDS_Shape();
243 myGeometryType = GeometryType_Faces;
244 myIsGeometryValid = InitTwoFacesAngle();
246 if (myIsGeometryValid && !myIsPlaneCustom)
254 //=======================================================================
255 //function : SetMeasuredGeometry
257 //=======================================================================
258 void AIS_AngleDimension::SetMeasuredGeometry (const TopoDS_Face& theFirstFace,
259 const TopoDS_Face& theSecondFace,
260 const gp_Pnt& thePoint)
262 myFirstShape = theFirstFace;
263 mySecondShape = theSecondFace;
264 myThirdShape = TopoDS_Shape();
265 myGeometryType = GeometryType_Faces;
266 myIsGeometryValid = InitTwoFacesAngle (thePoint);
268 if (myIsGeometryValid && !myIsPlaneCustom)
276 //=======================================================================
279 //=======================================================================
280 void AIS_AngleDimension::Init()
282 SetAngleReversed (Standard_False);
283 SetArrowVisible (Standard_True, Standard_True);
284 SetSpecialSymbol (THE_DEGREE_SYMBOL);
285 SetDisplaySpecialSymbol (AIS_DSS_After);
289 //=======================================================================
290 //function: GetCenterOnArc
292 //=======================================================================
293 gp_Pnt AIS_AngleDimension::GetCenterOnArc (const gp_Pnt& theFirstAttach,
294 const gp_Pnt& theSecondAttach,
295 const gp_Pnt& theCenter) const
297 // construct plane where the circle and the arc are located
298 gce_MakePln aConstructPlane (theFirstAttach, theSecondAttach, theCenter);
299 if (!aConstructPlane.IsDone())
304 gp_Pln aPlane = aConstructPlane.Value();
306 Standard_Real aRadius = theFirstAttach.Distance (theCenter);
308 // construct circle forming the arc
309 gce_MakeCirc aConstructCircle (theCenter, aPlane, aRadius);
310 if (!aConstructCircle.IsDone())
315 gp_Circ aCircle = aConstructCircle.Value();
317 // compute angle parameters of arc end-points on circle
318 Standard_Real aParamBeg = ElCLib::Parameter (aCircle, theFirstAttach);
319 Standard_Real aParamEnd = ElCLib::Parameter (aCircle, theSecondAttach);
320 ElCLib::AdjustPeriodic (0.0, M_PI * 2, Precision::PConfusion(), aParamBeg, aParamEnd);
322 return ElCLib::Value ((aParamBeg + aParamEnd) * 0.5, aCircle);
325 //=======================================================================
327 //purpose : draws the arc between two attach points
328 //=======================================================================
329 void AIS_AngleDimension::DrawArc (const Handle(Prs3d_Presentation)& thePresentation,
330 const gp_Pnt& theFirstAttach,
331 const gp_Pnt& theSecondAttach,
332 const gp_Pnt& theCenter,
333 const Standard_Real theRadius,
334 const Standard_Integer theMode)
336 // construct plane where the circle and the arc are located
337 gce_MakePln aConstructPlane (theFirstAttach, theSecondAttach, theCenter);
338 if (!aConstructPlane.IsDone())
343 gp_Pln aPlane = aConstructPlane.Value();
345 gp_Ax1 anAxis = aPlane.Axis();
346 gp_Dir aDir = anAxis.Direction();
348 aPlane.SetAxis(gp_Ax1(anAxis.Location(), aDir));
351 // construct circle forming the arc
352 gce_MakeCirc aConstructCircle (theCenter, aPlane, theRadius);
353 if (!aConstructCircle.IsDone())
358 gp_Circ aCircle = aConstructCircle.Value();
361 GC_MakeArcOfCircle aConstructArc(aCircle, theFirstAttach, theSecondAttach, Standard_True);
362 if (!aConstructArc.IsDone())
367 // generate points with specified deflection
368 const Handle(Geom_TrimmedCurve)& anArcCurve = aConstructArc.Value();
370 GeomAdaptor_Curve anArcAdaptor (anArcCurve, anArcCurve->FirstParameter(), anArcCurve->LastParameter());
372 // compute number of discretization elements in old-fanshioned way
373 gp_Vec aCenterToFirstVec (theCenter, theFirstAttach);
374 gp_Vec aCenterToSecondVec (theCenter, theSecondAttach);
376 gp_Ax1 anAxis = aPlane.Axis();
377 gp_Dir aDir = anAxis.Direction();
378 gp_Vec aRefVec(aDir);
379 Standard_Real anAngle = aCenterToFirstVec.AngleWithRef (aCenterToSecondVec, aRefVec);
381 anAngle = 2.0 * M_PI + anAngle;
382 const Standard_Integer aNbPoints = Max (4, Standard_Integer (50.0 * anAngle / M_PI));
384 GCPnts_UniformAbscissa aMakePnts (anArcAdaptor, aNbPoints);
385 if (!aMakePnts.IsDone())
390 // init data arrays for graphical and selection primitives
391 Handle(Graphic3d_ArrayOfPolylines) aPrimSegments = new Graphic3d_ArrayOfPolylines (aNbPoints);
393 SelectionGeometry::Curve& aSensitiveCurve = mySelectionGeom.NewCurve();
395 // load data into arrays
396 for (Standard_Integer aPntIt = 1; aPntIt <= aMakePnts.NbPoints(); ++aPntIt)
398 gp_Pnt aPnt = anArcAdaptor.Value (aMakePnts.Parameter (aPntIt));
400 aPrimSegments->AddVertex (aPnt);
402 aSensitiveCurve.Append (aPnt);
405 // add display presentation
406 if (!myDrawer->DimensionAspect()->IsText3d() && theMode == ComputeMode_All)
408 Prs3d_Root::CurrentGroup (thePresentation)->SetStencilTestOptions (Standard_True);
410 Handle(Graphic3d_AspectLine3d) aDimensionLineStyle = myDrawer->DimensionAspect()->LineAspect()->Aspect();
411 Prs3d_Root::CurrentGroup (thePresentation)->SetPrimitivesAspect (aDimensionLineStyle);
412 Prs3d_Root::CurrentGroup (thePresentation)->AddPrimitiveArray (aPrimSegments);
413 if (!myDrawer->DimensionAspect()->IsText3d() && theMode == ComputeMode_All)
415 Prs3d_Root::CurrentGroup (thePresentation)->SetStencilTestOptions (Standard_False);
419 //=======================================================================
420 //function: DrawArcWithText
422 //=======================================================================
423 void AIS_AngleDimension::DrawArcWithText (const Handle(Prs3d_Presentation)& thePresentation,
424 const gp_Pnt& theFirstAttach,
425 const gp_Pnt& theSecondAttach,
426 const gp_Pnt& theCenter,
427 const TCollection_ExtendedString& theText,
428 const Standard_Real theTextWidth,
429 const Standard_Integer theMode,
430 const Standard_Integer theLabelPosition)
432 // construct plane where the circle and the arc are located
433 gce_MakePln aConstructPlane (theFirstAttach, theSecondAttach, theCenter);
434 if (!aConstructPlane.IsDone())
439 gp_Pln aPlane = aConstructPlane.Value();
441 Standard_Real aRadius = theFirstAttach.Distance (myCenterPoint);
443 // construct circle forming the arc
444 gce_MakeCirc aConstructCircle (theCenter, aPlane, aRadius);
445 if (!aConstructCircle.IsDone())
450 gp_Circ aCircle = aConstructCircle.Value();
452 // compute angle parameters of arc end-points on circle
453 Standard_Real aParamBeg = ElCLib::Parameter (aCircle, theFirstAttach);
454 Standard_Real aParamEnd = ElCLib::Parameter (aCircle, theSecondAttach);
455 ElCLib::AdjustPeriodic (0.0, M_PI * 2, Precision::PConfusion(), aParamBeg, aParamEnd);
457 // middle point of arc parameter on circle
458 Standard_Real aParamMid = (aParamBeg + aParamEnd) * 0.5;
460 // add text graphical primitives
461 if (theMode == ComputeMode_All || theMode == ComputeMode_Text)
463 gp_Pnt aTextPos = ElCLib::Value (aParamMid, aCircle);
464 gp_Dir aTextDir = gce_MakeDir (theFirstAttach, theSecondAttach);
467 DrawText (thePresentation,
474 if (theMode != ComputeMode_All && theMode != ComputeMode_Line)
479 Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
481 Standard_Boolean isLineBreak = aDimensionAspect->TextVerticalPosition() == Prs3d_DTVP_Center
482 && aDimensionAspect->IsText3d();
486 // compute gap for label as parameteric size of sector on circle segment
487 Standard_Real aSectorOnCircle = theTextWidth / aRadius;
489 gp_Pnt aTextPntBeg = ElCLib::Value (aParamMid - aSectorOnCircle * 0.5, aCircle);
490 gp_Pnt aTextPntEnd = ElCLib::Value (aParamMid + aSectorOnCircle * 0.5, aCircle);
493 DrawArc (thePresentation, theFirstAttach, aTextPntBeg, theCenter, aRadius, theMode);
494 DrawArc (thePresentation, theSecondAttach, aTextPntEnd, theCenter, aRadius, theMode);
498 DrawArc (thePresentation, theFirstAttach, theSecondAttach, theCenter, aRadius, theMode);
502 //=======================================================================
503 //function : CheckPlane
505 //=======================================================================
506 Standard_Boolean AIS_AngleDimension::CheckPlane (const gp_Pln& thePlane)const
508 if (!thePlane.Contains (myFirstPoint, Precision::Confusion()) &&
509 !thePlane.Contains (mySecondPoint, Precision::Confusion()) &&
510 !thePlane.Contains (myCenterPoint, Precision::Confusion()))
512 return Standard_False;
515 return Standard_True;
518 //=======================================================================
519 //function : ComputePlane
521 //=======================================================================
522 void AIS_AngleDimension::ComputePlane()
524 if (!myIsGeometryValid)
529 gp_Vec aFirstVec = gp_Vec (myCenterPoint, myFirstPoint).Normalized();
530 gp_Vec aSecondVec = gp_Vec (myCenterPoint, mySecondPoint).Normalized();
531 gp_Vec aDirectionN = aSecondVec.Crossed (aFirstVec).Normalized();
532 gp_Vec aDirectionY = (aFirstVec + aSecondVec).Normalized();
533 gp_Vec aDirectionX = aDirectionY.Crossed (aDirectionN).Normalized();
535 myPlane = gp_Pln (gp_Ax3 (myCenterPoint, gp_Dir (aDirectionN), gp_Dir (aDirectionX)));
538 //=======================================================================
539 //function : GetModelUnits
541 //=======================================================================
542 const TCollection_AsciiString& AIS_AngleDimension::GetModelUnits() const
544 return myDrawer->DimAngleModelUnits();
547 //=======================================================================
548 //function : GetDisplayUnits
550 //=======================================================================
551 const TCollection_AsciiString& AIS_AngleDimension::GetDisplayUnits() const
553 return myDrawer->DimAngleDisplayUnits();
556 //=======================================================================
557 //function : SetModelUnits
559 //=======================================================================
560 void AIS_AngleDimension::SetModelUnits (const TCollection_AsciiString& theUnits)
562 myDrawer->SetDimAngleModelUnits (theUnits);
565 //=======================================================================
566 //function : SetDisplayUnits
568 //=======================================================================
569 void AIS_AngleDimension::SetDisplayUnits (const TCollection_AsciiString& theUnits)
571 myDrawer->SetDimAngleDisplayUnits (theUnits);
574 //=======================================================================
575 //function : ComputeValue
577 //=======================================================================
578 Standard_Real AIS_AngleDimension::ComputeValue() const
585 gp_Vec aVec1 (myCenterPoint, myFirstPoint);
586 gp_Vec aVec2 (myCenterPoint, mySecondPoint);
588 Standard_Real anAngle = aVec2.AngleWithRef (aVec1, GetPlane().Axis().Direction());
590 return anAngle > 0.0 ? anAngle : (2.0 * M_PI + anAngle);
593 //=======================================================================
595 //purpose : Having three gp_Pnt points compute presentation
596 //=======================================================================
597 void AIS_AngleDimension::Compute (const Handle(PrsMgr_PresentationManager3d)& /*thePM*/,
598 const Handle(Prs3d_Presentation)& thePresentation,
599 const Standard_Integer theMode)
601 thePresentation->Clear();
602 mySelectionGeom.Clear (theMode);
609 // Parameters for presentation
610 Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
612 Prs3d_Root::CurrentGroup(thePresentation)->SetPrimitivesAspect (aDimensionAspect->LineAspect()->Aspect());
614 Quantity_Length anArrowLength = aDimensionAspect->ArrowAspect()->Length();
616 // prepare label string and compute its geometrical width
617 Standard_Real aLabelWidth;
618 TCollection_ExtendedString aLabelString = GetValueString (aLabelWidth);
620 // add margins to label width
621 if (aDimensionAspect->IsText3d())
623 aLabelWidth += aDimensionAspect->TextAspect()->Height() * THE_3D_TEXT_MARGIN * 2.0;
626 // Get parameters from aspect or adjust it according with custom text position
627 Standard_Real anExtensionSize = aDimensionAspect->ExtensionSize();
628 Prs3d_DimensionTextHorizontalPosition aHorisontalTextPos = aDimensionAspect->TextHorizontalPosition();
630 if (IsTextPositionCustom())
632 AdjustParameters (myFixedTextPosition,anExtensionSize, aHorisontalTextPos, myFlyout);
635 // Handle user-defined and automatic arrow placement
636 Standard_Boolean isArrowsExternal = Standard_False;
637 Standard_Integer aLabelPosition = LabelPosition_None;
639 FitTextAlignment (aHorisontalTextPos, aLabelPosition, isArrowsExternal);
641 gp_Pnt aFirstAttach = myCenterPoint.Translated (gp_Vec(myCenterPoint, myFirstPoint).Normalized() * GetFlyout());
642 gp_Pnt aSecondAttach = myCenterPoint.Translated (gp_Vec(myCenterPoint, mySecondPoint).Normalized() * GetFlyout());
644 //Arrows positions and directions
645 gp_Vec aWPDir = gp_Vec (GetPlane().Axis().Direction());
647 gp_Dir aFirstExtensionDir = aWPDir ^ gp_Vec (myCenterPoint, aFirstAttach);
648 gp_Dir aSecondExtensionDir = aWPDir.Reversed() ^ gp_Vec (myCenterPoint, aSecondAttach);
650 gp_Vec aFirstArrowVec = gp_Vec (aFirstExtensionDir) * anArrowLength;
651 gp_Vec aSecondArrowVec = gp_Vec (aSecondExtensionDir) * anArrowLength;
653 gp_Pnt aFirstArrowBegin (0.0, 0.0, 0.0);
654 gp_Pnt aFirstArrowEnd (0.0, 0.0, 0.0);
655 gp_Pnt aSecondArrowBegin (0.0, 0.0, 0.0);
656 gp_Pnt aSecondArrowEnd (0.0, 0.0, 0.0);
658 if (isArrowsExternal)
660 aFirstArrowVec.Reverse();
661 aSecondArrowVec.Reverse();
664 aFirstArrowBegin = aFirstAttach;
665 aSecondArrowBegin = aSecondAttach;
666 aFirstArrowEnd = aFirstAttach.Translated (-aFirstArrowVec);
667 aSecondArrowEnd = aSecondAttach.Translated (-aSecondArrowVec);
669 // Group1: stenciling text and the angle dimension arc
670 Prs3d_Root::NewGroup (thePresentation);
672 Standard_Integer aHPosition = aLabelPosition & LabelPosition_HMask;
677 case LabelPosition_HCenter :
679 Standard_Boolean isLineBreak = aDimensionAspect->TextVerticalPosition() == Prs3d_DTVP_Center
680 && aDimensionAspect->IsText3d();
684 DrawArcWithText (thePresentation,
695 // compute text primitives
696 if (theMode == ComputeMode_All || theMode == ComputeMode_Text)
698 gp_Vec aDimensionDir (aFirstAttach, aSecondAttach);
699 gp_Pnt aTextPos = IsTextPositionCustom() ? myFixedTextPosition
700 : GetCenterOnArc (aFirstAttach, aSecondAttach, myCenterPoint);
701 gp_Dir aTextDir = aDimensionDir;
703 DrawText (thePresentation,
710 if (theMode == ComputeMode_All || theMode == ComputeMode_Line)
712 DrawArc (thePresentation,
713 (isArrowsExternal || !myFirstArrowVisible) ? aFirstAttach : aFirstArrowEnd,
714 (isArrowsExternal || !mySecondArrowVisible) ? aSecondAttach : aSecondArrowEnd,
722 case LabelPosition_Left :
724 DrawExtension (thePresentation,
726 (isArrowsExternal && myFirstArrowVisible) ? aFirstArrowEnd : aFirstAttach,
735 case LabelPosition_Right :
737 DrawExtension (thePresentation,
739 (isArrowsExternal && mySecondArrowVisible) ? aSecondArrowEnd : aSecondAttach,
749 // dimension arc without text
750 if ((theMode == ComputeMode_All || theMode == ComputeMode_Line) && aHPosition != LabelPosition_HCenter)
752 Prs3d_Root::NewGroup (thePresentation);
754 DrawArc (thePresentation,
755 (isArrowsExternal || !myFirstArrowVisible) ? aFirstAttach : aFirstArrowEnd,
756 (isArrowsExternal || !mySecondArrowVisible) ? aSecondAttach : aSecondArrowEnd,
762 // arrows and arrow extensions
763 if (theMode == ComputeMode_All || theMode == ComputeMode_Line)
765 Prs3d_Root::NewGroup (thePresentation);
767 if (myFirstArrowVisible)
768 DrawArrow (thePresentation, aFirstArrowBegin, gp_Dir (aFirstArrowVec));
769 if (mySecondArrowVisible)
770 DrawArrow (thePresentation, aSecondArrowBegin, gp_Dir (aSecondArrowVec));
773 if ((theMode == ComputeMode_All || theMode == ComputeMode_Line) && isArrowsExternal)
775 Prs3d_Root::NewGroup (thePresentation);
777 if (aHPosition != LabelPosition_Left && myFirstArrowVisible)
779 DrawExtension (thePresentation,
780 aDimensionAspect->ArrowTailSize(),
783 THE_EMPTY_LABEL_STRING,
784 THE_EMPTY_LABEL_WIDTH,
789 if (aHPosition != LabelPosition_Right && mySecondArrowVisible)
791 DrawExtension (thePresentation,
792 aDimensionAspect->ArrowTailSize(),
795 THE_EMPTY_LABEL_STRING,
796 THE_EMPTY_LABEL_WIDTH,
803 if (theMode == ComputeMode_All)
805 Prs3d_Root::NewGroup (thePresentation);
807 Handle(Graphic3d_ArrayOfSegments) aPrimSegments = new Graphic3d_ArrayOfSegments (4);
808 aPrimSegments->AddVertex (myCenterPoint);
809 aPrimSegments->AddVertex (aFirstAttach);
810 aPrimSegments->AddVertex (myCenterPoint);
811 aPrimSegments->AddVertex (aSecondAttach);
813 Handle(Graphic3d_AspectLine3d) aFlyoutStyle = myDrawer->DimensionAspect()->LineAspect()->Aspect();
814 Prs3d_Root::CurrentGroup (thePresentation)->SetPrimitivesAspect (aFlyoutStyle);
815 Prs3d_Root::CurrentGroup (thePresentation)->AddPrimitiveArray (aPrimSegments);
818 mySelectionGeom.IsComputed = Standard_True;
821 //=======================================================================
822 //function : ComputeFlyoutSelection
823 //purpose : computes selection for flyouts
824 //=======================================================================
825 void AIS_AngleDimension::ComputeFlyoutSelection (const Handle(SelectMgr_Selection)& theSelection,
826 const Handle(SelectMgr_EntityOwner)& theOwner)
828 gp_Pnt aFirstAttach = myCenterPoint.Translated (gp_Vec (myCenterPoint, myFirstPoint).Normalized() * GetFlyout());
829 gp_Pnt aSecondAttach = myCenterPoint.Translated (gp_Vec (myCenterPoint, mySecondPoint).Normalized() * GetFlyout());
831 Handle(Select3D_SensitiveGroup) aSensitiveEntity = new Select3D_SensitiveGroup (theOwner);
832 aSensitiveEntity->Add (new Select3D_SensitiveSegment (theOwner, myCenterPoint, aFirstAttach));
833 aSensitiveEntity->Add (new Select3D_SensitiveSegment (theOwner, myCenterPoint, aSecondAttach));
835 theSelection->Add (aSensitiveEntity);
838 //=======================================================================
839 //function : InitTwoEdgesAngle
841 //=======================================================================
842 Standard_Boolean AIS_AngleDimension::InitTwoEdgesAngle (gp_Pln& theComputedPlane,
843 const Standard_Boolean& theUseLongestDistance)
845 TopoDS_Edge aFirstEdge = TopoDS::Edge (myFirstShape);
846 TopoDS_Edge aSecondEdge = TopoDS::Edge (mySecondShape);
848 BRepAdaptor_Curve aMakeFirstLine (aFirstEdge);
849 BRepAdaptor_Curve aMakeSecondLine (aSecondEdge);
851 if (aMakeFirstLine.GetType() != GeomAbs_Line || aMakeSecondLine.GetType() != GeomAbs_Line)
853 return Standard_False;
856 Handle(Geom_Line) aFirstLine = new Geom_Line (aMakeFirstLine.Line());
857 Handle(Geom_Line) aSecondLine = new Geom_Line (aMakeSecondLine.Line());
859 gp_Lin aFirstLin = aFirstLine->Lin();
860 gp_Lin aSecondLin = aSecondLine->Lin();
862 Standard_Boolean isParallelLines = Abs (aFirstLin.Angle (aSecondLin) - M_PI) <= Precision::Angular();
864 gp_Pnt aPoint = aFirstLine->Value (0.0);
865 gp_Dir aNormal = isParallelLines
866 ? gp_Vec (aSecondLin.Normal (aPoint).Direction()) ^ gp_Vec (aSecondLin.Direction())
867 : gp_Vec (aFirstLin.Direction()) ^ gp_Vec (aSecondLin.Direction());
869 theComputedPlane = gp_Pln (aPoint, aNormal);
871 // Compute geometry for this plane and edges
872 Standard_Boolean isInfinite1,isInfinite2;
873 gp_Pnt aFirstPoint1, aLastPoint1, aFirstPoint2, aLastPoint2;
874 gp_Lin2d aFirstLin2d, aSecondLin2d;
876 if (!AIS::ComputeGeometry (aFirstEdge, aSecondEdge,
877 aFirstLine, aSecondLine,
878 aFirstPoint1, aLastPoint1,
879 aFirstPoint2, aLastPoint2,
880 isInfinite1, isInfinite2))
882 return Standard_False;
885 if (aFirstLin.Direction().IsParallel (aSecondLin.Direction(), Precision::Angular()))
887 myFirstPoint = aFirstLin.Location();
888 mySecondPoint = ElCLib::Value (ElCLib::Parameter (aFirstLin, myFirstPoint), aSecondLin);
890 if (mySecondPoint.Distance (myFirstPoint) <= Precision::Confusion())
892 mySecondPoint.Translate (gp_Vec (aSecondLin.Direction()) * Abs (GetFlyout()));
895 myCenterPoint.SetXYZ ((myFirstPoint.XYZ() + mySecondPoint.XYZ()) / 2.0);
900 gp_Lin2d aFirstLin2d = ProjLib::Project (theComputedPlane, aFirstLin);
901 gp_Lin2d aSecondLin2d = ProjLib::Project (theComputedPlane, aSecondLin);
903 IntAna2d_AnaIntersection anInt2d (aFirstLin2d, aSecondLin2d);
904 gp_Pnt2d anIntersectPoint;
905 if (!anInt2d.IsDone() || anInt2d.IsEmpty())
907 return Standard_False;
910 anIntersectPoint = gp_Pnt2d (anInt2d.Point(1).Value());
911 myCenterPoint = ElCLib::To3d (theComputedPlane.Position().Ax2(), anIntersectPoint);
913 if (isInfinite1 || isInfinite2)
915 myFirstPoint = myCenterPoint.Translated (gp_Vec (aFirstLin.Direction()) * Abs (GetFlyout()));
916 mySecondPoint = myCenterPoint.Translated (gp_Vec (aSecondLin.Direction()) * Abs (GetFlyout()));
918 return IsValidPoints (myFirstPoint, myCenterPoint, mySecondPoint);
922 // | <- dimension should be here
924 if (theUseLongestDistance) {
925 myFirstPoint = myCenterPoint.Distance (aFirstPoint1) > myCenterPoint.Distance (aLastPoint1)
929 mySecondPoint = myCenterPoint.Distance (aFirstPoint2) > myCenterPoint.Distance (aLastPoint2)
933 myFirstPoint = !myCenterPoint.IsEqual(aFirstPoint1, Precision::Confusion())
936 mySecondPoint = !myCenterPoint.IsEqual(aFirstPoint2, Precision::Confusion())
942 return IsValidPoints (myFirstPoint, myCenterPoint, mySecondPoint);
945 //=======================================================================
946 //function : InitTwoFacesAngle
947 //purpose : initialization of angle dimension between two faces
948 //=======================================================================
949 Standard_Boolean AIS_AngleDimension::InitTwoFacesAngle()
951 TopoDS_Face aFirstFace = TopoDS::Face (myFirstShape);
952 TopoDS_Face aSecondFace = TopoDS::Face (mySecondShape);
954 gp_Dir aFirstDir, aSecondDir;
955 gp_Pln aFirstPlane, aSecondPlane;
956 Handle(Geom_Surface) aFirstBasisSurf, aSecondBasisSurf;
957 AIS_KindOfSurface aFirstSurfType, aSecondSurfType;
958 Standard_Real aFirstOffset, aSecondOffset;
960 AIS::GetPlaneFromFace (aFirstFace, aFirstPlane,
961 aFirstBasisSurf,aFirstSurfType,aFirstOffset);
963 AIS::GetPlaneFromFace (aSecondFace, aSecondPlane,
964 aSecondBasisSurf, aSecondSurfType, aSecondOffset);
966 if (aFirstSurfType == AIS_KOS_Plane && aSecondSurfType == AIS_KOS_Plane)
969 Handle(Geom_Plane) aFirstPlane = Handle(Geom_Plane)::DownCast (aFirstBasisSurf);
970 Handle(Geom_Plane) aSecondPlane = Handle(Geom_Plane)::DownCast (aSecondBasisSurf);
971 return AIS::InitAngleBetweenPlanarFaces (aFirstFace,
976 && IsValidPoints (myFirstPoint,
982 // Curvilinear faces angle
983 return AIS::InitAngleBetweenCurvilinearFaces (aFirstFace,
990 && IsValidPoints (myFirstPoint,
996 //=======================================================================
997 //function : InitTwoFacesAngle
998 //purpose : initialization of angle dimension between two faces
999 //=======================================================================
1000 Standard_Boolean AIS_AngleDimension::InitTwoFacesAngle (const gp_Pnt thePointOnFirstFace)
1002 TopoDS_Face aFirstFace = TopoDS::Face (myFirstShape);
1003 TopoDS_Face aSecondFace = TopoDS::Face (mySecondShape);
1005 gp_Dir aFirstDir, aSecondDir;
1006 gp_Pln aFirstPlane, aSecondPlane;
1007 Handle(Geom_Surface) aFirstBasisSurf, aSecondBasisSurf;
1008 AIS_KindOfSurface aFirstSurfType, aSecondSurfType;
1009 Standard_Real aFirstOffset, aSecondOffset;
1011 AIS::GetPlaneFromFace (aFirstFace, aFirstPlane,
1012 aFirstBasisSurf,aFirstSurfType,aFirstOffset);
1014 AIS::GetPlaneFromFace (aSecondFace, aSecondPlane,
1015 aSecondBasisSurf, aSecondSurfType, aSecondOffset);
1017 myFirstPoint = thePointOnFirstFace;
1018 if (aFirstSurfType == AIS_KOS_Plane && aSecondSurfType == AIS_KOS_Plane)
1020 //Planar faces angle
1021 Handle(Geom_Plane) aFirstPlane = Handle(Geom_Plane)::DownCast (aFirstBasisSurf);
1022 Handle(Geom_Plane) aSecondPlane = Handle(Geom_Plane)::DownCast (aSecondBasisSurf);
1023 return AIS::InitAngleBetweenPlanarFaces (aFirstFace,
1029 && IsValidPoints (myFirstPoint,
1035 // Curvilinear faces angle
1036 return AIS::InitAngleBetweenCurvilinearFaces (aFirstFace,
1044 && IsValidPoints (myFirstPoint,
1050 //=======================================================================
1051 //function : InitConeAngle
1052 //purpose : initialization of the cone angle
1053 //=======================================================================
1054 Standard_Boolean AIS_AngleDimension::InitConeAngle()
1056 if (myFirstShape.IsNull())
1058 return Standard_False;
1061 TopoDS_Face aConeShape = TopoDS::Face (myFirstShape);
1065 // A surface from the Face
1066 Handle(Geom_Surface) aSurf;
1067 Handle(Geom_OffsetSurface) aOffsetSurf;
1068 Handle(Geom_ConicalSurface) aConicalSurf;
1069 Handle(Geom_SurfaceOfRevolution) aRevSurf;
1070 Handle(Geom_Line) aLine;
1071 BRepAdaptor_Surface aConeAdaptor (aConeShape);
1073 AIS_KindOfSurface aSurfType;
1074 Standard_Real anOffset = 0.;
1075 Handle(Standard_Type) aType;
1077 Standard_Real aMaxV = aConeAdaptor.FirstVParameter();
1078 Standard_Real aMinV = aConeAdaptor.LastVParameter();
1080 AIS::GetPlaneFromFace (aConeShape, aPln, aSurf, aSurfType, anOffset);
1082 if (aSurfType == AIS_KOS_Revolution)
1084 // Surface of revolution
1085 aRevSurf = Handle(Geom_SurfaceOfRevolution)::DownCast(aSurf);
1086 gp_Lin aLin (aRevSurf->Axis());
1087 Handle(Geom_Curve) aBasisCurve = aRevSurf->BasisCurve();
1088 //Must be a part of line (basis curve should be linear)
1089 if (aBasisCurve ->DynamicType() != STANDARD_TYPE(Geom_Line))
1090 return Standard_False;
1092 gp_Pnt aFirst1 = aConeAdaptor.Value (0., aMinV);
1093 gp_Pnt aLast1 = aConeAdaptor.Value (0., aMaxV);
1094 gp_Vec aVec1 (aFirst1, aLast1);
1096 //Projection <aFirst> on <aLin>
1097 gp_Pnt aFirst2 = ElCLib::Value (ElCLib::Parameter (aLin, aFirst1), aLin);
1098 // Projection <aLast> on <aLin>
1099 gp_Pnt aLast2 = ElCLib::Value (ElCLib::Parameter (aLin, aLast1), aLin);
1101 gp_Vec aVec2 (aFirst2, aLast2);
1103 // Check if two parts of revolution are parallel (it's a cylinder) or normal (it's a circle).
1104 if (aVec1.IsParallel (aVec2, Precision::Angular())
1105 || aVec1.IsNormal (aVec2,Precision::Angular()))
1106 return Standard_False;
1108 gce_MakeCone aMkCone (aRevSurf->Axis(), aFirst1, aLast1);
1109 aCone = aMkCone.Value();
1110 myCenterPoint = aCone.Apex();
1114 aType = aSurf->DynamicType();
1115 if (aType == STANDARD_TYPE(Geom_OffsetSurface) || anOffset > 0.01)
1118 aOffsetSurf = new Geom_OffsetSurface (aSurf, anOffset);
1119 aSurf = aOffsetSurf->Surface();
1120 BRepBuilderAPI_MakeFace aMkFace(aSurf, Precision::Confusion());
1122 if (!aMkFace.IsDone())
1123 return Standard_False;
1124 aConeAdaptor.Initialize (aMkFace.Face());
1126 aCone = aConeAdaptor.Cone();
1127 aConicalSurf = Handle(Geom_ConicalSurface)::DownCast (aSurf);
1128 myCenterPoint = aConicalSurf->Apex();
1131 // A circle where the angle is drawn
1132 Handle(Geom_Curve) aCurve;
1133 Standard_Real aMidV = ( aMinV + aMaxV ) / 2.5;
1134 aCurve = aSurf->VIso (aMidV);
1135 aCircle = Handle(Geom_Circle)::DownCast (aCurve)->Circ();
1137 aCurve = aSurf->VIso(aMaxV);
1138 gp_Circ aCircVmax = Handle(Geom_Circle)::DownCast(aCurve)->Circ();
1139 aCurve = aSurf->VIso(aMinV);
1140 gp_Circ aCircVmin = Handle(Geom_Circle)::DownCast(aCurve)->Circ();
1142 if (aCircVmax.Radius() < aCircVmin.Radius())
1144 gp_Circ aTmpCirc = aCircVmax;
1145 aCircVmax = aCircVmin;
1146 aCircVmin = aTmpCirc;
1149 myFirstPoint = ElCLib::Value (0, aCircle);
1150 mySecondPoint = ElCLib::Value (M_PI, aCircle);
1151 return Standard_True;
1154 //=======================================================================
1155 //function : IsValidPoints
1157 //=======================================================================
1158 Standard_Boolean AIS_AngleDimension::IsValidPoints (const gp_Pnt& theFirstPoint,
1159 const gp_Pnt& theCenterPoint,
1160 const gp_Pnt& theSecondPoint) const
1162 return theFirstPoint.Distance (theCenterPoint) > Precision::Confusion()
1163 && theSecondPoint.Distance (theCenterPoint) > Precision::Confusion()
1164 && gp_Vec (theCenterPoint, theFirstPoint).Angle (
1165 gp_Vec (theCenterPoint, theSecondPoint)) > Precision::Angular();
1168 //=======================================================================
1169 //function : GetTextPosition
1171 //=======================================================================
1172 const gp_Pnt AIS_AngleDimension::GetTextPosition() const
1176 return gp::Origin();
1179 if (IsTextPositionCustom())
1181 return myFixedTextPosition;
1184 // Counts text position according to the dimension parameters
1185 gp_Pnt aTextPosition (gp::Origin());
1187 Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
1189 // Prepare label string and compute its geometrical width
1190 Standard_Real aLabelWidth;
1191 TCollection_ExtendedString aLabelString = GetValueString (aLabelWidth);
1193 gp_Pnt aFirstAttach = myCenterPoint.Translated (gp_Vec(myCenterPoint, myFirstPoint).Normalized() * GetFlyout());
1194 gp_Pnt aSecondAttach = myCenterPoint.Translated (gp_Vec(myCenterPoint, mySecondPoint).Normalized() * GetFlyout());
1196 // Handle user-defined and automatic arrow placement
1197 Standard_Boolean isArrowsExternal = Standard_False;
1198 Standard_Integer aLabelPosition = LabelPosition_None;
1199 FitTextAlignment (aDimensionAspect->TextHorizontalPosition(),
1200 aLabelPosition, isArrowsExternal);
1202 // Get text position
1203 switch (aLabelPosition & LabelPosition_HMask)
1205 case LabelPosition_HCenter:
1207 aTextPosition = GetCenterOnArc (aFirstAttach, aSecondAttach, myCenterPoint);
1210 case LabelPosition_Left:
1212 gp_Dir aPlaneNormal = gp_Vec (aFirstAttach, aSecondAttach) ^ gp_Vec (myCenterPoint, aFirstAttach);
1213 gp_Dir anExtensionDir = aPlaneNormal ^ gp_Vec (myCenterPoint, aFirstAttach);
1214 Standard_Real anExtensionSize = aDimensionAspect->ExtensionSize();
1215 Standard_Real anOffset = isArrowsExternal
1216 ? anExtensionSize + aDimensionAspect->ArrowAspect()->Length()
1218 gp_Vec anExtensionVec = gp_Vec (anExtensionDir) * -anOffset;
1219 aTextPosition = aFirstAttach.Translated (anExtensionVec);
1222 case LabelPosition_Right:
1224 gp_Dir aPlaneNormal = gp_Vec (aFirstAttach, aSecondAttach) ^ gp_Vec (myCenterPoint, aFirstAttach);
1225 gp_Dir anExtensionDir = aPlaneNormal ^ gp_Vec (myCenterPoint, aSecondAttach);
1226 Standard_Real anExtensionSize = aDimensionAspect->ExtensionSize();
1227 Standard_Real anOffset = isArrowsExternal
1228 ? anExtensionSize + aDimensionAspect->ArrowAspect()->Length()
1230 gp_Vec anExtensionVec = gp_Vec (anExtensionDir) * anOffset;
1231 aTextPosition = aSecondAttach.Translated (anExtensionVec);
1236 return aTextPosition;
1239 //=======================================================================
1240 //function : SetTextPosition
1242 //=======================================================================
1243 void AIS_AngleDimension::SetTextPosition (const gp_Pnt& theTextPos)
1250 // The text position point for angle dimension should belong to the working plane.
1251 if (!GetPlane().Contains (theTextPos, Precision::Confusion()))
1253 Standard_ProgramError::Raise ("The text position point for angle dimension doesn't belong to the working plane.");
1256 myIsTextPositionFixed = Standard_True;
1257 myFixedTextPosition = theTextPos;
1260 //=======================================================================
1261 //function : SetAngleReversed
1263 //=======================================================================
1264 void AIS_AngleDimension::SetAngleReversed(const Standard_Boolean& theUseReverse)
1266 myUseReverse = theUseReverse;
1269 //=======================================================================
1270 //function : SetArrowVisible
1272 //=======================================================================
1273 void AIS_AngleDimension::SetArrowVisible(const Standard_Boolean& theFirstArrowVisible,
1274 const Standard_Boolean& theSecondArrowVisible)
1276 myFirstArrowVisible = theFirstArrowVisible;
1277 mySecondArrowVisible = theSecondArrowVisible;
1280 //=======================================================================
1281 //function : AdjustParameters
1283 //=======================================================================
1284 void AIS_AngleDimension::AdjustParameters (const gp_Pnt& theTextPos,
1285 Standard_Real& theExtensionSize,
1286 Prs3d_DimensionTextHorizontalPosition& theAlignment,
1287 Standard_Real& theFlyout) const
1289 Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
1290 Standard_Real anArrowLength = aDimensionAspect->ArrowAspect()->Length();
1292 // Build circle with radius that is equal to distance from text position to the center point.
1293 Standard_Real aRadius = gp_Vec (myCenterPoint, theTextPos).Magnitude();
1295 // Set attach points in positive direction of the flyout.
1296 gp_Pnt aFirstAttach = myCenterPoint.Translated (gp_Vec (myCenterPoint, myFirstPoint).Normalized() * aRadius);
1297 gp_Pnt aSecondAttach = myCenterPoint.Translated (gp_Vec (myCenterPoint, mySecondPoint).Normalized() * aRadius);
1299 gce_MakeCirc aConstructCircle (myCenterPoint, GetPlane(), aRadius);
1300 if (!aConstructCircle.IsDone())
1304 gp_Circ aCircle = aConstructCircle.Value();
1307 theExtensionSize = aDimensionAspect->ArrowAspect()->Length();
1308 theAlignment = Prs3d_DTHP_Center;
1310 Standard_Real aParamBeg = ElCLib::Parameter (aCircle, aFirstAttach);
1311 Standard_Real aParamEnd = ElCLib::Parameter (aCircle, aSecondAttach);
1312 if (aParamEnd < aParamBeg)
1314 Standard_Real aParam = aParamEnd;
1315 aParamEnd = aParamBeg;
1319 ElCLib::AdjustPeriodic (0.0, M_PI * 2, Precision::PConfusion(), aParamBeg, aParamEnd);
1320 Standard_Real aTextPar = ElCLib::Parameter (aCircle , theTextPos);
1322 // Horizontal center
1323 if (aTextPar > aParamBeg && aTextPar < aParamEnd)
1325 theFlyout = aRadius;
1331 ElCLib::AdjustPeriodic (0.0, M_PI * 2, Precision::PConfusion(), aParamBeg, aParamEnd);
1333 if (aTextPar > aParamBeg && aTextPar < aParamEnd)
1335 theFlyout = -aRadius;
1339 // Text on the extensions
1340 gp_Lin aFirstLine = gce_MakeLin (myCenterPoint, myFirstPoint);
1341 gp_Lin aSecondLine = gce_MakeLin (myCenterPoint, mySecondPoint);
1342 gp_Pnt aFirstTextProj = AIS::Nearest (aFirstLine, theTextPos);
1343 gp_Pnt aSecondTextProj = AIS::Nearest (aSecondLine, theTextPos);
1344 Standard_Real aFirstDist = aFirstTextProj.Distance (theTextPos);
1345 Standard_Real aSecondDist = aSecondTextProj.Distance (theTextPos);
1347 if (aFirstDist <= aSecondDist)
1349 aRadius = myCenterPoint.Distance (aFirstTextProj);
1350 Standard_Real aNewExtensionSize = aFirstDist - anArrowLength;
1351 theExtensionSize = aNewExtensionSize < 0.0 ? 0.0 : aNewExtensionSize;
1353 theAlignment = Prs3d_DTHP_Left;
1355 gp_Vec aPosFlyoutDir = gp_Vec (myCenterPoint, myFirstPoint).Normalized().Scaled (aRadius);
1357 theFlyout = aFirstTextProj.Distance (myCenterPoint.Translated (aPosFlyoutDir)) > Precision::Confusion()
1358 ? -aRadius : aRadius;
1362 aRadius = myCenterPoint.Distance (aSecondTextProj);
1364 Standard_Real aNewExtensionSize = aSecondDist - anArrowLength;
1366 theExtensionSize = aNewExtensionSize < 0.0 ? 0.0 : aNewExtensionSize;
1368 theAlignment = Prs3d_DTHP_Right;
1370 gp_Vec aPosFlyoutDir = gp_Vec (myCenterPoint, mySecondPoint).Normalized().Scaled (aRadius);
1372 theFlyout = aSecondTextProj.Distance (myCenterPoint.Translated (aPosFlyoutDir)) > Precision::Confusion()
1373 ? -aRadius : aRadius;
1377 //=======================================================================
1378 //function : FitTextAlignment
1380 //=======================================================================
1381 void AIS_AngleDimension::FitTextAlignment (const Prs3d_DimensionTextHorizontalPosition& theHorizontalTextPos,
1382 Standard_Integer& theLabelPosition,
1383 Standard_Boolean& theIsArrowsExternal) const
1385 Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
1387 Quantity_Length anArrowLength = aDimensionAspect->ArrowAspect()->Length();
1389 // Prepare label string and compute its geometrical width
1390 Standard_Real aLabelWidth;
1391 TCollection_ExtendedString aLabelString = GetValueString (aLabelWidth);
1393 // add margins to label width
1394 if (aDimensionAspect->IsText3d())
1396 aLabelWidth += aDimensionAspect->TextAspect()->Height() * THE_3D_TEXT_MARGIN * 2.0;
1399 gp_Pnt aFirstAttach = myCenterPoint.Translated (gp_Vec (myCenterPoint, myFirstPoint).Normalized() * GetFlyout());
1400 gp_Pnt aSecondAttach = myCenterPoint.Translated (gp_Vec (myCenterPoint, mySecondPoint).Normalized() * GetFlyout());
1402 // Handle user-defined and automatic arrow placement
1403 switch (aDimensionAspect->ArrowOrientation())
1405 case Prs3d_DAO_External: theIsArrowsExternal = true; break;
1406 case Prs3d_DAO_Internal: theIsArrowsExternal = false; break;
1409 gp_Vec anAttachVector (aFirstAttach, aSecondAttach);
1410 Standard_Real aDimensionWidth = anAttachVector.Magnitude();
1412 // Add margin to ensure a small tail between text and arrow
1413 Standard_Real anArrowMargin = aDimensionAspect->IsText3d()
1414 ? aDimensionAspect->TextAspect()->Height() * THE_3D_TEXT_MARGIN
1417 Standard_Real anArrowsWidth = (anArrowLength + anArrowMargin) * 2.0;
1419 theIsArrowsExternal = aDimensionWidth < aLabelWidth + anArrowsWidth;
1424 // Handle user-defined and automatic text placement
1425 switch (theHorizontalTextPos)
1427 case Prs3d_DTHP_Left : theLabelPosition |= LabelPosition_Left; break;
1428 case Prs3d_DTHP_Right : theLabelPosition |= LabelPosition_Right; break;
1429 case Prs3d_DTHP_Center: theLabelPosition |= LabelPosition_HCenter; break;
1430 case Prs3d_DTHP_Fit:
1432 gp_Vec anAttachVector (aFirstAttach, aSecondAttach);
1433 Standard_Real aDimensionWidth = anAttachVector.Magnitude();
1434 Standard_Real anArrowsWidth = anArrowLength * 2.0;
1435 Standard_Real aContentWidth = theIsArrowsExternal ? aLabelWidth : aLabelWidth + anArrowsWidth;
1437 theLabelPosition |= aDimensionWidth < aContentWidth ? LabelPosition_Left : LabelPosition_HCenter;
1442 switch (aDimensionAspect->TextVerticalPosition())
1444 case Prs3d_DTVP_Above : theLabelPosition |= LabelPosition_Above; break;
1445 case Prs3d_DTVP_Below : theLabelPosition |= LabelPosition_Below; break;
1446 case Prs3d_DTVP_Center : theLabelPosition |= LabelPosition_VCenter; break;