0024428: Implementation of LGPL license
[occt.git] / src / AIS / AIS_AngleDimension.cxx
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
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
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.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17 #include <AIS_AngleDimension.hxx>
18
19 #include <AIS.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>
26 #include <ElCLib.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>
52
53 IMPLEMENT_STANDARD_HANDLE (AIS_AngleDimension, AIS_Dimension)
54 IMPLEMENT_STANDARD_RTTIEXT (AIS_AngleDimension, AIS_Dimension)
55
56 namespace
57 {
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;
62 };
63
64 //=======================================================================
65 //function : Constructor
66 //purpose  : 
67 //=======================================================================
68 AIS_AngleDimension::AIS_AngleDimension (const TopoDS_Edge& theFirstEdge,
69                                         const TopoDS_Edge& theSecondEdge)
70 : AIS_Dimension (AIS_KOD_PLANEANGLE)
71 {
72   Init();
73   SetMeasuredGeometry (theFirstEdge, theSecondEdge);
74 }
75
76 //=======================================================================
77 //function : Constructor
78 //purpose  : 
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)
84 {
85   Init();
86   SetMeasuredGeometry (theFirstPoint, theSecondPoint, theThirdPoint);
87 }
88
89 //=======================================================================
90 //function : Constructor
91 //purpose  : 
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)
97 {
98   Init();
99   SetMeasuredGeometry (theFirstVertex, theSecondVertex, theThirdVertex);
100 }
101
102 //=======================================================================
103 //function : Constructor
104 //purpose  : 
105 //=======================================================================
106 AIS_AngleDimension::AIS_AngleDimension (const TopoDS_Face& theCone)
107 : AIS_Dimension (AIS_KOD_PLANEANGLE)
108 {
109   Init();
110   SetMeasuredGeometry (theCone);
111 }
112
113 //=======================================================================
114 //function : Constructor
115 //purpose  : 
116 //=======================================================================
117 AIS_AngleDimension::AIS_AngleDimension (const TopoDS_Face& theFirstFace,
118                                         const TopoDS_Face& theSecondFace)
119 : AIS_Dimension (AIS_KOD_PLANEANGLE)
120 {
121   Init();
122   SetMeasuredGeometry (theFirstFace, theSecondFace);
123 }
124
125 //=======================================================================
126 //function : Constructor
127 //purpose  : 
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)
133 {
134   Init();
135   SetMeasuredGeometry (theFirstFace, theSecondFace, thePoint);
136 }
137
138 //=======================================================================
139 //function : SetMeasuredGeometry
140 //purpose  : 
141 //=======================================================================
142 void AIS_AngleDimension::SetMeasuredGeometry (const TopoDS_Edge& theFirstEdge,
143                                               const TopoDS_Edge& theSecondEdge)
144 {
145   gp_Pln aComputedPlane;
146
147   myFirstShape   = theFirstEdge;
148   mySecondShape  = theSecondEdge;
149   myThirdShape   = TopoDS_Shape();
150   myGeometryType = GeometryType_Edges;
151   myIsValid      = InitTwoEdgesAngle (aComputedPlane);
152
153   if (myIsValid && !myIsPlaneCustom)
154   {
155     myPlane = aComputedPlane;
156   }
157
158   myIsValid &= CheckPlane (myPlane);
159
160   SetToUpdate();
161 }
162
163 //=======================================================================
164 //function : SetMeasuredGeometry
165 //purpose  : 
166 //=======================================================================
167 void AIS_AngleDimension::SetMeasuredGeometry (const gp_Pnt& theFirstPoint,
168                                               const gp_Pnt& theSecondPoint,
169                                               const gp_Pnt& theThirdPoint)
170 {
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);
179
180   if (myIsValid && !myIsPlaneCustom)
181   {
182     ComputePlane();
183   }
184
185   myIsValid &= CheckPlane (myPlane);
186
187   SetToUpdate();
188 }
189
190 //=======================================================================
191 //function : SetMeasuredGeometry
192 //purpose  : 
193 //=======================================================================
194 void AIS_AngleDimension::SetMeasuredGeometry (const TopoDS_Vertex& theFirstVertex,
195                                               const TopoDS_Vertex& theSecondVertex,
196                                               const TopoDS_Vertex& theThirdVertex)
197 {
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);
206
207   if (myIsValid && !myIsPlaneCustom)
208   {
209     ComputePlane();
210   }
211
212   myIsValid &= CheckPlane (myPlane);
213
214   SetToUpdate();
215 }
216
217 //=======================================================================
218 //function : SetMeasuredGeometry
219 //purpose  : 
220 //=======================================================================
221 void AIS_AngleDimension::SetMeasuredGeometry (const TopoDS_Face& theCone)
222 {
223   myFirstShape   = theCone;
224   mySecondShape  = TopoDS_Shape();
225   myThirdShape   = TopoDS_Shape();
226   myGeometryType = GeometryType_Face;
227   myIsValid      = InitConeAngle();
228
229   if (myIsValid && !myIsPlaneCustom)
230   {
231     ComputePlane();
232   }
233
234   myIsValid &= CheckPlane (myPlane);
235
236   SetToUpdate();
237 }
238
239 //=======================================================================
240 //function : SetMeasuredGeometry
241 //purpose  : 
242 //=======================================================================
243 void AIS_AngleDimension::SetMeasuredGeometry (const TopoDS_Face& theFirstFace,
244                                               const TopoDS_Face& theSecondFace)
245 {
246   myFirstShape   = theFirstFace;
247   mySecondShape  = theSecondFace;
248   myThirdShape   = TopoDS_Shape();
249   myGeometryType = GeometryType_Faces;
250   myIsValid      = InitTwoFacesAngle();
251
252   if (myIsValid && !myIsPlaneCustom)
253   {
254     ComputePlane();
255   }
256
257   myIsValid &= CheckPlane (myPlane);
258
259   SetToUpdate();
260 }
261
262 //=======================================================================
263 //function : SetMeasuredGeometry
264 //purpose  : 
265 //=======================================================================
266 void AIS_AngleDimension::SetMeasuredGeometry (const TopoDS_Face& theFirstFace,
267                                               const TopoDS_Face& theSecondFace,
268                                               const gp_Pnt& thePoint)
269 {
270   myFirstShape   = theFirstFace;
271   mySecondShape  = theSecondFace;
272   myThirdShape   = TopoDS_Shape();
273   myGeometryType = GeometryType_Faces;
274   myIsValid      = InitTwoFacesAngle (thePoint);
275
276   if (myIsValid && !myIsPlaneCustom)
277   {
278     ComputePlane();
279   }
280
281   myIsValid &= CheckPlane (myPlane);
282
283   SetToUpdate();
284 }
285
286 //=======================================================================
287 //function : Init
288 //purpose  : 
289 //=======================================================================
290 void AIS_AngleDimension::Init()
291 {
292   SetSpecialSymbol (THE_DEGREE_SYMBOL);
293   SetDisplaySpecialSymbol (AIS_DSS_After);
294   SetFlyout (15.0);
295 }
296
297 //=======================================================================
298 //function: GetCenterOnArc
299 //purpose :
300 //=======================================================================
301 gp_Pnt AIS_AngleDimension::GetCenterOnArc (const gp_Pnt& theFirstAttach,
302                                            const gp_Pnt& theSecondAttach,
303                                            const gp_Pnt& theCenter)
304 {
305   // construct plane where the circle and the arc are located
306   gce_MakePln aConstructPlane (theFirstAttach, theSecondAttach, theCenter);
307   if (!aConstructPlane.IsDone())
308   {
309     return gp::Origin();
310   }
311   
312   gp_Pln aPlane = aConstructPlane.Value();
313
314   Standard_Real aRadius = theFirstAttach.Distance (theCenter);
315
316   // construct circle forming the arc
317   gce_MakeCirc aConstructCircle (theCenter, aPlane, aRadius);
318   if (!aConstructCircle.IsDone())
319   {
320     return gp::Origin();
321   }
322
323   gp_Circ aCircle = aConstructCircle.Value();
324
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);
329
330   return ElCLib::Value ((aParamBeg + aParamEnd) * 0.5, aCircle);
331 }
332
333 //=======================================================================
334 //function : DrawArc
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)
343 {
344   // construct plane where the circle and the arc are located
345   gce_MakePln aConstructPlane (theFirstAttach, theSecondAttach, theCenter);
346   if (!aConstructPlane.IsDone())
347   {
348     return;
349   }
350
351   gp_Pln aPlane = aConstructPlane.Value();
352
353   // construct circle forming the arc
354   gce_MakeCirc aConstructCircle (theCenter, aPlane, theRadius);
355   if (!aConstructCircle.IsDone())
356   {
357     return;
358   }
359
360   gp_Circ aCircle = aConstructCircle.Value();
361
362   // construct the arc
363   GC_MakeArcOfCircle aConstructArc (aCircle, theFirstAttach, theSecondAttach, Standard_True);
364   if (!aConstructArc.IsDone())
365   {
366     return;
367   }
368
369   // generate points with specified deflection
370   const Handle(Geom_TrimmedCurve)& anArcCurve = aConstructArc.Value();
371   
372   GeomAdaptor_Curve anArcAdaptor (anArcCurve, anArcCurve->FirstParameter(), anArcCurve->LastParameter());
373
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));
379
380   GCPnts_UniformAbscissa aMakePnts (anArcAdaptor, aNbPoints);
381   if (!aMakePnts.IsDone())
382   {
383     return;
384   }
385
386   // init data arrays for graphical and selection primitives
387   Handle(Graphic3d_ArrayOfPolylines) aPrimSegments = new Graphic3d_ArrayOfPolylines (aNbPoints);
388
389   SelectionGeometry::Curve& aSensitiveCurve = mySelectionGeom.NewCurve();
390
391   // load data into arrays
392   for (Standard_Integer aPntIt = 1; aPntIt <= aMakePnts.NbPoints(); ++aPntIt)
393   {
394     gp_Pnt aPnt = anArcAdaptor.Value (aMakePnts.Parameter (aPntIt));
395
396     aPrimSegments->AddVertex (aPnt);
397
398     aSensitiveCurve.Append (aPnt);
399   }
400
401   // add display presentation
402   if (!myDrawer->DimensionAspect()->IsText3d() && theMode == ComputeMode_All)
403   {
404     Prs3d_Root::CurrentGroup (thePresentation)->SetStencilTestOptions (Standard_True);
405   }
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)
410   {
411     Prs3d_Root::CurrentGroup (thePresentation)->SetStencilTestOptions (Standard_False);
412   }
413 }
414
415 //=======================================================================
416 //function: DrawArcWithText
417 //purpose :
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)
427 {
428   // construct plane where the circle and the arc are located
429   gce_MakePln aConstructPlane (theFirstAttach, theSecondAttach, theCenter);
430   if (!aConstructPlane.IsDone())
431   {
432     return;
433   }
434
435   gp_Pln aPlane = aConstructPlane.Value();
436
437   Standard_Real aRadius = theFirstAttach.Distance (myCenterPoint);
438
439   // construct circle forming the arc
440   gce_MakeCirc aConstructCircle (theCenter, aPlane, aRadius);
441   if (!aConstructCircle.IsDone())
442   {
443     return;
444   }
445
446   gp_Circ aCircle = aConstructCircle.Value();
447
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);
452
453   // middle point of arc parameter on circle
454   Standard_Real aParamMid = (aParamBeg + aParamEnd) * 0.5;
455
456   // add text graphical primitives
457   if (theMode == ComputeMode_All || theMode == ComputeMode_Text)
458   {
459     gp_Pnt aTextPos = ElCLib::Value (aParamMid, aCircle);
460     gp_Dir aTextDir = gce_MakeDir (theFirstAttach, theSecondAttach);
461
462     // Drawing text
463     DrawText (thePresentation,
464               aTextPos,
465               aTextDir,
466               theText,
467               theLabelPosition);
468   }
469
470   if (theMode != ComputeMode_All && theMode != ComputeMode_Line)
471   {
472     return;
473   }
474
475   Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
476
477   Standard_Boolean isLineBreak = aDimensionAspect->TextVerticalPosition() == Prs3d_DTVP_Center
478                               && aDimensionAspect->IsText3d();
479
480   if (isLineBreak)
481   {
482     // compute gap for label as parameteric size of sector on circle segment
483     Standard_Real aSectorOnCircle = theTextWidth / aRadius;
484   
485     gp_Pnt aTextPntBeg = ElCLib::Value (aParamMid - aSectorOnCircle * 0.5, aCircle);
486     gp_Pnt aTextPntEnd = ElCLib::Value (aParamMid + aSectorOnCircle * 0.5, aCircle);
487
488     // Drawing arcs
489     DrawArc (thePresentation, theFirstAttach, aTextPntBeg, theCenter, aRadius, theMode);
490     DrawArc (thePresentation, theSecondAttach, aTextPntEnd, theCenter, aRadius, theMode);
491   }
492   else
493   {
494     DrawArc (thePresentation, theFirstAttach, theSecondAttach, theCenter, aRadius, theMode);
495   }
496 }
497
498 //=======================================================================
499 //function : CheckPlane
500 //purpose  : 
501 //=======================================================================
502 Standard_Boolean AIS_AngleDimension::CheckPlane (const gp_Pln& thePlane)const
503 {
504   if (!thePlane.Contains (myFirstPoint, Precision::Confusion()) &&
505       !thePlane.Contains (mySecondPoint, Precision::Confusion()) &&
506       !thePlane.Contains (myCenterPoint, Precision::Confusion()))
507   {
508     return Standard_False;
509   }
510
511   return Standard_True;
512 }
513
514 //=======================================================================
515 //function : ComputePlane
516 //purpose  : 
517 //=======================================================================
518 void AIS_AngleDimension::ComputePlane()
519 {
520   if (!IsValid())
521   {
522     return;
523   }
524
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();
530
531   myPlane = gp_Pln (gp_Ax3 (myCenterPoint, gp_Dir (aDirectionN), gp_Dir (aDirectionX)));
532 }
533
534 //=======================================================================
535 //function : GetModelUnits
536 //purpose  :
537 //=======================================================================
538 const TCollection_AsciiString& AIS_AngleDimension::GetModelUnits() const
539 {
540   return myDrawer->DimAngleModelUnits();
541 }
542
543 //=======================================================================
544 //function : GetDisplayUnits
545 //purpose  :
546 //=======================================================================
547 const TCollection_AsciiString& AIS_AngleDimension::GetDisplayUnits() const
548 {
549   return myDrawer->DimAngleDisplayUnits();
550 }
551
552 //=======================================================================
553 //function : SetModelUnits
554 //purpose  :
555 //=======================================================================
556 void AIS_AngleDimension::SetModelUnits (const TCollection_AsciiString& theUnits)
557 {
558   myDrawer->SetDimAngleModelUnits (theUnits);
559 }
560
561 //=======================================================================
562 //function : SetDisplayUnits
563 //purpose  :
564 //=======================================================================
565 void AIS_AngleDimension::SetDisplayUnits (const TCollection_AsciiString& theUnits)
566 {
567   myDrawer->SetDimAngleDisplayUnits (theUnits);
568 }
569
570 //=======================================================================
571 //function : ComputeValue
572 //purpose  : 
573 //=======================================================================
574 Standard_Real AIS_AngleDimension::ComputeValue() const
575 {
576   if (!IsValid())
577   {
578     return 0.0;
579   }
580
581   gp_Vec aVec1 (myCenterPoint, myFirstPoint);
582   gp_Vec aVec2 (myCenterPoint, mySecondPoint);
583
584   Standard_Real anAngle = aVec2.AngleWithRef (aVec1, GetPlane().Axis().Direction());
585
586   return anAngle > 0.0 ? anAngle : (2.0 * M_PI - anAngle);
587 }
588
589 //=======================================================================
590 //function : Compute
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)
596 {
597   thePresentation->Clear();
598   mySelectionGeom.Clear (theMode);
599
600   if (!IsValid())
601   {
602     return;
603   }
604
605   // Parameters for presentation
606   Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
607
608   Prs3d_Root::CurrentGroup(thePresentation)->SetPrimitivesAspect (aDimensionAspect->LineAspect()->Aspect());
609
610   Quantity_Length anArrowLength = aDimensionAspect->ArrowAspect()->Length();
611
612   // prepare label string and compute its geometrical width
613   Standard_Real aLabelWidth;
614   TCollection_ExtendedString aLabelString = GetValueString (aLabelWidth);
615
616   // add margins to label width
617   if (aDimensionAspect->IsText3d())
618   {
619     aLabelWidth += aDimensionAspect->TextAspect()->Height() * THE_3D_TEXT_MARGIN * 2.0;
620   }
621
622   gp_Pnt aFirstAttach = myCenterPoint.Translated (gp_Vec(myCenterPoint, myFirstPoint).Normalized() * GetFlyout());
623   gp_Pnt aSecondAttach = myCenterPoint.Translated (gp_Vec(myCenterPoint, mySecondPoint).Normalized() * GetFlyout());
624
625   // Handle user-defined and automatic arrow placement
626   bool isArrowsExternal = false;
627   switch (aDimensionAspect->ArrowOrientation())
628   {
629     case Prs3d_DAO_External: isArrowsExternal = true; break;
630     case Prs3d_DAO_Internal: isArrowsExternal = false; break;
631     case Prs3d_DAO_Fit:
632     {
633       gp_Vec anAttachVector (aFirstAttach, aSecondAttach);
634       Standard_Real aDimensionWidth = anAttachVector.Magnitude();
635
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
639                                     : 0.0;
640
641       Standard_Real anArrowsWidth   = (anArrowLength + anArrowMargin) * 2.0;
642
643       isArrowsExternal = aDimensionWidth < aLabelWidth + anArrowsWidth;
644       break;
645     }
646   }
647
648   //Arrows positions and directions
649   gp_Vec aWPDir = gp_Vec (GetPlane().Axis().Direction());
650
651   gp_Dir aFirstExtensionDir  = aWPDir            ^ gp_Vec (myCenterPoint, aFirstAttach);
652   gp_Dir aSecondExtensionDir = aWPDir.Reversed() ^ gp_Vec (myCenterPoint, aSecondAttach);
653
654   gp_Vec aFirstArrowVec  = gp_Vec (aFirstExtensionDir)  * anArrowLength;
655   gp_Vec aSecondArrowVec = gp_Vec (aSecondExtensionDir) * anArrowLength;
656
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);
661
662   if (isArrowsExternal)
663   {
664     aFirstArrowVec.Reverse();
665     aSecondArrowVec.Reverse();
666   }
667
668   aFirstArrowBegin  = aFirstAttach;
669   aSecondArrowBegin = aSecondAttach;
670   aFirstArrowEnd    = aFirstAttach.Translated (-aFirstArrowVec);
671   aSecondArrowEnd   = aSecondAttach.Translated (-aSecondArrowVec);
672
673   Standard_Integer aLabelPosition = LabelPosition_None;
674
675   // Handle user-defined and automatic text placement
676   switch (aDimensionAspect->TextHorizontalPosition())
677   {
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;
681     case Prs3d_DTHP_Fit:
682     {
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;
687
688       aLabelPosition |= aDimensionWidth < aContentWidth ? LabelPosition_Left : LabelPosition_HCenter;
689       break;
690     }
691   }
692
693   switch (aDimensionAspect->TextVerticalPosition())
694   {
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;
698   }
699
700   // Group1: stenciling text and the angle dimension arc
701   Prs3d_Root::NewGroup (thePresentation);
702
703   Standard_Real anExtensionSize = aDimensionAspect->ExtensionSize();
704
705   Standard_Integer aHPosition = aLabelPosition & LabelPosition_HMask;
706
707   // draw text label
708   switch (aHPosition)
709   {
710     case LabelPosition_HCenter :
711     {
712       Standard_Boolean isLineBreak = aDimensionAspect->TextVerticalPosition() == Prs3d_DTVP_Center
713                                   && aDimensionAspect->IsText3d();
714
715       if (isLineBreak)
716       {
717         DrawArcWithText (thePresentation,
718                          aFirstAttach,
719                          aSecondAttach,
720                          myCenterPoint,
721                          aLabelString,
722                          aLabelWidth,
723                          theMode,
724                          aLabelPosition);
725         break;
726       }
727
728       // compute text primitives
729       if (theMode == ComputeMode_All || theMode == ComputeMode_Text)
730       {
731         gp_Vec aDimensionDir (aFirstAttach, aSecondAttach);
732         gp_Pnt aTextPos = GetCenterOnArc (aFirstAttach, aSecondAttach, myCenterPoint);
733         gp_Dir aTextDir = aDimensionDir;
734
735         DrawText (thePresentation,
736                   aTextPos,
737                   aTextDir,
738                   aLabelString,
739                   aLabelPosition);
740       }
741
742       if (theMode == ComputeMode_All || theMode == ComputeMode_Line)
743       {
744         DrawArc (thePresentation,
745                  isArrowsExternal ? aFirstAttach : aFirstArrowEnd,
746                  isArrowsExternal ? aSecondAttach : aSecondArrowEnd,
747                  myCenterPoint,
748                  Abs (GetFlyout()),
749                  theMode);
750       }
751     }
752     break;
753
754     case LabelPosition_Left :
755     {
756       DrawExtension (thePresentation,
757                      anExtensionSize,
758                      isArrowsExternal ? aFirstArrowEnd : aFirstAttach,
759                      aFirstExtensionDir,
760                      aLabelString,
761                      aLabelWidth,
762                      theMode,
763                      aLabelPosition);
764     }
765     break;
766
767     case LabelPosition_Right :
768     {
769       DrawExtension (thePresentation,
770                      anExtensionSize,
771                      isArrowsExternal ? aSecondArrowEnd : aSecondAttach,
772                      aSecondExtensionDir,
773                      aLabelString,
774                      aLabelWidth,
775                      theMode,
776                      aLabelPosition);
777     }
778     break;
779   }
780
781   // dimension arc without text
782   if ((theMode == ComputeMode_All || theMode == ComputeMode_Line) && aHPosition != LabelPosition_HCenter)
783   {
784     Prs3d_Root::NewGroup (thePresentation);
785
786     DrawArc (thePresentation,
787              isArrowsExternal ? aFirstAttach  : aFirstArrowEnd,
788              isArrowsExternal ? aSecondAttach : aSecondArrowEnd,
789              myCenterPoint,
790              Abs(GetFlyout ()),
791              theMode);
792   }
793
794   // arrows and arrow extensions
795   if (theMode == ComputeMode_All || theMode == ComputeMode_Line)
796   {
797     Prs3d_Root::NewGroup (thePresentation);
798
799     DrawArrow (thePresentation, aFirstArrowBegin,  gp_Dir (aFirstArrowVec));
800     DrawArrow (thePresentation, aSecondArrowBegin, gp_Dir (aSecondArrowVec));
801   }
802
803   if ((theMode == ComputeMode_All || theMode == ComputeMode_Line) && isArrowsExternal)
804   {
805     Prs3d_Root::NewGroup (thePresentation);
806
807     if (aHPosition != LabelPosition_Left)
808     {
809       DrawExtension (thePresentation,
810                      anExtensionSize,
811                      aFirstArrowEnd,
812                      aFirstExtensionDir,
813                      THE_EMPTY_LABEL_STRING,
814                      THE_EMPTY_LABEL_WIDTH,
815                      theMode,
816                      LabelPosition_None);
817     }
818
819     if (aHPosition != LabelPosition_Right)
820     {
821       DrawExtension (thePresentation,
822                      anExtensionSize,
823                      aSecondArrowEnd,
824                      aSecondExtensionDir,
825                      THE_EMPTY_LABEL_STRING,
826                      THE_EMPTY_LABEL_WIDTH,
827                      theMode,
828                      LabelPosition_None);
829     }
830   }
831
832   // flyouts
833   if (theMode == ComputeMode_All)
834   {
835     Prs3d_Root::NewGroup (thePresentation);
836
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);
842
843     Handle(Graphic3d_AspectLine3d) aFlyoutStyle = myDrawer->DimensionAspect()->LineAspect()->Aspect();
844     Prs3d_Root::CurrentGroup (thePresentation)->SetPrimitivesAspect (aFlyoutStyle);
845     Prs3d_Root::CurrentGroup (thePresentation)->AddPrimitiveArray (aPrimSegments);
846   }
847
848   myIsComputed = Standard_True;
849 }
850
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)
857 {
858   gp_Pnt aFirstAttach  = myCenterPoint.Translated (gp_Vec (myCenterPoint, myFirstPoint).Normalized()  * GetFlyout());
859   gp_Pnt aSecondAttach = myCenterPoint.Translated (gp_Vec (myCenterPoint, mySecondPoint).Normalized() * GetFlyout());
860
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));
864
865   theSelection->Add (aSensitiveEntity);
866 }
867
868 //=======================================================================
869 //function : InitTwoEdgesAngle
870 //purpose  : 
871 //=======================================================================
872 Standard_Boolean AIS_AngleDimension::InitTwoEdgesAngle (gp_Pln& theComputedPlane)
873 {
874   TopoDS_Edge aFirstEdge  = TopoDS::Edge (myFirstShape);
875   TopoDS_Edge aSecondEdge = TopoDS::Edge (mySecondShape);
876
877   BRepAdaptor_Curve aMakeFirstLine  (aFirstEdge);
878   BRepAdaptor_Curve aMakeSecondLine (aSecondEdge);
879
880   if (aMakeFirstLine.GetType() != GeomAbs_Line || aMakeSecondLine.GetType() != GeomAbs_Line)
881   {
882     return  Standard_False;
883   }
884
885   Handle(Geom_Line) aFirstLine  = new Geom_Line (aMakeFirstLine.Line());
886   Handle(Geom_Line) aSecondLine = new Geom_Line (aMakeSecondLine.Line());
887
888   gp_Lin aFirstLin  = aFirstLine->Lin();
889   gp_Lin aSecondLin = aSecondLine->Lin();
890
891   Standard_Boolean isParallelLines = Abs (aFirstLin.Angle (aSecondLin) - M_PI) <= Precision::Angular();
892
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());
897
898   theComputedPlane = gp_Pln (aPoint, aNormal);
899
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;
904
905   if (!AIS::ComputeGeometry (aFirstEdge, aSecondEdge,
906                              aFirstLine, aSecondLine,
907                              aFirstPoint1, aLastPoint1,
908                              aFirstPoint2, aLastPoint2,
909                              isInfinite1, isInfinite2))
910   {
911     return Standard_False;
912   }
913
914   if (aFirstLin.Direction().IsParallel (aSecondLin.Direction(), Precision::Angular()))
915   {
916     myFirstPoint  = aFirstLin.Location();
917     mySecondPoint = ElCLib::Value (ElCLib::Parameter (aFirstLin, myFirstPoint), aSecondLin);
918
919     if (mySecondPoint.Distance (myFirstPoint) <= Precision::Confusion())
920     {
921       mySecondPoint.Translate (gp_Vec (aSecondLin.Direction()) * Abs (GetFlyout()));
922     }
923
924     myCenterPoint.SetXYZ ((myFirstPoint.XYZ() + mySecondPoint.XYZ()) / 2.0);
925   }
926   else
927   {
928     // Find intersection
929     gp_Lin2d aFirstLin2d  = ProjLib::Project (theComputedPlane, aFirstLin);
930     gp_Lin2d aSecondLin2d = ProjLib::Project (theComputedPlane, aSecondLin);
931
932     IntAna2d_AnaIntersection anInt2d (aFirstLin2d, aSecondLin2d);
933     gp_Pnt2d anIntersectPoint;
934     if (!anInt2d.IsDone() || anInt2d.IsEmpty())
935     {
936       return Standard_False;
937     }
938
939     anIntersectPoint = gp_Pnt2d (anInt2d.Point(1).Value());
940     myCenterPoint = ElCLib::To3d (theComputedPlane.Position().Ax2(), anIntersectPoint);
941
942     if (isInfinite1 || isInfinite2)
943     {
944       myFirstPoint  = myCenterPoint.Translated (gp_Vec (aFirstLin.Direction()) * Abs (GetFlyout()));
945       mySecondPoint = myCenterPoint.Translated (gp_Vec (aSecondLin.Direction()) * Abs (GetFlyout()));
946
947       return IsValidPoints (myFirstPoint, myCenterPoint, mySecondPoint);
948     }
949
950     // |
951     // | <- dimension should be here
952     // *----
953     myFirstPoint  = myCenterPoint.Distance (aFirstPoint1) > myCenterPoint.Distance (aLastPoint1)
954                   ? aFirstPoint1
955                   : aLastPoint1;
956
957     mySecondPoint = myCenterPoint.Distance (aFirstPoint2) > myCenterPoint.Distance (aLastPoint2)
958                   ? aFirstPoint2
959                   : aLastPoint2;
960   }
961
962   return IsValidPoints (myFirstPoint, myCenterPoint, mySecondPoint);
963 }
964
965 //=======================================================================
966 //function : InitTwoFacesAngle
967 //purpose  : initialization of angle dimension between two faces
968 //=======================================================================
969 Standard_Boolean AIS_AngleDimension::InitTwoFacesAngle()
970 {
971   TopoDS_Face aFirstFace = TopoDS::Face (myFirstShape);
972   TopoDS_Face aSecondFace = TopoDS::Face (mySecondShape);
973
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;
979
980   AIS::GetPlaneFromFace (aFirstFace, aFirstPlane,
981                          aFirstBasisSurf,aFirstSurfType,aFirstOffset);
982
983   AIS::GetPlaneFromFace (aSecondFace, aSecondPlane,
984                          aSecondBasisSurf, aSecondSurfType, aSecondOffset);
985
986   if (aFirstSurfType == AIS_KOS_Plane && aSecondSurfType == AIS_KOS_Plane)
987   {
988     //Planar faces angle
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,
992                                              aSecondFace,
993                                              myCenterPoint,
994                                              myFirstPoint,
995                                              mySecondPoint)
996            && IsValidPoints (myFirstPoint,
997                              myCenterPoint,
998                              mySecondPoint);
999   }
1000   else
1001   {
1002     // Curvilinear faces angle
1003     return AIS::InitAngleBetweenCurvilinearFaces (aFirstFace,
1004                                                   aSecondFace,
1005                                                   aFirstSurfType,
1006                                                   aSecondSurfType,
1007                                                   myCenterPoint,
1008                                                   myFirstPoint,
1009                                                   mySecondPoint)
1010            && IsValidPoints (myFirstPoint,
1011                              myCenterPoint,
1012                              mySecondPoint);
1013   }
1014 }
1015
1016 //=======================================================================
1017 //function : InitTwoFacesAngle
1018 //purpose  : initialization of angle dimension between two faces
1019 //=======================================================================
1020 Standard_Boolean AIS_AngleDimension::InitTwoFacesAngle (const gp_Pnt thePointOnFirstFace)
1021 {
1022   TopoDS_Face aFirstFace = TopoDS::Face (myFirstShape);
1023   TopoDS_Face aSecondFace = TopoDS::Face (mySecondShape);
1024
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;
1030
1031   AIS::GetPlaneFromFace (aFirstFace, aFirstPlane,
1032                          aFirstBasisSurf,aFirstSurfType,aFirstOffset);
1033
1034   AIS::GetPlaneFromFace (aSecondFace, aSecondPlane,
1035                          aSecondBasisSurf, aSecondSurfType, aSecondOffset);
1036
1037   myFirstPoint = thePointOnFirstFace;
1038   if (aFirstSurfType == AIS_KOS_Plane && aSecondSurfType == AIS_KOS_Plane)
1039   {
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,
1044                                              aSecondFace,
1045                                              myCenterPoint,
1046                                              myFirstPoint,
1047                                              mySecondPoint,
1048                                              Standard_True)
1049            && IsValidPoints (myFirstPoint,
1050                              myCenterPoint,
1051                              mySecondPoint);
1052   }
1053   else
1054   {
1055     // Curvilinear faces angle
1056     return AIS::InitAngleBetweenCurvilinearFaces (aFirstFace,
1057                                                   aSecondFace,
1058                                                   aFirstSurfType,
1059                                                   aSecondSurfType,
1060                                                   myCenterPoint,
1061                                                   myFirstPoint,
1062                                                   mySecondPoint,
1063                                                   Standard_True)
1064            && IsValidPoints (myFirstPoint,
1065                              myCenterPoint,
1066                              mySecondPoint);
1067   }
1068 }
1069
1070 //=======================================================================
1071 //function : InitConeAngle
1072 //purpose  : initialization of the cone angle
1073 //=======================================================================
1074 Standard_Boolean AIS_AngleDimension::InitConeAngle()
1075 {
1076   if (myFirstShape.IsNull())
1077   {
1078     return Standard_False;
1079   }
1080
1081   TopoDS_Face aConeShape = TopoDS::Face (myFirstShape);
1082   gp_Pln aPln;
1083   gp_Cone aCone;
1084   gp_Circ aCircle;
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);
1092   TopoDS_Face aFace;
1093   AIS_KindOfSurface aSurfType;
1094   Standard_Real anOffset = 0.;
1095   Handle(Standard_Type) aType;
1096
1097   Standard_Real aMaxV = aConeAdaptor.FirstVParameter();
1098   Standard_Real aMinV = aConeAdaptor.LastVParameter();
1099
1100   AIS::GetPlaneFromFace (aConeShape, aPln, aSurf, aSurfType, anOffset);
1101
1102   if (aSurfType == AIS_KOS_Revolution)
1103   {
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;
1111
1112     gp_Pnt aFirst1 = aConeAdaptor.Value (0., aMinV);
1113     gp_Pnt aLast1 = aConeAdaptor.Value (0., aMaxV);
1114     gp_Vec aVec1 (aFirst1, aLast1);
1115
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);
1120
1121     gp_Vec aVec2 (aFirst2, aLast2);
1122
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;
1127
1128     gce_MakeCone aMkCone (aRevSurf->Axis(), aFirst1, aLast1);
1129     aCone =  aMkCone.Value();
1130     myCenterPoint = aCone.Apex();
1131   }
1132   else
1133   {
1134     aType = aSurf->DynamicType();
1135     if (aType == STANDARD_TYPE(Geom_OffsetSurface) || anOffset > 0.01)
1136     {
1137       // Offset surface
1138       aOffsetSurf = new Geom_OffsetSurface (aSurf, anOffset);
1139       aSurf = aOffsetSurf->Surface();
1140       BRepBuilderAPI_MakeFace aMkFace(aSurf, Precision::Confusion());
1141       aMkFace.Build();
1142       if (!aMkFace.IsDone())
1143         return Standard_False;
1144       aConeAdaptor.Initialize (aMkFace.Face());
1145     }
1146     aCone = aConeAdaptor.Cone();
1147     aConicalSurf = Handle(Geom_ConicalSurface)::DownCast (aSurf);
1148     myCenterPoint =  aConicalSurf->Apex();
1149   }
1150
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();
1156
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();
1161
1162   if (aCircVmax.Radius() < aCircVmin.Radius())
1163   {
1164    gp_Circ aTmpCirc = aCircVmax;
1165    aCircVmax = aCircVmin;
1166    aCircVmin = aTmpCirc;
1167   }
1168
1169   myFirstPoint  = ElCLib::Value (0, aCircle);
1170   mySecondPoint = ElCLib::Value (M_PI, aCircle);
1171   return Standard_True;
1172 }
1173
1174 //=======================================================================
1175 //function : IsValidPoints
1176 //purpose  : 
1177 //=======================================================================
1178 Standard_Boolean AIS_AngleDimension::IsValidPoints (const gp_Pnt& theFirstPoint,
1179                                                     const gp_Pnt& theCenterPoint,
1180                                                     const gp_Pnt& theSecondPoint) const
1181 {
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();
1186 }