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
9 // under the terms of the GNU Lesser General Public version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
17 #include <AIS_AngleDimension.hxx>
20 #include <AIS_Drawer.hxx>
21 #include <BRepBuilderAPI_MakeFace.hxx>
22 #include <BRepAdaptor_Curve.hxx>
23 #include <BRepAdaptor_Surface.hxx>
24 #include <BRepLib_MakeVertex.hxx>
25 #include <BRep_Tool.hxx>
27 #include <GCPnts_UniformAbscissa.hxx>
28 #include <GC_MakeArcOfCircle.hxx>
29 #include <gce_MakeLin2d.hxx>
30 #include <gce_MakeLin.hxx>
31 #include <gce_MakeCirc.hxx>
32 #include <gce_MakeCone.hxx>
33 #include <gce_MakePln.hxx>
34 #include <gce_MakeDir.hxx>
35 #include <Geom_Circle.hxx>
36 #include <Geom_TrimmedCurve.hxx>
37 #include <Geom_ConicalSurface.hxx>
38 #include <Geom_SurfaceOfRevolution.hxx>
39 #include <Geom_OffsetSurface.hxx>
40 #include <Graphic3d_ArrayOfSegments.hxx>
41 #include <Graphic3d_Group.hxx>
42 #include <Graphic3d_ArrayOfPolylines.hxx>
43 #include <IntAna2d_AnaIntersection.hxx>
44 #include <ProjLib.hxx>
45 #include <Prs3d_Root.hxx>
46 #include <Prs3d_ShadingAspect.hxx>
47 #include <PrsMgr_PresentationManager3d.hxx>
48 #include <Select3D_SensitiveGroup.hxx>
49 #include <Select3D_SensitiveSegment.hxx>
50 #include <SelectMgr_Selection.hxx>
51 #include <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 myIsValid = InitTwoEdgesAngle (aComputedPlane);
153 if (myIsValid && !myIsPlaneCustom)
155 myPlane = aComputedPlane;
158 myIsValid &= CheckPlane (myPlane);
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 myIsValid = IsValidPoints (myFirstPoint, myCenterPoint, mySecondPoint);
180 if (myIsValid && !myIsPlaneCustom)
185 myIsValid &= CheckPlane (myPlane);
190 //=======================================================================
191 //function : SetMeasuredGeometry
193 //=======================================================================
194 void AIS_AngleDimension::SetMeasuredGeometry (const TopoDS_Vertex& theFirstVertex,
195 const TopoDS_Vertex& theSecondVertex,
196 const TopoDS_Vertex& theThirdVertex)
198 myFirstShape = theFirstVertex;
199 mySecondShape = theSecondVertex;
200 myThirdShape = theThirdVertex;
201 myFirstPoint = BRep_Tool::Pnt (theFirstVertex);
202 myCenterPoint = BRep_Tool::Pnt (theSecondVertex);
203 mySecondPoint = BRep_Tool::Pnt (theThirdVertex);
204 myGeometryType = GeometryType_Points;
205 myIsValid = IsValidPoints (myFirstPoint, myCenterPoint, mySecondPoint);
207 if (myIsValid && !myIsPlaneCustom)
212 myIsValid &= CheckPlane (myPlane);
217 //=======================================================================
218 //function : SetMeasuredGeometry
220 //=======================================================================
221 void AIS_AngleDimension::SetMeasuredGeometry (const TopoDS_Face& theCone)
223 myFirstShape = theCone;
224 mySecondShape = TopoDS_Shape();
225 myThirdShape = TopoDS_Shape();
226 myGeometryType = GeometryType_Face;
227 myIsValid = InitConeAngle();
229 if (myIsValid && !myIsPlaneCustom)
234 myIsValid &= CheckPlane (myPlane);
239 //=======================================================================
240 //function : SetMeasuredGeometry
242 //=======================================================================
243 void AIS_AngleDimension::SetMeasuredGeometry (const TopoDS_Face& theFirstFace,
244 const TopoDS_Face& theSecondFace)
246 myFirstShape = theFirstFace;
247 mySecondShape = theSecondFace;
248 myThirdShape = TopoDS_Shape();
249 myGeometryType = GeometryType_Faces;
250 myIsValid = InitTwoFacesAngle();
252 if (myIsValid && !myIsPlaneCustom)
257 myIsValid &= CheckPlane (myPlane);
262 //=======================================================================
263 //function : SetMeasuredGeometry
265 //=======================================================================
266 void AIS_AngleDimension::SetMeasuredGeometry (const TopoDS_Face& theFirstFace,
267 const TopoDS_Face& theSecondFace,
268 const gp_Pnt& thePoint)
270 myFirstShape = theFirstFace;
271 mySecondShape = theSecondFace;
272 myThirdShape = TopoDS_Shape();
273 myGeometryType = GeometryType_Faces;
274 myIsValid = InitTwoFacesAngle (thePoint);
276 if (myIsValid && !myIsPlaneCustom)
281 myIsValid &= CheckPlane (myPlane);
286 //=======================================================================
289 //=======================================================================
290 void AIS_AngleDimension::Init()
292 SetSpecialSymbol (THE_DEGREE_SYMBOL);
293 SetDisplaySpecialSymbol (AIS_DSS_After);
297 //=======================================================================
298 //function: GetCenterOnArc
300 //=======================================================================
301 gp_Pnt AIS_AngleDimension::GetCenterOnArc (const gp_Pnt& theFirstAttach,
302 const gp_Pnt& theSecondAttach,
303 const gp_Pnt& theCenter)
305 // construct plane where the circle and the arc are located
306 gce_MakePln aConstructPlane (theFirstAttach, theSecondAttach, theCenter);
307 if (!aConstructPlane.IsDone())
312 gp_Pln aPlane = aConstructPlane.Value();
314 Standard_Real aRadius = theFirstAttach.Distance (theCenter);
316 // construct circle forming the arc
317 gce_MakeCirc aConstructCircle (theCenter, aPlane, aRadius);
318 if (!aConstructCircle.IsDone())
323 gp_Circ aCircle = aConstructCircle.Value();
325 // compute angle parameters of arc end-points on circle
326 Standard_Real aParamBeg = ElCLib::Parameter (aCircle, theFirstAttach);
327 Standard_Real aParamEnd = ElCLib::Parameter (aCircle, theSecondAttach);
328 ElCLib::AdjustPeriodic (0.0, M_PI * 2, Precision::PConfusion(), aParamBeg, aParamEnd);
330 return ElCLib::Value ((aParamBeg + aParamEnd) * 0.5, aCircle);
333 //=======================================================================
335 //purpose : draws the arc between two attach points
336 //=======================================================================
337 void AIS_AngleDimension::DrawArc (const Handle(Prs3d_Presentation)& thePresentation,
338 const gp_Pnt& theFirstAttach,
339 const gp_Pnt& theSecondAttach,
340 const gp_Pnt& theCenter,
341 const Standard_Real theRadius,
342 const Standard_Integer theMode)
344 // construct plane where the circle and the arc are located
345 gce_MakePln aConstructPlane (theFirstAttach, theSecondAttach, theCenter);
346 if (!aConstructPlane.IsDone())
351 gp_Pln aPlane = aConstructPlane.Value();
353 // construct circle forming the arc
354 gce_MakeCirc aConstructCircle (theCenter, aPlane, theRadius);
355 if (!aConstructCircle.IsDone())
360 gp_Circ aCircle = aConstructCircle.Value();
363 GC_MakeArcOfCircle aConstructArc (aCircle, theFirstAttach, theSecondAttach, Standard_True);
364 if (!aConstructArc.IsDone())
369 // generate points with specified deflection
370 const Handle(Geom_TrimmedCurve)& anArcCurve = aConstructArc.Value();
372 GeomAdaptor_Curve anArcAdaptor (anArcCurve, anArcCurve->FirstParameter(), anArcCurve->LastParameter());
374 // compute number of discretization elements in old-fanshioned way
375 gp_Vec aCenterToFirstVec (theCenter, theFirstAttach);
376 gp_Vec aCenterToSecondVec (theCenter, theSecondAttach);
377 const Standard_Real anAngle = aCenterToFirstVec.Angle (aCenterToSecondVec);
378 const Standard_Integer aNbPoints = Max (4, Standard_Integer (50.0 * anAngle / M_PI));
380 GCPnts_UniformAbscissa aMakePnts (anArcAdaptor, aNbPoints);
381 if (!aMakePnts.IsDone())
386 // init data arrays for graphical and selection primitives
387 Handle(Graphic3d_ArrayOfPolylines) aPrimSegments = new Graphic3d_ArrayOfPolylines (aNbPoints);
389 SelectionGeometry::Curve& aSensitiveCurve = mySelectionGeom.NewCurve();
391 // load data into arrays
392 for (Standard_Integer aPntIt = 1; aPntIt <= aMakePnts.NbPoints(); ++aPntIt)
394 gp_Pnt aPnt = anArcAdaptor.Value (aMakePnts.Parameter (aPntIt));
396 aPrimSegments->AddVertex (aPnt);
398 aSensitiveCurve.Append (aPnt);
401 // add display presentation
402 if (!myDrawer->DimensionAspect()->IsText3d() && theMode == ComputeMode_All)
404 Prs3d_Root::CurrentGroup (thePresentation)->SetStencilTestOptions (Standard_True);
406 Handle(Graphic3d_AspectLine3d) aDimensionLineStyle = myDrawer->DimensionAspect()->LineAspect()->Aspect();
407 Prs3d_Root::CurrentGroup (thePresentation)->SetPrimitivesAspect (aDimensionLineStyle);
408 Prs3d_Root::CurrentGroup (thePresentation)->AddPrimitiveArray (aPrimSegments);
409 if (!myDrawer->DimensionAspect()->IsText3d() && theMode == ComputeMode_All)
411 Prs3d_Root::CurrentGroup (thePresentation)->SetStencilTestOptions (Standard_False);
415 //=======================================================================
416 //function: DrawArcWithText
418 //=======================================================================
419 void AIS_AngleDimension::DrawArcWithText (const Handle(Prs3d_Presentation)& thePresentation,
420 const gp_Pnt& theFirstAttach,
421 const gp_Pnt& theSecondAttach,
422 const gp_Pnt& theCenter,
423 const TCollection_ExtendedString& theText,
424 const Standard_Real theTextWidth,
425 const Standard_Integer theMode,
426 const Standard_Integer theLabelPosition)
428 // construct plane where the circle and the arc are located
429 gce_MakePln aConstructPlane (theFirstAttach, theSecondAttach, theCenter);
430 if (!aConstructPlane.IsDone())
435 gp_Pln aPlane = aConstructPlane.Value();
437 Standard_Real aRadius = theFirstAttach.Distance (myCenterPoint);
439 // construct circle forming the arc
440 gce_MakeCirc aConstructCircle (theCenter, aPlane, aRadius);
441 if (!aConstructCircle.IsDone())
446 gp_Circ aCircle = aConstructCircle.Value();
448 // compute angle parameters of arc end-points on circle
449 Standard_Real aParamBeg = ElCLib::Parameter (aCircle, theFirstAttach);
450 Standard_Real aParamEnd = ElCLib::Parameter (aCircle, theSecondAttach);
451 ElCLib::AdjustPeriodic (0.0, M_PI * 2, Precision::PConfusion(), aParamBeg, aParamEnd);
453 // middle point of arc parameter on circle
454 Standard_Real aParamMid = (aParamBeg + aParamEnd) * 0.5;
456 // add text graphical primitives
457 if (theMode == ComputeMode_All || theMode == ComputeMode_Text)
459 gp_Pnt aTextPos = ElCLib::Value (aParamMid, aCircle);
460 gp_Dir aTextDir = gce_MakeDir (theFirstAttach, theSecondAttach);
463 DrawText (thePresentation,
470 if (theMode != ComputeMode_All && theMode != ComputeMode_Line)
475 Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
477 Standard_Boolean isLineBreak = aDimensionAspect->TextVerticalPosition() == Prs3d_DTVP_Center
478 && aDimensionAspect->IsText3d();
482 // compute gap for label as parameteric size of sector on circle segment
483 Standard_Real aSectorOnCircle = theTextWidth / aRadius;
485 gp_Pnt aTextPntBeg = ElCLib::Value (aParamMid - aSectorOnCircle * 0.5, aCircle);
486 gp_Pnt aTextPntEnd = ElCLib::Value (aParamMid + aSectorOnCircle * 0.5, aCircle);
489 DrawArc (thePresentation, theFirstAttach, aTextPntBeg, theCenter, aRadius, theMode);
490 DrawArc (thePresentation, theSecondAttach, aTextPntEnd, theCenter, aRadius, theMode);
494 DrawArc (thePresentation, theFirstAttach, theSecondAttach, theCenter, aRadius, theMode);
498 //=======================================================================
499 //function : CheckPlane
501 //=======================================================================
502 Standard_Boolean AIS_AngleDimension::CheckPlane (const gp_Pln& thePlane)const
504 if (!thePlane.Contains (myFirstPoint, Precision::Confusion()) &&
505 !thePlane.Contains (mySecondPoint, Precision::Confusion()) &&
506 !thePlane.Contains (myCenterPoint, Precision::Confusion()))
508 return Standard_False;
511 return Standard_True;
514 //=======================================================================
515 //function : ComputePlane
517 //=======================================================================
518 void AIS_AngleDimension::ComputePlane()
525 gp_Vec aFirstVec = gp_Vec (myCenterPoint, myFirstPoint).Normalized();
526 gp_Vec aSecondVec = gp_Vec (myCenterPoint, mySecondPoint).Normalized();
527 gp_Vec aDirectionN = aSecondVec.Crossed (aFirstVec).Normalized();
528 gp_Vec aDirectionY = (aFirstVec + aSecondVec).Normalized();
529 gp_Vec aDirectionX = aDirectionY.Crossed (aDirectionN).Normalized();
531 myPlane = gp_Pln (gp_Ax3 (myCenterPoint, gp_Dir (aDirectionN), gp_Dir (aDirectionX)));
534 //=======================================================================
535 //function : GetModelUnits
537 //=======================================================================
538 const TCollection_AsciiString& AIS_AngleDimension::GetModelUnits() const
540 return myDrawer->DimAngleModelUnits();
543 //=======================================================================
544 //function : GetDisplayUnits
546 //=======================================================================
547 const TCollection_AsciiString& AIS_AngleDimension::GetDisplayUnits() const
549 return myDrawer->DimAngleDisplayUnits();
552 //=======================================================================
553 //function : SetModelUnits
555 //=======================================================================
556 void AIS_AngleDimension::SetModelUnits (const TCollection_AsciiString& theUnits)
558 myDrawer->SetDimAngleModelUnits (theUnits);
561 //=======================================================================
562 //function : SetDisplayUnits
564 //=======================================================================
565 void AIS_AngleDimension::SetDisplayUnits (const TCollection_AsciiString& theUnits)
567 myDrawer->SetDimAngleDisplayUnits (theUnits);
570 //=======================================================================
571 //function : ComputeValue
573 //=======================================================================
574 Standard_Real AIS_AngleDimension::ComputeValue() const
581 gp_Vec aVec1 (myCenterPoint, myFirstPoint);
582 gp_Vec aVec2 (myCenterPoint, mySecondPoint);
584 Standard_Real anAngle = aVec2.AngleWithRef (aVec1, GetPlane().Axis().Direction());
586 return anAngle > 0.0 ? anAngle : (2.0 * M_PI - anAngle);
589 //=======================================================================
591 //purpose : Having three gp_Pnt points compute presentation
592 //=======================================================================
593 void AIS_AngleDimension::Compute (const Handle(PrsMgr_PresentationManager3d)& /*thePM*/,
594 const Handle(Prs3d_Presentation)& thePresentation,
595 const Standard_Integer theMode)
597 thePresentation->Clear();
598 mySelectionGeom.Clear (theMode);
605 // Parameters for presentation
606 Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
608 Prs3d_Root::CurrentGroup(thePresentation)->SetPrimitivesAspect (aDimensionAspect->LineAspect()->Aspect());
610 Quantity_Length anArrowLength = aDimensionAspect->ArrowAspect()->Length();
612 // prepare label string and compute its geometrical width
613 Standard_Real aLabelWidth;
614 TCollection_ExtendedString aLabelString = GetValueString (aLabelWidth);
616 // add margins to label width
617 if (aDimensionAspect->IsText3d())
619 aLabelWidth += aDimensionAspect->TextAspect()->Height() * THE_3D_TEXT_MARGIN * 2.0;
622 gp_Pnt aFirstAttach = myCenterPoint.Translated (gp_Vec(myCenterPoint, myFirstPoint).Normalized() * GetFlyout());
623 gp_Pnt aSecondAttach = myCenterPoint.Translated (gp_Vec(myCenterPoint, mySecondPoint).Normalized() * GetFlyout());
625 // Handle user-defined and automatic arrow placement
626 bool isArrowsExternal = false;
627 switch (aDimensionAspect->ArrowOrientation())
629 case Prs3d_DAO_External: isArrowsExternal = true; break;
630 case Prs3d_DAO_Internal: isArrowsExternal = false; break;
633 gp_Vec anAttachVector (aFirstAttach, aSecondAttach);
634 Standard_Real aDimensionWidth = anAttachVector.Magnitude();
636 // add margin to ensure a small tail between text and arrow
637 Standard_Real anArrowMargin = aDimensionAspect->IsText3d()
638 ? aDimensionAspect->TextAspect()->Height() * THE_3D_TEXT_MARGIN
641 Standard_Real anArrowsWidth = (anArrowLength + anArrowMargin) * 2.0;
643 isArrowsExternal = aDimensionWidth < aLabelWidth + anArrowsWidth;
648 //Arrows positions and directions
649 gp_Vec aWPDir = gp_Vec (GetPlane().Axis().Direction());
651 gp_Dir aFirstExtensionDir = aWPDir ^ gp_Vec (myCenterPoint, aFirstAttach);
652 gp_Dir aSecondExtensionDir = aWPDir.Reversed() ^ gp_Vec (myCenterPoint, aSecondAttach);
654 gp_Vec aFirstArrowVec = gp_Vec (aFirstExtensionDir) * anArrowLength;
655 gp_Vec aSecondArrowVec = gp_Vec (aSecondExtensionDir) * anArrowLength;
657 gp_Pnt aFirstArrowBegin (0.0, 0.0, 0.0);
658 gp_Pnt aFirstArrowEnd (0.0, 0.0, 0.0);
659 gp_Pnt aSecondArrowBegin (0.0, 0.0, 0.0);
660 gp_Pnt aSecondArrowEnd (0.0, 0.0, 0.0);
662 if (isArrowsExternal)
664 aFirstArrowVec.Reverse();
665 aSecondArrowVec.Reverse();
668 aFirstArrowBegin = aFirstAttach;
669 aSecondArrowBegin = aSecondAttach;
670 aFirstArrowEnd = aFirstAttach.Translated (-aFirstArrowVec);
671 aSecondArrowEnd = aSecondAttach.Translated (-aSecondArrowVec);
673 Standard_Integer aLabelPosition = LabelPosition_None;
675 // Handle user-defined and automatic text placement
676 switch (aDimensionAspect->TextHorizontalPosition())
678 case Prs3d_DTHP_Left : aLabelPosition |= LabelPosition_Left; break;
679 case Prs3d_DTHP_Right : aLabelPosition |= LabelPosition_Right; break;
680 case Prs3d_DTHP_Center: aLabelPosition |= LabelPosition_HCenter; break;
683 gp_Vec anAttachVector (aFirstAttach, aSecondAttach);
684 Standard_Real aDimensionWidth = anAttachVector.Magnitude();
685 Standard_Real anArrowsWidth = anArrowLength * 2.0;
686 Standard_Real aContentWidth = isArrowsExternal ? aLabelWidth : aLabelWidth + anArrowsWidth;
688 aLabelPosition |= aDimensionWidth < aContentWidth ? LabelPosition_Left : LabelPosition_HCenter;
693 switch (aDimensionAspect->TextVerticalPosition())
695 case Prs3d_DTVP_Above : aLabelPosition |= LabelPosition_Above; break;
696 case Prs3d_DTVP_Below : aLabelPosition |= LabelPosition_Below; break;
697 case Prs3d_DTVP_Center : aLabelPosition |= LabelPosition_VCenter; break;
700 // Group1: stenciling text and the angle dimension arc
701 Prs3d_Root::NewGroup (thePresentation);
703 Standard_Real anExtensionSize = aDimensionAspect->ExtensionSize();
705 Standard_Integer aHPosition = aLabelPosition & LabelPosition_HMask;
710 case LabelPosition_HCenter :
712 Standard_Boolean isLineBreak = aDimensionAspect->TextVerticalPosition() == Prs3d_DTVP_Center
713 && aDimensionAspect->IsText3d();
717 DrawArcWithText (thePresentation,
728 // compute text primitives
729 if (theMode == ComputeMode_All || theMode == ComputeMode_Text)
731 gp_Vec aDimensionDir (aFirstAttach, aSecondAttach);
732 gp_Pnt aTextPos = GetCenterOnArc (aFirstAttach, aSecondAttach, myCenterPoint);
733 gp_Dir aTextDir = aDimensionDir;
735 DrawText (thePresentation,
742 if (theMode == ComputeMode_All || theMode == ComputeMode_Line)
744 DrawArc (thePresentation,
745 isArrowsExternal ? aFirstAttach : aFirstArrowEnd,
746 isArrowsExternal ? aSecondAttach : aSecondArrowEnd,
754 case LabelPosition_Left :
756 DrawExtension (thePresentation,
758 isArrowsExternal ? aFirstArrowEnd : aFirstAttach,
767 case LabelPosition_Right :
769 DrawExtension (thePresentation,
771 isArrowsExternal ? aSecondArrowEnd : aSecondAttach,
781 // dimension arc without text
782 if ((theMode == ComputeMode_All || theMode == ComputeMode_Line) && aHPosition != LabelPosition_HCenter)
784 Prs3d_Root::NewGroup (thePresentation);
786 DrawArc (thePresentation,
787 isArrowsExternal ? aFirstAttach : aFirstArrowEnd,
788 isArrowsExternal ? aSecondAttach : aSecondArrowEnd,
794 // arrows and arrow extensions
795 if (theMode == ComputeMode_All || theMode == ComputeMode_Line)
797 Prs3d_Root::NewGroup (thePresentation);
799 DrawArrow (thePresentation, aFirstArrowBegin, gp_Dir (aFirstArrowVec));
800 DrawArrow (thePresentation, aSecondArrowBegin, gp_Dir (aSecondArrowVec));
803 if ((theMode == ComputeMode_All || theMode == ComputeMode_Line) && isArrowsExternal)
805 Prs3d_Root::NewGroup (thePresentation);
807 if (aHPosition != LabelPosition_Left)
809 DrawExtension (thePresentation,
813 THE_EMPTY_LABEL_STRING,
814 THE_EMPTY_LABEL_WIDTH,
819 if (aHPosition != LabelPosition_Right)
821 DrawExtension (thePresentation,
825 THE_EMPTY_LABEL_STRING,
826 THE_EMPTY_LABEL_WIDTH,
833 if (theMode == ComputeMode_All)
835 Prs3d_Root::NewGroup (thePresentation);
837 Handle(Graphic3d_ArrayOfSegments) aPrimSegments = new Graphic3d_ArrayOfSegments (4);
838 aPrimSegments->AddVertex (myCenterPoint);
839 aPrimSegments->AddVertex (aFirstAttach);
840 aPrimSegments->AddVertex (myCenterPoint);
841 aPrimSegments->AddVertex (aSecondAttach);
843 Handle(Graphic3d_AspectLine3d) aFlyoutStyle = myDrawer->DimensionAspect()->LineAspect()->Aspect();
844 Prs3d_Root::CurrentGroup (thePresentation)->SetPrimitivesAspect (aFlyoutStyle);
845 Prs3d_Root::CurrentGroup (thePresentation)->AddPrimitiveArray (aPrimSegments);
848 myIsComputed = Standard_True;
851 //=======================================================================
852 //function : ComputeFlyoutSelection
853 //purpose : computes selection for flyouts
854 //=======================================================================
855 void AIS_AngleDimension::ComputeFlyoutSelection (const Handle(SelectMgr_Selection)& theSelection,
856 const Handle(SelectMgr_EntityOwner)& theOwner)
858 gp_Pnt aFirstAttach = myCenterPoint.Translated (gp_Vec (myCenterPoint, myFirstPoint).Normalized() * GetFlyout());
859 gp_Pnt aSecondAttach = myCenterPoint.Translated (gp_Vec (myCenterPoint, mySecondPoint).Normalized() * GetFlyout());
861 Handle(Select3D_SensitiveGroup) aSensitiveEntity = new Select3D_SensitiveGroup (theOwner);
862 aSensitiveEntity->Add (new Select3D_SensitiveSegment (theOwner, myCenterPoint, aFirstAttach));
863 aSensitiveEntity->Add (new Select3D_SensitiveSegment (theOwner, myCenterPoint, aSecondAttach));
865 theSelection->Add (aSensitiveEntity);
868 //=======================================================================
869 //function : InitTwoEdgesAngle
871 //=======================================================================
872 Standard_Boolean AIS_AngleDimension::InitTwoEdgesAngle (gp_Pln& theComputedPlane)
874 TopoDS_Edge aFirstEdge = TopoDS::Edge (myFirstShape);
875 TopoDS_Edge aSecondEdge = TopoDS::Edge (mySecondShape);
877 BRepAdaptor_Curve aMakeFirstLine (aFirstEdge);
878 BRepAdaptor_Curve aMakeSecondLine (aSecondEdge);
880 if (aMakeFirstLine.GetType() != GeomAbs_Line || aMakeSecondLine.GetType() != GeomAbs_Line)
882 return Standard_False;
885 Handle(Geom_Line) aFirstLine = new Geom_Line (aMakeFirstLine.Line());
886 Handle(Geom_Line) aSecondLine = new Geom_Line (aMakeSecondLine.Line());
888 gp_Lin aFirstLin = aFirstLine->Lin();
889 gp_Lin aSecondLin = aSecondLine->Lin();
891 Standard_Boolean isParallelLines = Abs (aFirstLin.Angle (aSecondLin) - M_PI) <= Precision::Angular();
893 gp_Pnt aPoint = aFirstLine->Value (0.0);
894 gp_Dir aNormal = isParallelLines
895 ? gp_Vec (aSecondLin.Normal (aPoint).Direction()) ^ gp_Vec (aSecondLin.Direction())
896 : gp_Vec (aFirstLin.Direction()) ^ gp_Vec (aSecondLin.Direction());
898 theComputedPlane = gp_Pln (aPoint, aNormal);
900 // Compute geometry for this plane and edges
901 Standard_Boolean isInfinite1,isInfinite2;
902 gp_Pnt aFirstPoint1, aLastPoint1, aFirstPoint2, aLastPoint2;
903 gp_Lin2d aFirstLin2d, aSecondLin2d;
905 if (!AIS::ComputeGeometry (aFirstEdge, aSecondEdge,
906 aFirstLine, aSecondLine,
907 aFirstPoint1, aLastPoint1,
908 aFirstPoint2, aLastPoint2,
909 isInfinite1, isInfinite2))
911 return Standard_False;
914 if (aFirstLin.Direction().IsParallel (aSecondLin.Direction(), Precision::Angular()))
916 myFirstPoint = aFirstLin.Location();
917 mySecondPoint = ElCLib::Value (ElCLib::Parameter (aFirstLin, myFirstPoint), aSecondLin);
919 if (mySecondPoint.Distance (myFirstPoint) <= Precision::Confusion())
921 mySecondPoint.Translate (gp_Vec (aSecondLin.Direction()) * Abs (GetFlyout()));
924 myCenterPoint.SetXYZ ((myFirstPoint.XYZ() + mySecondPoint.XYZ()) / 2.0);
929 gp_Lin2d aFirstLin2d = ProjLib::Project (theComputedPlane, aFirstLin);
930 gp_Lin2d aSecondLin2d = ProjLib::Project (theComputedPlane, aSecondLin);
932 IntAna2d_AnaIntersection anInt2d (aFirstLin2d, aSecondLin2d);
933 gp_Pnt2d anIntersectPoint;
934 if (!anInt2d.IsDone() || anInt2d.IsEmpty())
936 return Standard_False;
939 anIntersectPoint = gp_Pnt2d (anInt2d.Point(1).Value());
940 myCenterPoint = ElCLib::To3d (theComputedPlane.Position().Ax2(), anIntersectPoint);
942 if (isInfinite1 || isInfinite2)
944 myFirstPoint = myCenterPoint.Translated (gp_Vec (aFirstLin.Direction()) * Abs (GetFlyout()));
945 mySecondPoint = myCenterPoint.Translated (gp_Vec (aSecondLin.Direction()) * Abs (GetFlyout()));
947 return IsValidPoints (myFirstPoint, myCenterPoint, mySecondPoint);
951 // | <- dimension should be here
953 myFirstPoint = myCenterPoint.Distance (aFirstPoint1) > myCenterPoint.Distance (aLastPoint1)
957 mySecondPoint = myCenterPoint.Distance (aFirstPoint2) > myCenterPoint.Distance (aLastPoint2)
962 return IsValidPoints (myFirstPoint, myCenterPoint, mySecondPoint);
965 //=======================================================================
966 //function : InitTwoFacesAngle
967 //purpose : initialization of angle dimension between two faces
968 //=======================================================================
969 Standard_Boolean AIS_AngleDimension::InitTwoFacesAngle()
971 TopoDS_Face aFirstFace = TopoDS::Face (myFirstShape);
972 TopoDS_Face aSecondFace = TopoDS::Face (mySecondShape);
974 gp_Dir aFirstDir, aSecondDir;
975 gp_Pln aFirstPlane, aSecondPlane;
976 Handle(Geom_Surface) aFirstBasisSurf, aSecondBasisSurf;
977 AIS_KindOfSurface aFirstSurfType, aSecondSurfType;
978 Standard_Real aFirstOffset, aSecondOffset;
980 AIS::GetPlaneFromFace (aFirstFace, aFirstPlane,
981 aFirstBasisSurf,aFirstSurfType,aFirstOffset);
983 AIS::GetPlaneFromFace (aSecondFace, aSecondPlane,
984 aSecondBasisSurf, aSecondSurfType, aSecondOffset);
986 if (aFirstSurfType == AIS_KOS_Plane && aSecondSurfType == AIS_KOS_Plane)
989 Handle(Geom_Plane) aFirstPlane = Handle(Geom_Plane)::DownCast (aFirstBasisSurf);
990 Handle(Geom_Plane) aSecondPlane = Handle(Geom_Plane)::DownCast (aSecondBasisSurf);
991 return AIS::InitAngleBetweenPlanarFaces (aFirstFace,
996 && IsValidPoints (myFirstPoint,
1002 // Curvilinear faces angle
1003 return AIS::InitAngleBetweenCurvilinearFaces (aFirstFace,
1010 && IsValidPoints (myFirstPoint,
1016 //=======================================================================
1017 //function : InitTwoFacesAngle
1018 //purpose : initialization of angle dimension between two faces
1019 //=======================================================================
1020 Standard_Boolean AIS_AngleDimension::InitTwoFacesAngle (const gp_Pnt thePointOnFirstFace)
1022 TopoDS_Face aFirstFace = TopoDS::Face (myFirstShape);
1023 TopoDS_Face aSecondFace = TopoDS::Face (mySecondShape);
1025 gp_Dir aFirstDir, aSecondDir;
1026 gp_Pln aFirstPlane, aSecondPlane;
1027 Handle(Geom_Surface) aFirstBasisSurf, aSecondBasisSurf;
1028 AIS_KindOfSurface aFirstSurfType, aSecondSurfType;
1029 Standard_Real aFirstOffset, aSecondOffset;
1031 AIS::GetPlaneFromFace (aFirstFace, aFirstPlane,
1032 aFirstBasisSurf,aFirstSurfType,aFirstOffset);
1034 AIS::GetPlaneFromFace (aSecondFace, aSecondPlane,
1035 aSecondBasisSurf, aSecondSurfType, aSecondOffset);
1037 myFirstPoint = thePointOnFirstFace;
1038 if (aFirstSurfType == AIS_KOS_Plane && aSecondSurfType == AIS_KOS_Plane)
1040 //Planar faces angle
1041 Handle(Geom_Plane) aFirstPlane = Handle(Geom_Plane)::DownCast (aFirstBasisSurf);
1042 Handle(Geom_Plane) aSecondPlane = Handle(Geom_Plane)::DownCast (aSecondBasisSurf);
1043 return AIS::InitAngleBetweenPlanarFaces (aFirstFace,
1049 && IsValidPoints (myFirstPoint,
1055 // Curvilinear faces angle
1056 return AIS::InitAngleBetweenCurvilinearFaces (aFirstFace,
1064 && IsValidPoints (myFirstPoint,
1070 //=======================================================================
1071 //function : InitConeAngle
1072 //purpose : initialization of the cone angle
1073 //=======================================================================
1074 Standard_Boolean AIS_AngleDimension::InitConeAngle()
1076 if (myFirstShape.IsNull())
1078 return Standard_False;
1081 TopoDS_Face aConeShape = TopoDS::Face (myFirstShape);
1085 // A surface from the Face
1086 Handle(Geom_Surface) aSurf;
1087 Handle(Geom_OffsetSurface) aOffsetSurf;
1088 Handle(Geom_ConicalSurface) aConicalSurf;
1089 Handle(Geom_SurfaceOfRevolution) aRevSurf;
1090 Handle(Geom_Line) aLine;
1091 BRepAdaptor_Surface aConeAdaptor (aConeShape);
1093 AIS_KindOfSurface aSurfType;
1094 Standard_Real anOffset = 0.;
1095 Handle(Standard_Type) aType;
1097 Standard_Real aMaxV = aConeAdaptor.FirstVParameter();
1098 Standard_Real aMinV = aConeAdaptor.LastVParameter();
1100 AIS::GetPlaneFromFace (aConeShape, aPln, aSurf, aSurfType, anOffset);
1102 if (aSurfType == AIS_KOS_Revolution)
1104 // Surface of revolution
1105 aRevSurf = Handle(Geom_SurfaceOfRevolution)::DownCast(aSurf);
1106 gp_Lin aLin (aRevSurf->Axis());
1107 Handle(Geom_Curve) aBasisCurve = aRevSurf->BasisCurve();
1108 //Must be a part of line (basis curve should be linear)
1109 if (aBasisCurve ->DynamicType() != STANDARD_TYPE(Geom_Line))
1110 return Standard_False;
1112 gp_Pnt aFirst1 = aConeAdaptor.Value (0., aMinV);
1113 gp_Pnt aLast1 = aConeAdaptor.Value (0., aMaxV);
1114 gp_Vec aVec1 (aFirst1, aLast1);
1116 //Projection <aFirst> on <aLin>
1117 gp_Pnt aFirst2 = ElCLib::Value (ElCLib::Parameter (aLin, aFirst1), aLin);
1118 // Projection <aLast> on <aLin>
1119 gp_Pnt aLast2 = ElCLib::Value (ElCLib::Parameter (aLin, aLast1), aLin);
1121 gp_Vec aVec2 (aFirst2, aLast2);
1123 // Check if two parts of revolution are parallel (it's a cylinder) or normal (it's a circle).
1124 if (aVec1.IsParallel (aVec2, Precision::Angular())
1125 || aVec1.IsNormal (aVec2,Precision::Angular()))
1126 return Standard_False;
1128 gce_MakeCone aMkCone (aRevSurf->Axis(), aFirst1, aLast1);
1129 aCone = aMkCone.Value();
1130 myCenterPoint = aCone.Apex();
1134 aType = aSurf->DynamicType();
1135 if (aType == STANDARD_TYPE(Geom_OffsetSurface) || anOffset > 0.01)
1138 aOffsetSurf = new Geom_OffsetSurface (aSurf, anOffset);
1139 aSurf = aOffsetSurf->Surface();
1140 BRepBuilderAPI_MakeFace aMkFace(aSurf, Precision::Confusion());
1142 if (!aMkFace.IsDone())
1143 return Standard_False;
1144 aConeAdaptor.Initialize (aMkFace.Face());
1146 aCone = aConeAdaptor.Cone();
1147 aConicalSurf = Handle(Geom_ConicalSurface)::DownCast (aSurf);
1148 myCenterPoint = aConicalSurf->Apex();
1151 // A circle where the angle is drawn
1152 Handle(Geom_Curve) aCurve;
1153 Standard_Real aMidV = ( aMinV + aMaxV ) / 2.5;
1154 aCurve = aSurf->VIso (aMidV);
1155 aCircle = Handle(Geom_Circle)::DownCast (aCurve)->Circ();
1157 aCurve = aSurf->VIso(aMaxV);
1158 gp_Circ aCircVmax = Handle(Geom_Circle)::DownCast(aCurve)->Circ();
1159 aCurve = aSurf->VIso(aMinV);
1160 gp_Circ aCircVmin = Handle(Geom_Circle)::DownCast(aCurve)->Circ();
1162 if (aCircVmax.Radius() < aCircVmin.Radius())
1164 gp_Circ aTmpCirc = aCircVmax;
1165 aCircVmax = aCircVmin;
1166 aCircVmin = aTmpCirc;
1169 myFirstPoint = ElCLib::Value (0, aCircle);
1170 mySecondPoint = ElCLib::Value (M_PI, aCircle);
1171 return Standard_True;
1174 //=======================================================================
1175 //function : IsValidPoints
1177 //=======================================================================
1178 Standard_Boolean AIS_AngleDimension::IsValidPoints (const gp_Pnt& theFirstPoint,
1179 const gp_Pnt& theCenterPoint,
1180 const gp_Pnt& theSecondPoint) const
1182 return theFirstPoint.Distance (theCenterPoint) > Precision::Confusion()
1183 && theSecondPoint.Distance (theCenterPoint) > Precision::Confusion()
1184 && gp_Vec (theCenterPoint, theFirstPoint).Angle (
1185 gp_Vec (theCenterPoint, theSecondPoint)) > Precision::Angular();