1 // Created on: 1996-12-05
2 // Created by: Arnaud BOUZY/Odile Olivier
3 // Copyright (c) 1996-1999 Matra Datavision
4 // Copyright (c) 1999-2012 OPEN CASCADE SAS
6 // The content of this file is subject to the Open CASCADE Technology Public
7 // License Version 6.5 (the "License"). You may not use the content of this file
8 // except in compliance with the License. Please obtain a copy of the License
9 // at http://www.opencascade.org and read it completely before using this file.
11 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
12 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
14 // The Original Code and all software distributed under the License is
15 // distributed on an "AS IS" basis, without warranty of any kind, and the
16 // Initial Developer hereby disclaims all such warranties, including without
17 // limitation, any warranties of merchantability, fitness for a particular
18 // purpose or non-infringement. Please see the License for the specific terms
19 // and conditions governing the rights and limitations under the License.
21 #include <AIS_AngleDimension.hxx>
24 #include <AIS_Dimension.hxx>
25 #include <AIS_DimensionOwner.hxx>
26 #include <AIS_Drawer.hxx>
27 #include <BRep_Tool.hxx>
28 #include <BRepBuilderAPI_MakeFace.hxx>
29 #include <BRepAdaptor_Curve.hxx>
30 #include <BRepAdaptor_Surface.hxx>
31 #include <BRepLib_MakeVertex.hxx>
34 #include <DsgPrs_AnglePresentation.hxx>
39 #include <GC_MakeCircle.hxx>
40 #include <GC_MakeConicalSurface.hxx>
41 #include <gce_MakeLin.hxx>
42 #include <gce_MakeLin2d.hxx>
43 #include <gce_MakePln.hxx>
44 #include <gce_MakeCirc.hxx>
45 #include <gce_MakeCone.hxx>
46 #include <Geom2d_Circle.hxx>
47 #include <Geom2d_Curve.hxx>
48 #include <Geom2d_Line.hxx>
49 #include <Geom2dAPI_ExtremaCurveCurve.hxx>
50 #include <GeomAPI.hxx>
51 #include <Geom_Circle.hxx>
52 #include <Geom_Line.hxx>
53 #include <Geom_Plane.hxx>
54 #include <Geom_TrimmedCurve.hxx>
55 #include <Geom_Surface.hxx>
56 #include <Geom_CylindricalSurface.hxx>
57 #include <Geom_ConicalSurface.hxx>
58 #include <Geom_SurfaceOfRevolution.hxx>
59 #include <Geom_SurfaceOfLinearExtrusion.hxx>
60 #include <Geom_OffsetSurface.hxx>
61 #include <GeomAPI_ExtremaCurveCurve.hxx>
62 #include <Graphic3d_ArrayOfSegments.hxx>
63 #include <Graphic3d_AspectLine3d.hxx>
67 #include <gp_Cone.hxx>
70 #include <gp_Pnt2d.hxx>
73 #include <Graphic3d_Group.hxx>
74 #include <Graphic3d_ArrayOfPrimitives.hxx>
75 #include <Graphic3d_ArrayOfPolylines.hxx>
77 #include <IntAna2d_AnaIntersection.hxx>
78 #include <IntAna2d_IntPoint.hxx>
79 #include <IntAna_QuadQuadGeo.hxx>
80 #include <IntAna_ResultType.hxx>
81 #include <Poly_Polygon3D.hxx>
82 #include <Precision.hxx>
83 #include <ProjLib.hxx>
84 #include <Prs3d_ArrowAspect.hxx>
85 #include <Prs3d_DimensionAspect.hxx>
86 #include <Prs3d_Drawer.hxx>
87 #include <Prs3d_Root.hxx>
88 #include <PrsMgr_PresentationManager3d.hxx>
89 #include <Select3D_SensitiveCurve.hxx>
90 #include <Select3D_SensitiveGroup.hxx>
91 #include <Select3D_SensitiveSegment.hxx>
92 #include <SelectMgr_Selection.hxx>
93 #include <Standard_NotImplemented.hxx>
94 #include <Standard_Type.hxx>
95 #include <Standard_Macro.hxx>
96 #include <Standard_DefineHandle.hxx>
98 #include <TColStd_Array1OfReal.hxx>
100 #include <TopExp_Explorer.hxx>
101 #include <TopoDS.hxx>
102 #include <TopoDS_Shape.hxx>
103 #include <TopoDS_Vertex.hxx>
104 #include <UnitsAPI.hxx>
106 IMPLEMENT_STANDARD_HANDLE (AIS_AngleDimension, AIS_Dimension)
107 IMPLEMENT_STANDARD_RTTIEXT (AIS_AngleDimension, AIS_Dimension)
109 //=======================================================================
111 //purpose : Private constructor for default initialization
112 //=======================================================================
114 void AIS_AngleDimension::init()
116 SetKindOfDimension (AIS_KOD_PLANEANGLE);
118 // Default values of units
119 UnitsAPI::SetLocalSystem (UnitsAPI_SI);
120 SetUnitsQuantity ("PLANE ANGLE");
121 SetModelUnits ("rad");
122 SetDisplayUnits ("deg");
123 SetSpecialSymbol (0x00B0);
124 SetDisplaySpecialSymbol (AIS_DSS_After);
125 MakeUnitsDisplayed (Standard_False);
128 //=======================================================================
129 //function : Constructor
130 //purpose : Two edges dimension
131 //=======================================================================
133 AIS_AngleDimension::AIS_AngleDimension (const TopoDS_Edge& theFirstEdge,
134 const TopoDS_Edge& theSecondEdge)
136 myIsFlyoutLines (Standard_True)
140 myFirstShape = theFirstEdge;
141 mySecondShape = theSecondEdge;
144 //=======================================================================
145 //function : Constructor
146 //purpose : Two edges dimension
147 // <thePlane> is used in case of Angle=PI
148 //=======================================================================
150 AIS_AngleDimension::AIS_AngleDimension (const TopoDS_Edge& theFirstEdge,
151 const TopoDS_Edge& theSecondEdge,
152 const gp_Pln& thePlane)
154 myIsFlyoutLines (Standard_True)
158 myFirstShape = theFirstEdge;
159 mySecondShape = theSecondEdge;
160 SetWorkingPlane (thePlane);
163 //=======================================================================
164 //function : Constructor
165 //purpose : Two edges dimension with aspect
166 // <thePlane> is used in case of Angle=PI
167 //=======================================================================
169 AIS_AngleDimension::AIS_AngleDimension (const TopoDS_Edge& theFirstEdge,
170 const TopoDS_Edge& theSecondEdge,
171 const gp_Pln& thePlane,
172 const Handle(Prs3d_DimensionAspect)& theDimensionAspect,
173 const Standard_Real theExtensionSize)
174 : AIS_Dimension (theDimensionAspect,theExtensionSize),
175 myIsFlyoutLines (Standard_True)
178 myFirstShape = theFirstEdge;
179 mySecondShape = theSecondEdge;
180 SetWorkingPlane (thePlane);
183 //=======================================================================
184 //function : Constructor
185 //purpose : Three points dimension
186 //=======================================================================
188 AIS_AngleDimension::AIS_AngleDimension (const gp_Pnt& theFirstPoint,
189 const gp_Pnt& theSecondPoint,
190 const gp_Pnt& theThirdPoint)
192 myIsFlyoutLines (Standard_True)
195 myIsInitialized = Standard_True;
196 myFirstPoint = theFirstPoint;
197 myCenter = theSecondPoint;
198 mySecondPoint = theThirdPoint;
202 //=======================================================================
203 //function : Constructor
204 //purpose : Three points dimension
205 //=======================================================================
207 AIS_AngleDimension::AIS_AngleDimension (const gp_Pnt& theFirstPoint,
208 const gp_Pnt& theSecondPoint,
209 const gp_Pnt& theThirdPoint,
210 const Handle(Prs3d_DimensionAspect)& theDimensionAspect,
211 const Standard_Real theExtensionSize)
212 : AIS_Dimension (theDimensionAspect,theExtensionSize),
213 myIsFlyoutLines (Standard_True)
215 myIsInitialized = Standard_True;
216 myFirstPoint = theFirstPoint;
217 myCenter = theSecondPoint;
218 mySecondPoint = theThirdPoint;
222 //=======================================================================
223 //function : Constructor
224 //purpose : Cone dimension
225 //=======================================================================
227 AIS_AngleDimension::AIS_AngleDimension (const TopoDS_Face& theCone)
229 myIsFlyoutLines (Standard_True)
232 myIsInitialized = Standard_False;
233 myFirstShape = theCone;
237 //=======================================================================
238 //function : Constructor
239 //purpose : Two faces dimension
240 //=======================================================================
242 AIS_AngleDimension::AIS_AngleDimension (const TopoDS_Face& theFirstFace,
243 const TopoDS_Face& theSecondFace,
244 const gp_Ax1& theAxis)
246 myIsFlyoutLines (Standard_True)
249 myIsInitialized = Standard_False;
250 myFirstShape = theFirstFace;
251 mySecondShape = theSecondFace;
254 aPlane.SetAxis (theAxis);
255 SetWorkingPlane (aPlane);
258 //=======================================================================
259 //function : SetFirstShape
261 //=======================================================================
263 void AIS_AngleDimension::SetFirstShape (const TopoDS_Shape& theShape,
264 const Standard_Boolean isSingleShape /*= Standard_False*/)
266 AIS_Dimension::SetFirstShape (theShape);
271 //=======================================================================
272 //function : aboveInBelowCone
273 //purpose : Returns 1 if <theC> center is above of <theCMin> center;
274 // 0 if <theC> center is between <theCMin> and
275 // <theCMax> centers;
276 // -1 if <theC> center is below <theCMax> center.
277 //=======================================================================
279 Standard_Integer AIS_AngleDimension::aboveInBelowCone (const gp_Circ &theCMax,
280 const gp_Circ &theCMin,
283 const Standard_Real aD = theCMax.Location().Distance (theCMin.Location());
284 const Standard_Real aD1 = theCMax.Location().Distance (theC.Location());
285 const Standard_Real aD2 = theCMin.Location().Distance (theC.Location());
287 if (aD >= aD1 && aD >= aD2) return 0;
288 if (aD < aD2 && aD1 < aD2) return -1;
289 if (aD < aD1 && aD2 < aD1) return 1;
293 //=======================================================================
294 //function : initConeAngle
295 //purpose : initialization of the cone angle
296 //=======================================================================
298 Standard_Boolean AIS_AngleDimension::initConeAngle (const TopoDS_Face& theCone)
300 if (theCone.IsNull ())
301 return Standard_False;
306 // A surface from the Face
307 Handle(Geom_Surface) aSurf;
308 Handle(Geom_OffsetSurface) aOffsetSurf;
309 Handle(Geom_ConicalSurface) aConicalSurf;
310 Handle(Geom_SurfaceOfRevolution) aRevSurf;
311 Handle(Geom_Line) aLine;
312 BRepAdaptor_Surface aConeAdaptor (theCone);
314 AIS_KindOfSurface aSurfType;
315 Standard_Real anOffset = 0.;
316 Handle(Standard_Type) aType;
318 Standard_Real aMaxV = aConeAdaptor.FirstVParameter();
319 Standard_Real aMinV = aConeAdaptor.LastVParameter();
321 AIS::GetPlaneFromFace(theCone, aPln, aSurf, aSurfType, anOffset);
323 if (aSurfType == AIS_KOS_Revolution)
325 // Surface of revolution
326 aRevSurf = Handle(Geom_SurfaceOfRevolution)::DownCast(aSurf);
327 gp_Lin aLin (aRevSurf->Axis());
328 Handle(Geom_Curve) aBasisCurve = aRevSurf->BasisCurve();
329 //Must be a part of line (basis curve should be linear)
330 if (aBasisCurve ->DynamicType() != STANDARD_TYPE(Geom_Line))
331 return Standard_False;
333 gp_Pnt aFirst1 = aConeAdaptor.Value (0., aMinV);
334 gp_Pnt aLast1 = aConeAdaptor.Value (0., aMaxV);
335 gp_Vec aVec1 (aFirst1, aLast1);
337 //Projection <aFirst> on <aLin>
338 gp_Pnt aFirst2 = ElCLib::Value (ElCLib::Parameter (aLin, aFirst1), aLin);
339 // Projection <aLast> on <aLin>
340 gp_Pnt aLast2 = ElCLib::Value (ElCLib::Parameter (aLin, aLast1), aLin);
342 gp_Vec aVec2 (aFirst2, aLast2);
344 // Check if two parts of revolution are parallel (it's a cylinder) or normal (it's a circle).
345 if (aVec1.IsParallel (aVec2, Precision::Angular())
346 || aVec1.IsNormal (aVec2,Precision::Angular()))
347 return Standard_False;
349 gce_MakeCone aMkCone (aRevSurf->Axis(), aFirst1, aLast1);
350 aCone = aMkCone.Value();
351 myCenter = aCone.Apex();
355 aType = aSurf->DynamicType();
356 if (aType == STANDARD_TYPE(Geom_OffsetSurface) || anOffset > 0.01)
359 aOffsetSurf = new Geom_OffsetSurface (aSurf, anOffset);
360 aSurf = aOffsetSurf->Surface();
361 BRepBuilderAPI_MakeFace aMkFace(aSurf, Precision::Confusion());
363 if (!aMkFace.IsDone())
364 return Standard_False;
365 aConeAdaptor.Initialize (aMkFace.Face());
367 aCone = aConeAdaptor.Cone();
368 aConicalSurf = Handle(Geom_ConicalSurface)::DownCast (aSurf);
369 myCenter = aConicalSurf->Apex();
372 // A circle where the angle is drawn
373 Handle(Geom_Curve) aCurve;
374 Standard_Real aMidV = ( aMinV + aMaxV ) / 2.5;
375 aCurve = aSurf->VIso (aMidV);
376 aCircle = Handle(Geom_Circle)::DownCast (aCurve)->Circ();
378 aCurve = aSurf->VIso(aMaxV);
379 gp_Circ aCircVmax = Handle(Geom_Circle)::DownCast(aCurve)->Circ();
380 aCurve = aSurf->VIso(aMinV);
381 gp_Circ aCircVmin = Handle(Geom_Circle)::DownCast(aCurve)->Circ();
384 if (aCircVmax.Radius() < aCircVmin.Radius())
386 gp_Circ aTmpCirc = aCircVmax;
387 aCircVmax = aCircVmin;
388 aCircVmin = aTmpCirc;
391 myFirstPoint = ElCLib::Value (0, aCircle);
392 mySecondPoint = ElCLib::Value (M_PI, aCircle);
393 return Standard_True;
396 //=======================================================================
397 //function : initTwoFacesAngle
398 //purpose : initialization of angle dimension between two faces
399 //=======================================================================
401 Standard_Boolean AIS_AngleDimension::initTwoFacesAngle ()
403 TopoDS_Face aFirstFace = TopoDS::Face (myFirstShape);
404 TopoDS_Face aSecondFace = TopoDS::Face (mySecondShape);
405 gp_Dir aFirstDir, aSecondDir;
406 gp_Pln aFirstPlane, aSecondPlane;
407 Handle(Geom_Surface) aFirstBasisSurf, aSecondBasisSurf;
408 AIS_KindOfSurface aFirstSurfType, aSecondSurfType;
409 Standard_Real aFirstOffset, aSecondOffset;
411 AIS::GetPlaneFromFace (aFirstFace, aFirstPlane,
412 aFirstBasisSurf,aFirstSurfType,aFirstOffset);
413 AIS::GetPlaneFromFace (aSecondFace, aSecondPlane,
414 aSecondBasisSurf, aSecondSurfType, aSecondOffset);
416 if (aFirstSurfType == AIS_KOS_Plane)
419 AIS::ComputeAngleBetweenPlanarFaces (aFirstFace,
422 GetWorkingPlane().Axis(),
425 myGeom.myTextPosition,
434 // Curvilinear faces angle
435 Handle(Geom_Plane) aPlane = new Geom_Plane (GetWorkingPlane());
436 AIS::ComputeAngleBetweenCurvilinearFaces (aFirstFace,
442 GetWorkingPlane().Axis(),
445 myGeom.myTextPosition,
452 SetWorkingPlane (aPlane->Pln());
454 return Standard_True;
457 //=======================================================================
458 //function : countDefaultPlane
460 //=======================================================================
462 void AIS_AngleDimension::countDefaultPlane ()
464 if (!myIsInitialized)
466 // Compute normal of the default plane.
467 gp_Vec aVec1(myCenter, myFirstPoint),
468 aVec2(myCenter, mySecondPoint);
469 myDefaultPlane = gp_Pln(myCenter, aVec1^aVec2);
470 // Set computed value to <myWorkingPlane>
471 ResetWorkingPlane ();
474 //=======================================================================
475 //function : computeValue
477 //=======================================================================
479 void AIS_AngleDimension::computeValue ()
481 gp_Vec aVec1 (myCenter, myFirstPoint),
482 aVec2 (myCenter, mySecondPoint);
483 myValue = aVec1.Angle (aVec2);
485 AIS_Dimension::computeValue();
488 //=======================================================================
489 //function : initTwoEdgesAngle
490 //purpose : Fill gp_Pnt fields for further presentation computation
491 // If intersection between two edges doesn't exist
492 // <myIsInitialized> is set to false
493 //=======================================================================
495 Standard_Boolean AIS_AngleDimension::initTwoEdgesAngle ()
497 // Data initialization
498 TopoDS_Edge aFirstEdge = TopoDS::Edge (myFirstShape);
499 TopoDS_Edge aSecondEdge = TopoDS::Edge (mySecondShape);
500 BRepAdaptor_Curve aMakeFirstLine (aFirstEdge);
501 BRepAdaptor_Curve aMakeSecondLine (aSecondEdge);
503 if (aMakeFirstLine.GetType() != GeomAbs_Line || aMakeSecondLine.GetType() != GeomAbs_Line)
505 return Standard_False;
508 Handle(Geom_Line) aFirstLine = new Geom_Line (aMakeFirstLine.Line());
509 Handle(Geom_Line) aSecondLine = new Geom_Line (aMakeSecondLine.Line());
511 gp_Lin aFirstLin = aFirstLine->Lin ();
512 gp_Lin aSecondLin = aSecondLine->Lin ();
513 gp_Lin2d aFirstLin2d, aSecondLin2d;
514 Standard_Boolean isParallelLines = aFirstLin.Direction().IsParallel (aSecondLin.Direction(), Precision::Angular());
515 Standard_Boolean isSameLines = isParallelLines && aFirstLin.Distance (aSecondLin.Location()) <= Precision::Confusion();
516 // In case where we can't compute plane automatically
517 if ((isParallelLines || isSameLines) && !myIsWorkingPlaneCustom)
519 return Standard_False;
524 /// PART 1 is for automatic plane computation from two edges if it is possible
526 if (!myIsWorkingPlaneCustom)
528 gp_Pnt aPoint = aFirstLine->Value (0.);
529 gp_Dir aNormal = isParallelLines
530 ? gp_Vec(aSecondLin.Normal (aPoint).Direction()) ^ gp_Vec (aSecondLin.Direction())
531 : gp_Vec (aFirstLin.Direction()) ^ gp_Vec (aSecondLin.Direction());
532 aPlane = gp_Pln (aPoint, aNormal);
533 resetWorkingPlane (aPlane);
537 aPlane = GetWorkingPlane();
540 // Compute geometry for this plane and edges
541 Standard_Boolean isInfinite1,isInfinite2;
542 gp_Pnt aFirstPoint1, aLastPoint1, aFirstPoint2, aLastPoint2;
543 Standard_Integer anExtIndex = -1;
544 Handle(Geom_Curve) anExtCurve;
545 Handle(Geom_Plane) aGeomPlane = new Geom_Plane (aPlane);
546 if (!AIS::ComputeGeometry (aFirstEdge, aSecondEdge,
548 aFirstLine, aSecondLine,
549 aFirstPoint1, aLastPoint1,
550 aFirstPoint2, aLastPoint2,
552 isInfinite1, isInfinite2,
555 return Standard_False;
558 // Check if both edges are on this plane
559 if (!anExtCurve.IsNull())
561 if (anExtIndex == 1) // First curve is out of the plane
563 // Project curve on the plane
564 if (myIsWorkingPlaneCustom)
566 aFirstLin2d = ProjLib::Project (aPlane, aFirstLin);
567 aFirstLin = ElCLib::To3d (aPlane.Position().Ax2(), aFirstLin2d);
571 aFirstLin.Translate (gp_Vec (aFirstLin.Location(), aSecondLin.Location()));
574 aFirstLine = new Geom_Line (aFirstLin);
576 else if (anExtIndex == 2) // Second curve is out of the plane
578 if (myIsWorkingPlaneCustom)
580 aSecondLin2d = ProjLib::Project (aPlane, aSecondLin);
581 aSecondLin = ElCLib::To3d (aPlane.Position().Ax2(), aSecondLin2d);
585 aSecondLin.Translate (gp_Vec (aSecondLin.Location(), aFirstLin.Location()));
588 aSecondLine = new Geom_Line (aSecondLin);
592 /// PART 2 is for dimension computation using the working plane
594 if (aFirstLin.Direction ().IsParallel (aSecondLin.Direction (), Precision::Angular ()))
597 isSameLines = aFirstLin.Distance(aSecondLin.Location()) <= Precision::Confusion();
599 return Standard_False;
601 myFirstPoint = aFirstLin.Location();
602 mySecondPoint = ElCLib::Value (ElCLib::Parameter (aFirstLin, myFirstPoint), aSecondLin);
603 if (mySecondPoint.Distance (mySecondPoint) <= Precision::Confusion ())
604 mySecondPoint.Translate (gp_Vec (aSecondLin.Direction ())*Abs(GetFlyout()));
605 myCenter.SetXYZ( (myFirstPoint.XYZ() + mySecondPoint.XYZ()) / 2. );
610 aFirstLin2d = ProjLib::Project (aPlane, aFirstLin);
611 aSecondLin2d = ProjLib::Project (aPlane, aSecondLin);
613 IntAna2d_AnaIntersection anInt2d (aFirstLin2d, aSecondLin2d);
614 gp_Pnt2d anIntersectPoint;
615 if (!anInt2d.IsDone() || anInt2d.IsEmpty())
617 return Standard_False;
620 anIntersectPoint = gp_Pnt2d (anInt2d.Point(1).Value());
621 myCenter = ElCLib::To3d(aPlane.Position().Ax2(), anIntersectPoint);
623 if (isInfinite1 || isInfinite2)
625 myFirstPoint = myCenter.Translated (gp_Vec (aFirstLin.Direction())*Abs (GetFlyout()));
626 mySecondPoint = myCenter.Translated (gp_Vec (aSecondLin.Direction())*Abs (GetFlyout()));
627 return Standard_True;
631 // | <- dimension should be here
633 myFirstPoint = myCenter.Distance (aFirstPoint1) > myCenter.Distance (aLastPoint1) ? aFirstPoint1 : aLastPoint1;
634 mySecondPoint = myCenter.Distance (aFirstPoint2) > myCenter.Distance (aLastPoint2) ? aFirstPoint2 : aLastPoint2;
636 return Standard_True;
639 //=======================================================================
640 //function : canTextBeInCenter
641 //purpose : Auxiliary method to arrange text and arrows
642 //=======================================================================
644 Standard_Boolean AIS_AngleDimension::canTextBeInCenter (const gp_Pnt& theFirstAttach,
645 const gp_Pnt& theSecondAttach,
646 const Quantity_Length& theTextLength,
647 const Quantity_Length& theArrowLength)
649 gp_Vec anAttachVector (theFirstAttach, theSecondAttach);
650 Standard_Real aValue = anAttachVector.Magnitude();
651 return (aValue < theTextLength + 2.*theArrowLength) ? Standard_False : Standard_True;
654 //=======================================================================
655 //function: getCenterOnArc
657 //=======================================================================
658 gp_Pnt AIS_AngleDimension::getCenterOnArc (const gp_Pnt& theFirstAttach,
659 const gp_Pnt& theSecondAttach)
661 gp_Pnt2d aCenter2d = ProjLib::Project (GetWorkingPlane(), myCenter),
662 aFirstAttach2d = ProjLib::Project (GetWorkingPlane(), theFirstAttach),
663 aSecondAttach2d = ProjLib::Project (GetWorkingPlane(), theSecondAttach);
664 gp_Lin2d anAttachLine2d = gce_MakeLin2d (aFirstAttach2d, aSecondAttach2d);
666 // Getting text center
667 gp_Pnt2d aTextCenterPnt = ElCLib::Value ((ElCLib::Parameter (anAttachLine2d, aFirstAttach2d) + ElCLib::Parameter (anAttachLine2d, aSecondAttach2d)) / 2., anAttachLine2d);
668 gp_Lin2d aCenterToTextCenterLin = gce_MakeLin2d (aCenter2d, aTextCenterPnt);
671 Standard_Real aRadius = theFirstAttach.Distance (myCenter);
672 gp_Circ2d aCircle (gp_Ax22d (aCenter2d, gp_Dir2d (1, 0)), aRadius);
674 // Getting text position in the center of arc
675 IntAna2d_AnaIntersection anInt2d (aCenterToTextCenterLin, aCircle);
676 gp_Pnt2d aTextCenterOnArc2d;
677 if (anInt2d.IsDone())
678 if (!anInt2d.IsEmpty())
679 aTextCenterOnArc2d = gp_Pnt2d (anInt2d.Point (1).Value());
680 gp_Pnt aCenterOnArc = ElCLib::To3d (GetWorkingPlane().Position().Ax2(), aTextCenterOnArc2d);
684 //=======================================================================
685 //function: drawArcWithText
687 //=======================================================================
689 void AIS_AngleDimension::drawArcWithText (const Handle(Prs3d_Presentation)& thePresentation,
690 const gp_Pnt& theFirstAttach,
691 const gp_Pnt& theSecondAttach,
692 const TCollection_ExtendedString& theText,
693 const AIS_DimensionDisplayMode theMode)
695 gp_Pnt2d aCenter2d = ProjLib::Project (GetWorkingPlane(), myCenter),
696 aFirstAttach2d = ProjLib::Project (GetWorkingPlane(), theFirstAttach),
697 aSecondAttach2d = ProjLib::Project (GetWorkingPlane(), theSecondAttach);
698 gp_Lin2d anAttachLine2d = gce_MakeLin2d (aFirstAttach2d, aSecondAttach2d);
700 // Getting text center
701 gp_Pnt2d aTextCenterPnt = ElCLib::Value ((ElCLib::Parameter (anAttachLine2d, aFirstAttach2d) + ElCLib::Parameter (anAttachLine2d, aSecondAttach2d)) / 2., anAttachLine2d);
702 gp_Lin2d aCenterToTextCenterLin = gce_MakeLin2d (aCenter2d, aTextCenterPnt);
705 Standard_Real aRadius = theFirstAttach.Distance (myCenter);
706 gp_Circ2d aCircle (gp_Ax22d (aCenter2d, gp_Dir2d (1, 0)), aRadius);
708 // Getting text position in the center of arc
709 IntAna2d_AnaIntersection anInt2d (aCenterToTextCenterLin, aCircle);
710 gp_Pnt2d aTextCenterOnArc2d;
711 if (anInt2d.IsDone())
712 if (!anInt2d.IsEmpty())
713 aTextCenterOnArc2d = gp_Pnt2d (anInt2d.Point (1).Value());
714 myGeom.myTextPosition = ElCLib::To3d (GetWorkingPlane().Position().Ax2(), aTextCenterOnArc2d);
717 gp_Vec aVec (theFirstAttach, theSecondAttach);
718 Standard_Real aTextWidth = drawText (thePresentation,
719 myIsTextReversed ? aVec.Reversed() : aVec,
722 // Getting text begin and end points
723 gp_Pnt2d aTextBeginPnt = ElCLib::Value ((ElCLib::Parameter (anAttachLine2d, aFirstAttach2d) +
724 ElCLib::Parameter (anAttachLine2d, aSecondAttach2d) -
725 aTextWidth) / 2., anAttachLine2d),
726 aTextEndPnt = ElCLib::Value (ElCLib::Parameter (anAttachLine2d,aTextBeginPnt) + aTextWidth, anAttachLine2d);
729 gp_Lin2d aCenterToTextBeginLin = gce_MakeLin2d (aCenter2d, aTextBeginPnt),
730 aCenterToTextEndLin = gce_MakeLin2d (aCenter2d, aTextEndPnt);
732 // Text begin and end on the dimension arc
733 gp_Pnt2d aTextBeginOnArc2d, aTextEndOnArc2d;
734 anInt2d.Perform (aCenterToTextBeginLin, aCircle);
735 if (anInt2d.IsDone())
736 if (!anInt2d.IsEmpty())
737 aTextBeginOnArc2d = gp_Pnt2d (anInt2d.Point (1).Value());
739 anInt2d.Perform (aCenterToTextEndLin, aCircle);
740 if (anInt2d.IsDone())
741 if (!anInt2d.IsEmpty())
742 aTextEndOnArc2d = gp_Pnt2d (anInt2d.Point (1).Value());
744 gp_Pnt aTextBeginOnArc = ElCLib::To3d (GetWorkingPlane().Position().Ax2(), aTextBeginOnArc2d);
745 gp_Pnt aTextEndOnArc = ElCLib::To3d (GetWorkingPlane().Position().Ax2(), aTextEndOnArc2d);
748 if (theMode != AIS_DDM_Text)
750 drawArc (thePresentation, theFirstAttach, aTextBeginOnArc, myCenter, aRadius, theMode);
751 drawArc (thePresentation, aTextEndOnArc, theSecondAttach, myCenter, aRadius, theMode);
756 //=======================================================================
758 //purpose : draws the arc between two attach points
759 //=======================================================================
761 void AIS_AngleDimension::drawArc (const Handle(Prs3d_Presentation)& thePresentation,
762 const gp_Pnt& theFirstAttach,
763 const gp_Pnt& theSecondAttach,
764 const gp_Pnt& theCenter,
765 const Standard_Real theRadius,
766 const AIS_DimensionDisplayMode theMode)
768 Handle(SelectMgr_EntityOwner) anEmptyOwner;
769 Prs3d_Root::CurrentGroup (thePresentation)->
770 SetPrimitivesAspect(myDrawer->DimensionAspect()->LineAspect()->Aspect());
772 gp_Vec aCenterToFirstVec (theCenter,theFirstAttach);
773 gp_Vec aCenterToSecondVec (theCenter,theSecondAttach);
774 gp_Dir aCenterToFirstDir (aCenterToFirstVec);
775 gp_Dir aPlaneNormal = GetWorkingPlane().Axis().Direction();
776 gp_Dir aCenterToSecondDir = aPlaneNormal.Crossed (aCenterToFirstDir);
778 const Standard_Real anAngle = aCenterToFirstVec.Angle(aCenterToSecondVec);
779 const Standard_Integer aPointsOnArc = Max (4 , Standard_Integer (50. * anAngle / M_PI));
780 const Standard_Real anAngleStep = anAngle / (aPointsOnArc - 1);
781 TColgp_Array1OfPnt aPointArray (0,aPointsOnArc-1);
782 Handle(Graphic3d_ArrayOfPolylines) aPrimSegments = new Graphic3d_ArrayOfPolylines (aPointsOnArc,2);
783 aPrimSegments->AddVertex (theFirstAttach);
784 aPointArray.SetValue(0, theFirstAttach);
785 gp_Pnt aPoint = theFirstAttach;
788 for (Standard_Integer anI = 1; anI < aPointsOnArc - 1; ++anI)
790 aVector = (gp_Vec(aCenterToFirstDir) * Cos ( (anI - 1) * anAngleStep) + gp_Vec(aCenterToSecondDir) * Sin ( (anI - 1) * anAngleStep)) * theRadius;
791 aPoint = theCenter.Translated(aVector);
792 aPrimSegments->AddVertex(aPoint);
793 aPointArray.SetValue (anI,aPoint);
795 aPrimSegments->AddVertex (theSecondAttach);
796 aPointArray.SetValue (aPointsOnArc - 1,theSecondAttach);
798 // Fill sensitive list
799 myGeom.mySensitiveSegments.Append(new Select3D_SensitiveCurve(anEmptyOwner,aPointArray));
801 // Fill display presentation
802 if (!myDrawer->DimensionAspect()->IsText3d() && theMode == AIS_DDM_All)
804 Prs3d_Root::CurrentGroup (thePresentation)->SetStencilTestOptions (Standard_True);
806 Prs3d_Root::CurrentGroup (thePresentation)->AddPrimitiveArray (aPrimSegments);
807 if (!myDrawer->DimensionAspect()->IsText3d() && theMode == AIS_DDM_All)
809 Prs3d_Root::CurrentGroup (thePresentation)->SetStencilTestOptions (Standard_False);
813 //=======================================================================
815 //purpose : Having three gp_Pnt points compute presentation
816 //=======================================================================
818 void AIS_AngleDimension::Compute (const Handle(PrsMgr_PresentationManager3d)& /*thePM*/,
819 const Handle(Prs3d_Presentation)& thePresentation,
820 const Standard_Integer theMode)
822 thePresentation->Clear();
823 myGeom.mySensitiveSegments.Clear();
824 Handle(SelectMgr_EntityOwner) anEmptyOwner;
826 if (!myIsInitialized)
828 if (myShapesNumber == 1)
830 myIsInitialized = initConeAngle (TopoDS::Face (myFirstShape));
832 else if (myShapesNumber == 2)
834 switch (myFirstShape.ShapeType())
838 myIsInitialized = initTwoFacesAngle ();
843 myIsInitialized = initTwoEdgesAngle ();
854 // If initialization failed
855 if (!myIsInitialized)
858 // Parameters for presentation
859 Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
860 Prs3d_Root::CurrentGroup(thePresentation)->
861 SetPrimitivesAspect(aDimensionAspect->LineAspect()->Aspect());
862 Quantity_Length anArrowLength = aDimensionAspect->ArrowAspect()->Length();
863 if (!myIsValueCustom)
865 TCollection_ExtendedString aValueString;
866 Standard_Real aTextLength;
867 getTextWidthAndString (aTextLength, aValueString);
868 if (!myIsWorkingPlaneCustom)
870 gp_Pnt aFirstAttach = myCenter.Translated (gp_Vec(myCenter, myFirstPoint).Normalized() * GetFlyout());
871 gp_Pnt aSecondAttach = myCenter.Translated (gp_Vec(myCenter, mySecondPoint).Normalized() * GetFlyout());
872 // Attach points and radius
873 if (aDimensionAspect->HorizontalTextAlignment () == Prs3d_HTA_Center)
875 aDimensionAspect->SetArrowOrientation (Prs3d_DAO_Internal);
877 if (!canTextBeInCenter (aFirstAttach, aSecondAttach, aTextLength, anArrowLength))
879 aDimensionAspect->SetArrowOrientation (Prs3d_DAO_External);
880 aDimensionAspect->SetHorizontalTextAlignment (Prs3d_HTA_Left);
884 aDimensionAspect->SetArrowOrientation (Prs3d_DAO_External);
886 //Arrows positions and directions
887 gp_Vec aFirstArrowVec = (gp_Vec(myCenter, aFirstAttach)^gp_Vec(GetWorkingPlane().Axis().Direction())).Normalized().Reversed()*anArrowLength;
888 gp_Vec aSecondArrowVec = (gp_Vec(myCenter, aSecondAttach)^gp_Vec(GetWorkingPlane().Axis().Direction())).Normalized()*anArrowLength;
890 gp_Pnt aFirstArrowBegin,
895 if (aDimensionAspect->GetArrowOrientation() == Prs3d_DAO_External)
897 aFirstArrowVec.Reverse();
898 aSecondArrowVec.Reverse();
900 aFirstArrowBegin = aFirstAttach.Translated (aFirstArrowVec);
901 aFirstArrowEnd = aFirstAttach;
902 aSecondArrowBegin = aSecondAttach;
903 aSecondArrowEnd = aSecondAttach.Translated (aSecondArrowVec);
907 aFirstArrowBegin = aFirstAttach;
908 aFirstArrowEnd = aFirstAttach.Translated (aFirstArrowVec);
909 aSecondArrowBegin = aSecondAttach.Translated (aSecondArrowVec);
910 aSecondArrowEnd = aSecondAttach;
914 Handle(Graphic3d_ArrayOfSegments) aPrimSegments;
915 Standard_Boolean isTextInCenter = aDimensionAspect->VerticalTextAlignment() == Prs3d_VTA_Center;
916 if (aDimensionAspect->HorizontalTextAlignment() == Prs3d_HTA_Center)
918 // Important! Current implementation doesn't draw the extensions here
919 aPrimSegments = new Graphic3d_ArrayOfSegments (4);
920 // Get text begin and end positions (text is positioned in the center between two attach points)
921 gp_Pnt aTextBeginOnArc, aTextEndOnArc, anArcCenter;
922 if (isTextInCenter && aDimensionAspect->IsText3d())
924 drawArcWithText (thePresentation, aFirstAttach, aSecondAttach, aValueString, (AIS_DimensionDisplayMode)theMode);
928 gp_Vec aTextDir (aFirstArrowEnd, aSecondArrowBegin);
929 myGeom.myTextPosition = getCenterOnArc (aFirstArrowEnd, aSecondArrowBegin);
930 drawText (thePresentation,
931 myIsTextReversed ? aTextDir.Reversed() : aTextDir,
932 aValueString, (AIS_DimensionDisplayMode)theMode);
933 if (theMode != AIS_DDM_Text)
934 drawArc (thePresentation, aFirstArrowEnd, aSecondArrowBegin, myCenter, Abs (GetFlyout()), (AIS_DimensionDisplayMode)theMode);
939 // Lines for extensions
940 gp_Lin aLeftExtension (aFirstAttach,gp_Dir(aFirstArrowVec));
941 gp_Lin aRightExtension (aSecondAttach, gp_Dir(aSecondArrowVec));
942 aPrimSegments = new Graphic3d_ArrayOfSegments (6);
944 if (aDimensionAspect->HorizontalTextAlignment() == Prs3d_HTA_Left)
946 aStartPoint = aFirstArrowBegin;
948 aPrimSegments->AddVertex (aSecondArrowEnd);
949 aPrimSegments->AddVertex (aSecondArrowEnd.Translated(gp_Vec(aRightExtension.Direction())*anArrowLength));
950 myGeom.mySensitiveSegments.Append (new Select3D_SensitiveSegment(anEmptyOwner,
952 aSecondArrowEnd.Translated(gp_Vec(aRightExtension.Direction())*anArrowLength)));
955 drawExtensionWithText (thePresentation, aStartPoint, aLeftExtension, aValueString, (AIS_DimensionDisplayMode)theMode);
957 else // Prs3d_HTA_Right
959 aStartPoint = aSecondArrowEnd;
961 aPrimSegments->AddVertex (aFirstArrowBegin);
962 aPrimSegments->AddVertex (aFirstArrowBegin.Translated (gp_Vec (aLeftExtension.Direction()) * anArrowLength));
963 myGeom.mySensitiveSegments.Append (new Select3D_SensitiveSegment(anEmptyOwner,
965 aFirstArrowBegin.Translated (gp_Vec (aLeftExtension.Direction()) * anArrowLength)));
968 drawExtensionWithText (thePresentation, aStartPoint, aRightExtension, aValueString, (AIS_DimensionDisplayMode)theMode);
971 if (theMode != AIS_DDM_Text)
974 drawArc (thePresentation, aFirstArrowEnd, aSecondArrowBegin, myCenter, Abs(GetFlyout ()), (AIS_DimensionDisplayMode)theMode);
978 // Draw flyout lines and arrows in new group.
979 Prs3d_Root::NewGroup (thePresentation)
980 ->SetPrimitivesAspect (myDrawer->DimensionAspect()->LineAspect()->Aspect());
981 if (theMode == AIS_DDM_All && myIsFlyoutLines)
983 aPrimSegments->AddVertex (myCenter);
984 aPrimSegments->AddVertex (aFirstAttach);
985 aPrimSegments->AddVertex (myCenter);
986 aPrimSegments->AddVertex (aSecondAttach);
988 if (theMode != AIS_DDM_Text)
990 Prs3d_Root::CurrentGroup (thePresentation)->AddPrimitiveArray (aPrimSegments);
991 drawArrow (thePresentation, aFirstAttach, gp_Dir (aFirstArrowVec));
992 drawArrow (thePresentation, aSecondAttach, gp_Dir (aSecondArrowVec));
995 setComputed (Standard_True);
998 //=======================================================================
999 //function : computeFlyoutSelection
1000 //purpose : computes selection for flyouts
1001 //=======================================================================
1003 void AIS_AngleDimension::computeFlyoutSelection (const Handle(SelectMgr_Selection)& theSelection,
1004 const Handle(AIS_DimensionOwner)& theOwner)
1006 if (!myIsFlyoutLines)
1009 gp_Pnt aFirstAttach = myCenter.Translated (gp_Vec (myCenter, myFirstPoint).Normalized() * GetFlyout());
1010 gp_Pnt aSecondAttach = myCenter.Translated (gp_Vec (myCenter, mySecondPoint).Normalized() * GetFlyout());
1011 Handle(Select3D_SensitiveGroup) aSensitiveEntity = new Select3D_SensitiveGroup (theOwner);
1012 aSensitiveEntity->Add (new Select3D_SensitiveSegment (theOwner, myCenter, aFirstAttach));
1013 aSensitiveEntity->Add (new Select3D_SensitiveSegment (theOwner, myCenter, aSecondAttach));
1014 theSelection->Add (aSensitiveEntity);