0026433: AIS_Dimension may attempt to modify the state of default Drawer shading...
[occt.git] / src / AIS / AIS_Dimension.cxx
1 // Created on: 2013-11-11
2 // Created by: Anastasia BORISOVA
3 // Copyright (c) 2013-2014 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16 #include <AIS_Dimension.hxx>
17
18 #include <AIS.hxx>
19 #include <AIS_DimensionOwner.hxx>
20 #include <Adaptor3d_HCurve.hxx>
21 #include <BRepAdaptor_Curve.hxx>
22 #include <BRepAdaptor_Surface.hxx>
23 #include <BRepBndLib.hxx>
24 #include <Bnd_Box.hxx>
25 #include <ElCLib.hxx>
26 #include <Font_BRepFont.hxx>
27 #include <Font_BRepTextBuilder.hxx>
28 #include <GC_MakeCircle.hxx>
29 #include <Geom_Line.hxx>
30 #include <GeomAdaptor_Curve.hxx>
31 #include <Geom_Circle.hxx>
32 #include <Geom_TrimmedCurve.hxx>
33 #include <gce_MakeDir.hxx>
34 #include <gce_MakeLin.hxx>
35 #include <gce_MakePln.hxx>
36 #include <Graphic3d_ArrayOfSegments.hxx>
37 #include <Graphic3d_ArrayOfTriangles.hxx>
38 #include <Graphic3d_AspectLine3d.hxx>
39 #include <Graphic3d_AspectFillArea3d.hxx>
40 #include <Graphic3d_AspectText3d.hxx>
41 #include <Graphic3d_Group.hxx>
42 #include <PrsMgr_PresentationManager3d.hxx>
43 #include <Prs3d_Arrow.hxx>
44 #include <Prs3d_ArrowAspect.hxx>
45 #include <Prs3d_Drawer.hxx>
46 #include <Prs3d_LineAspect.hxx>
47 #include <Prs3d_Presentation.hxx>
48 #include <Prs3d_Root.hxx>
49 #include <Prs3d_ShadingAspect.hxx>
50 #include <Prs3d_Text.hxx>
51 #include <SelectMgr_EntityOwner.hxx>
52 #include <SelectMgr_Selection.hxx>
53 #include <SelectMgr_SequenceOfOwner.hxx>
54 #include <Select3D_SensitiveCircle.hxx>
55 #include <Select3D_SensitiveGroup.hxx>
56 #include <Select3D_SensitiveCurve.hxx>
57 #include <Select3D_SensitiveSegment.hxx>
58 #include <Select3D_SensitiveTriangle.hxx>
59 #include <Select3D_SensitiveTriangulation.hxx>
60 #include <Poly_Array1OfTriangle.hxx>
61 #include <Poly_Triangulation.hxx>
62 #include <Standard_CString.hxx>
63 #include <Standard_ProgramError.hxx>
64 #include <StdPrs_ShadedShape.hxx>
65 #include <StdPrs_WFShape.hxx>
66 #include <TCollection_AsciiString.hxx>
67 #include <TCollection_ExtendedString.hxx>
68 #include <TopExp_Explorer.hxx>
69 #include <TopoDS.hxx>
70 #include <TopoDS_Edge.hxx>
71 #include <TopoDS_Vertex.hxx>
72 #include <Units.hxx>
73 #include <Units_UnitsDictionary.hxx>
74 #include <UnitsAPI.hxx>
75 #include <UnitsAPI_SystemUnits.hxx>
76
77
78 IMPLEMENT_STANDARD_RTTIEXT(AIS_Dimension,AIS_InteractiveObject)
79
80 namespace
81 {
82   // default text strings
83   static const TCollection_ExtendedString THE_EMPTY_LABEL;
84   static const TCollection_AsciiString    THE_UNDEFINED_UNITS;
85
86   // default text margin and resolution
87   static const Standard_Real THE_3D_TEXT_MARGIN    = 0.1;
88   static const unsigned int  THE_2D_TEXT_RESOLUTION = 72;
89
90   // default selection priorities
91   static const Standard_Integer THE_NEUTRAL_SEL_PRIORITY = 5;
92   static const Standard_Integer THE_LOCAL_SEL_PRIORITY   = 6;
93 };
94
95 //=======================================================================
96 //function : Constructor
97 //purpose  : 
98 //=======================================================================
99 AIS_Dimension::AIS_Dimension (const AIS_KindOfDimension theType)
100 : AIS_InteractiveObject  (),
101   mySelToleranceForText2d(0.0),
102   myCustomValue          (0.0),
103   myIsValueCustom        (Standard_False),
104   myIsTextPositionFixed  (Standard_False), 
105   mySpecialSymbol        (' '),
106   myDisplaySpecialSymbol (AIS_DSS_No),
107   myGeometryType         (GeometryType_UndefShapes),
108   myIsPlaneCustom        (Standard_False),
109   myFlyout               (0.0),
110   myIsGeometryValid      (Standard_False),
111   myKindOfDimension      (theType)
112 {
113 }
114
115 //=======================================================================
116 //function : SetCustomValue
117 //purpose  : 
118 //=======================================================================
119 void AIS_Dimension::SetCustomValue (const Standard_Real theValue)
120 {
121   if (myIsValueCustom && myCustomValue == theValue)
122   {
123     return;
124   }
125
126   myIsValueCustom = Standard_True;
127
128   myCustomValue = theValue;
129
130   SetToUpdate();
131 }
132
133 //=======================================================================
134 //function : GetPlane
135 //purpose  : 
136 //=======================================================================
137 const gp_Pln& AIS_Dimension::GetPlane() const
138 {
139   return myPlane;
140 }
141
142 //=======================================================================
143 //function : SetUserPlane
144 //purpose  : 
145 //=======================================================================
146 void AIS_Dimension::SetCustomPlane (const gp_Pln& thePlane)
147 {
148   myPlane = thePlane;
149   myIsPlaneCustom = Standard_True;
150
151   // Disable fixed (custom) text position
152   UnsetFixedTextPosition();
153
154   // Check validity if geometry has been set already.
155   if (IsValid())
156   {
157     SetToUpdate();
158   }
159 }
160
161 //=======================================================================
162 //function : SetDimensionAspect
163 //purpose  :
164 //=======================================================================
165 void AIS_Dimension::SetDimensionAspect (const Handle(Prs3d_DimensionAspect)& theDimensionAspect)
166 {
167   myDrawer->SetDimensionAspect (theDimensionAspect);
168
169   SetToUpdate();
170 }
171
172 //=======================================================================
173 //function : SetDisplaySpecialSymbol
174 //purpose  :
175 //=======================================================================
176 void AIS_Dimension::SetDisplaySpecialSymbol (const AIS_DisplaySpecialSymbol theDisplaySpecSymbol)
177 {
178   if (myDisplaySpecialSymbol == theDisplaySpecSymbol)
179   {
180     return;
181   }
182
183   myDisplaySpecialSymbol = theDisplaySpecSymbol;
184
185   SetToUpdate();
186 }
187
188 //=======================================================================
189 //function : SetSpecialSymbol
190 //purpose  :
191 //=======================================================================
192 void AIS_Dimension::SetSpecialSymbol (const Standard_ExtCharacter theSpecialSymbol)
193 {
194   if (mySpecialSymbol == theSpecialSymbol)
195   {
196     return;
197   }
198
199   mySpecialSymbol = theSpecialSymbol;
200
201   SetToUpdate();
202 }
203
204 //=======================================================================
205 //function : SetSelToleranceForText2d
206 //purpose  :
207 //=======================================================================
208 void AIS_Dimension::SetSelToleranceForText2d (const Standard_Real theTol)
209 {
210   if (mySelToleranceForText2d == theTol)
211   {
212     return;
213   }
214
215   mySelToleranceForText2d = theTol;
216
217   SetToUpdate();
218 }
219
220 //=======================================================================
221 //function : SetFlyout
222 //purpose  :
223 //=======================================================================
224 void AIS_Dimension::SetFlyout (const Standard_Real theFlyout)
225 {
226   if (myFlyout == theFlyout)
227   {
228     return;
229   }
230
231   myFlyout = theFlyout;
232
233   // Disable fixed text position
234   UnsetFixedTextPosition();
235
236   SetToUpdate();
237 }
238
239 //=======================================================================
240 //function : GetDisplayUnits
241 //purpose  :
242 //=======================================================================
243 const TCollection_AsciiString& AIS_Dimension::GetDisplayUnits() const
244 {
245   return THE_UNDEFINED_UNITS;
246 }
247
248 //=======================================================================
249 //function : GetModelUnits
250 //purpose  :
251 //=======================================================================
252 const TCollection_AsciiString& AIS_Dimension::GetModelUnits() const
253 {
254   return THE_UNDEFINED_UNITS;
255 }
256
257 //=======================================================================
258 //function : ValueToDisplayUnits
259 //purpose  :
260 //=======================================================================
261 Standard_Real AIS_Dimension::ValueToDisplayUnits() const
262 {
263   return UnitsAPI::AnyToAny (GetValue(),
264                              GetModelUnits().ToCString(),
265                              GetDisplayUnits().ToCString());
266 }
267
268 //=======================================================================
269 //function : GetValueString
270 //purpose  : 
271 //=======================================================================
272 TCollection_ExtendedString AIS_Dimension::GetValueString (Standard_Real& theWidth) const
273 {
274   // format value string using "sprintf"
275   TCollection_AsciiString aFormatStr = myDrawer->DimensionAspect()->ValueStringFormat();
276
277   char aFmtBuffer[256];
278   sprintf (aFmtBuffer, aFormatStr.ToCString(), ValueToDisplayUnits());
279   TCollection_ExtendedString aValueStr = TCollection_ExtendedString (aFmtBuffer);
280
281   // add units to values string
282   if (myDrawer->DimensionAspect()->IsUnitsDisplayed())
283   {
284     aValueStr += " ";
285     aValueStr += TCollection_ExtendedString (GetDisplayUnits());
286   }
287
288   switch (myDisplaySpecialSymbol)
289   {
290     case AIS_DSS_Before : aValueStr.Insert (1, mySpecialSymbol); break;
291     case AIS_DSS_After  : aValueStr.Insert (aValueStr.Length() + 1, mySpecialSymbol); break;
292     case AIS_DSS_No     : break;
293   }
294
295   // Get text style parameters
296   Quantity_Color aColor; 
297   Standard_CString aFontName;
298   Standard_Real aFactor;
299   Standard_Real aSpace;
300   myDrawer->DimensionAspect()->TextAspect()->Aspect()->Values (aColor, aFontName, aFactor, aSpace);
301   Font_FontAspect aFontAspect = myDrawer->DimensionAspect()->TextAspect()->Aspect()->GetTextFontAspect();
302   Standard_Real   aFontHeight = myDrawer->DimensionAspect()->TextAspect()->Height();
303
304   NCollection_Utf8String anUTFString = (Standard_Utf16Char* )aValueStr.ToExtString();
305
306   theWidth = 0.0;
307
308   if (myDrawer->DimensionAspect()->IsText3d())
309   {
310     // text width produced by BRepFont
311     Font_BRepFont aFont (aFontName, aFontAspect, aFontHeight);
312
313     for (NCollection_Utf8Iter anIter = anUTFString.Iterator(); *anIter != 0; )
314     {
315       Standard_Utf32Char aCurrChar = *anIter;
316       Standard_Utf32Char aNextChar = *(++anIter);
317       theWidth += aFont.AdvanceX (aCurrChar, aNextChar);
318     }
319   }
320   else
321   {
322     // Text width for 1:1 scale 2D case
323     Handle(Font_FTFont) aFont = new Font_FTFont();
324     aFont->Init (aFontName, aFontAspect, (const unsigned int)aFontHeight, THE_2D_TEXT_RESOLUTION);
325
326     for (NCollection_Utf8Iter anIter = anUTFString.Iterator(); *anIter != 0; )
327     {
328       Standard_Utf32Char aCurrChar = *anIter;
329       Standard_Utf32Char aNextChar = *(++anIter);
330       theWidth += (Standard_Real) aFont->AdvanceX (aCurrChar, aNextChar);
331     }
332   }
333
334   return aValueStr;
335 }
336
337 //=======================================================================
338 //function : DrawArrow
339 //purpose  : 
340 //=======================================================================
341 void AIS_Dimension::DrawArrow (const Handle(Prs3d_Presentation)& thePresentation,
342                                const gp_Pnt& theLocation,
343                                const gp_Dir& theDirection)
344 {
345   Prs3d_Root::NewGroup (thePresentation);
346
347   Quantity_Length aLength = myDrawer->DimensionAspect()->ArrowAspect()->Length();
348   Standard_Real   anAngle = myDrawer->DimensionAspect()->ArrowAspect()->Angle();
349
350   if (myDrawer->DimensionAspect()->IsArrows3d())
351   {
352     Prs3d_Arrow::Draw (thePresentation,
353                        theLocation,
354                        theDirection,
355                        anAngle,
356                        aLength);
357   }
358   else
359   {
360     gp_Pnt aLeftPoint (gp::Origin());
361     gp_Pnt aRightPoint (gp::Origin());
362     const gp_Dir& aPlane = GetPlane().Axis().Direction();
363
364     PointsForArrow (theLocation, theDirection, aPlane, aLength, anAngle, aLeftPoint, aRightPoint);
365
366     Handle(Graphic3d_ArrayOfTriangles) anArrow = new Graphic3d_ArrayOfTriangles(3);
367
368     anArrow->AddVertex (aLeftPoint);
369     anArrow->AddVertex (theLocation);
370     anArrow->AddVertex (aRightPoint);
371
372     // Set aspect for arrow triangles
373     Quantity_Color aColor;
374     Aspect_TypeOfLine aTOL;
375     Standard_Real aWidth;
376     myDrawer->DimensionAspect()->ArrowAspect()->Aspect()->Values (aColor, aTOL, aWidth);
377     Graphic3d_MaterialAspect aShadeMat (Graphic3d_NOM_DEFAULT);
378     aShadeMat.SetReflectionModeOff (Graphic3d_TOR_AMBIENT);
379     aShadeMat.SetReflectionModeOff (Graphic3d_TOR_DIFFUSE);
380     aShadeMat.SetReflectionModeOff (Graphic3d_TOR_SPECULAR);
381
382     Handle(Prs3d_ShadingAspect) aShadingStyle = new Prs3d_ShadingAspect();
383     aShadingStyle->SetColor (aColor);
384     aShadingStyle->SetMaterial (aShadeMat);
385
386     Prs3d_Root::CurrentGroup (thePresentation)->SetPrimitivesAspect (aShadingStyle->Aspect());
387     Prs3d_Root::CurrentGroup (thePresentation)->AddPrimitiveArray (anArrow);
388   }
389
390   SelectionGeometry::Arrow& aSensitiveArrow = mySelectionGeom.NewArrow();
391   aSensitiveArrow.Position  = theLocation;
392   aSensitiveArrow.Direction = theDirection;
393 }
394
395 //=======================================================================
396 //function : DrawText
397 //purpose  : 
398 //=======================================================================
399 void AIS_Dimension::DrawText (const Handle(Prs3d_Presentation)& thePresentation,
400                               const gp_Pnt& theTextPos,
401                               const gp_Dir& theTextDir,
402                               const TCollection_ExtendedString& theText,
403                               const Standard_Integer theLabelPosition)
404 {
405   if (myDrawer->DimensionAspect()->IsText3d())
406   {
407     // getting font parameters
408     Quantity_Color aColor;
409     Standard_CString aFontName;
410     Standard_Real anExpansionFactor;
411     Standard_Real aSpace;
412     myDrawer->DimensionAspect()->TextAspect()->Aspect()->Values (aColor, aFontName, anExpansionFactor, aSpace);
413     Font_FontAspect aFontAspect = myDrawer->DimensionAspect()->TextAspect()->Aspect()->GetTextFontAspect();
414     Standard_Real aFontHeight = myDrawer->DimensionAspect()->TextAspect()->Height();
415
416     // creating TopoDS_Shape for text
417     Font_BRepFont aFont (aFontName, aFontAspect, aFontHeight);
418     NCollection_Utf8String anUTFString = (Standard_Utf16Char* )theText.ToExtString();
419
420     Font_BRepTextBuilder aBuilder;
421     TopoDS_Shape aTextShape = aBuilder.Perform (aFont, anUTFString);
422
423     // compute text width with kerning
424     Standard_Real aTextWidth  = 0.0;
425     Standard_Real aTextHeight = aFont.Ascender() + aFont.Descender();
426
427     for (NCollection_Utf8Iter anIter = anUTFString.Iterator(); *anIter != 0; )
428     {
429       Standard_Utf32Char aCurrChar = *anIter;
430       Standard_Utf32Char aNextChar = *(++anIter);
431       aTextWidth += aFont.AdvanceX (aCurrChar, aNextChar);
432     }
433
434     // formating text position in XOY plane
435     Standard_Integer aHLabelPos = theLabelPosition & LabelPosition_HMask;
436     Standard_Integer aVLabelPos = theLabelPosition & LabelPosition_VMask;
437
438     gp_Dir aTextDir (aHLabelPos == LabelPosition_Left ? -theTextDir : theTextDir);
439
440     // compute label offsets
441     Standard_Real aMarginSize    = aFontHeight * THE_3D_TEXT_MARGIN;
442     Standard_Real aCenterHOffset = 0.0;
443     Standard_Real aCenterVOffset = 0.0;
444     switch (aHLabelPos)
445     {
446       case LabelPosition_HCenter : aCenterHOffset =  0.0; break;
447       case LabelPosition_Right   : aCenterHOffset =  aTextWidth / 2.0 + aMarginSize; break;
448       case LabelPosition_Left    : aCenterHOffset = -aTextWidth / 2.0 - aMarginSize; break;
449     }
450     switch (aVLabelPos)
451     {
452       case LabelPosition_VCenter : aCenterVOffset =  0.0; break;
453       case LabelPosition_Above   : aCenterVOffset =  aTextHeight / 2.0 + aMarginSize; break;
454       case LabelPosition_Below   : aCenterVOffset = -aTextHeight / 2.0 - aMarginSize; break;
455     }
456
457     // compute shape offset transformation
458     Standard_Real aShapeHOffset = aCenterHOffset - aTextWidth / 2.0;
459     Standard_Real aShapeVOffset = aCenterVOffset - aTextHeight / 2.0;
460
461     // center shape in its bounding box (suppress border spacing added by FT_Font)
462     Bnd_Box aShapeBnd;
463     BRepBndLib::AddClose (aTextShape, aShapeBnd);
464
465     Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
466     aShapeBnd.Get (aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
467
468     Standard_Real aXalign = aTextWidth  * 0.5 - (aXmax + aXmin) * 0.5;
469     Standard_Real aYalign = aTextHeight * 0.5 - (aYmax + aYmin) * 0.5;
470     aShapeHOffset += aXalign;
471     aShapeVOffset += aYalign;
472
473     gp_Trsf anOffsetTrsf;
474     anOffsetTrsf.SetTranslation (gp::Origin(), gp_Pnt (aShapeHOffset, aShapeVOffset, 0.0));
475     aTextShape.Move (anOffsetTrsf);
476
477     // transform text to myWorkingPlane coordinate system
478     gp_Ax3 aTextCoordSystem (theTextPos, GetPlane().Axis().Direction(), aTextDir);
479     gp_Trsf aTextPlaneTrsf;
480     aTextPlaneTrsf.SetTransformation (aTextCoordSystem, gp_Ax3 (gp::XOY()));
481     aTextShape.Move (aTextPlaneTrsf);
482
483     // set text flipping anchors
484     gp_Trsf aCenterOffsetTrsf;
485     gp_Pnt aCenterOffset (aCenterHOffset, aCenterVOffset, 0.0);
486     aCenterOffsetTrsf.SetTranslation (gp::Origin(), aCenterOffset);
487
488     gp_Pnt aCenterOfLabel (gp::Origin());
489     aCenterOfLabel.Transform (aCenterOffsetTrsf);
490     aCenterOfLabel.Transform (aTextPlaneTrsf);
491
492     gp_Ax2 aFlippingAxes (aCenterOfLabel, GetPlane().Axis().Direction(), aTextDir);
493     Prs3d_Root::CurrentGroup (thePresentation)->SetFlippingOptions (Standard_True, aFlippingAxes);
494
495     // draw text
496     if (myDrawer->DimensionAspect()->IsTextShaded())
497     {
498       // Setting text shading and color parameters
499       if (!myDrawer->HasOwnShadingAspect())
500       {
501         myDrawer->SetShadingAspect (new Prs3d_ShadingAspect());
502       }
503
504       Graphic3d_MaterialAspect aShadeMat (Graphic3d_NOM_DEFAULT);
505       aShadeMat.SetReflectionModeOff (Graphic3d_TOR_AMBIENT);
506       aShadeMat.SetReflectionModeOff (Graphic3d_TOR_DIFFUSE);
507       aShadeMat.SetReflectionModeOff (Graphic3d_TOR_SPECULAR);
508       myDrawer->ShadingAspect()->Aspect()->SetInteriorColor (aColor);
509       myDrawer->ShadingAspect()->Aspect()->SetBackInteriorColor (aColor);
510       myDrawer->ShadingAspect()->SetMaterial (aShadeMat);
511
512       // drawing text
513       StdPrs_ShadedShape::Add (thePresentation, aTextShape, myDrawer);
514     }
515     else
516     {
517       // Setting color for text
518       if (!myDrawer->HasOwnFreeBoundaryAspect())
519       {
520         myDrawer->SetFreeBoundaryAspect (new Prs3d_LineAspect (aColor, Aspect_TOL_SOLID, 1.0));
521       }
522
523       myDrawer->FreeBoundaryAspect()->Aspect()->SetColor (aColor);
524
525       // drawing text
526       StdPrs_WFShape::Add (thePresentation, aTextShape, myDrawer);
527     }
528     Prs3d_Root::CurrentGroup (thePresentation)->SetFlippingOptions (Standard_False, gp_Ax2());
529
530     mySelectionGeom.TextPos    = aCenterOfLabel;
531     mySelectionGeom.TextDir    = aTextDir;
532     mySelectionGeom.TextWidth  = aTextWidth + aMarginSize * 2.0;
533     mySelectionGeom.TextHeight = aTextHeight;
534
535     return;
536   }
537
538   // generate primitives for 2D text
539   myDrawer->DimensionAspect()->TextAspect()->Aspect()->SetDisplayType (Aspect_TODT_DIMENSION);
540
541   Prs3d_Text::Draw (thePresentation,
542                     myDrawer->DimensionAspect()->TextAspect(),
543                     theText,
544                     theTextPos);
545
546   mySelectionGeom.TextPos    = theTextPos;
547   mySelectionGeom.TextDir    = theTextDir;
548   mySelectionGeom.TextWidth  = 0.0;
549   mySelectionGeom.TextHeight = 0.0;
550 }
551
552 //=======================================================================
553 //function : DrawExtension
554 //purpose  : 
555 //=======================================================================
556 void AIS_Dimension::DrawExtension (const Handle(Prs3d_Presentation)& thePresentation,
557                                    const Standard_Real theExtensionSize,
558                                    const gp_Pnt& theExtensionStart,
559                                    const gp_Dir& theExtensionDir,
560                                    const TCollection_ExtendedString& theLabelString,
561                                    const Standard_Real theLabelWidth,
562                                    const Standard_Integer theMode,
563                                    const Standard_Integer theLabelPosition)
564 {
565   // reference line for extension starting at its connection point
566   gp_Lin anExtensionLine (theExtensionStart, theExtensionDir);
567
568   Standard_Boolean hasLabel = theLabelString.Length() > 0;
569   if (hasLabel && (theMode == ComputeMode_All || theMode == ComputeMode_Text))
570   {
571     // compute text primitives; get its model width
572     gp_Pnt aTextPos = ElCLib::Value (theExtensionSize, anExtensionLine);
573     gp_Dir aTextDir = theExtensionDir;
574
575     DrawText (thePresentation,
576               aTextPos,
577               aTextDir,
578               theLabelString,
579               theLabelPosition);
580   }
581
582   if (theMode != ComputeMode_All && theMode != ComputeMode_Line)
583   {
584     return;
585   }
586
587   Standard_Boolean isShortLine =  !myDrawer->DimensionAspect()->IsText3d()
588                                || theLabelPosition & LabelPosition_VCenter;
589
590   // compute graphical primitives and sensitives for extension line
591   gp_Pnt anExtStart = theExtensionStart;
592   gp_Pnt anExtEnd   = !hasLabel || isShortLine
593     ? ElCLib::Value (theExtensionSize, anExtensionLine)
594     : ElCLib::Value (theExtensionSize + theLabelWidth, anExtensionLine);
595
596   // add graphical primitives
597   Handle(Graphic3d_ArrayOfSegments) anExtPrimitive = new Graphic3d_ArrayOfSegments (2);
598   anExtPrimitive->AddVertex (anExtStart);
599   anExtPrimitive->AddVertex (anExtEnd);
600
601   // add selection primitives
602   SelectionGeometry::Curve& aSensitiveCurve = mySelectionGeom.NewCurve();
603   aSensitiveCurve.Append (anExtStart);
604   aSensitiveCurve.Append (anExtEnd);
605
606   if (!myDrawer->DimensionAspect()->IsText3d() && theMode == ComputeMode_All)
607   {
608     Prs3d_Root::CurrentGroup (thePresentation)->SetStencilTestOptions (Standard_True);
609   }
610   Handle(Graphic3d_AspectLine3d) aDimensionLineStyle = myDrawer->DimensionAspect()->LineAspect()->Aspect();
611   Prs3d_Root::CurrentGroup (thePresentation)->SetPrimitivesAspect (aDimensionLineStyle);
612   Prs3d_Root::CurrentGroup (thePresentation)->AddPrimitiveArray (anExtPrimitive);
613   if (!myDrawer->DimensionAspect()->IsText3d() && theMode == ComputeMode_All)
614   {
615     Prs3d_Root::CurrentGroup (thePresentation)->SetStencilTestOptions (Standard_False);
616   }
617 }
618
619 //=======================================================================
620 //function : DrawLinearDimension
621 //purpose  : 
622 //=======================================================================
623 void AIS_Dimension::DrawLinearDimension (const Handle(Prs3d_Presentation)& thePresentation,
624                                          const Standard_Integer theMode,
625                                          const gp_Pnt& theFirstPoint,
626                                          const gp_Pnt& theSecondPoint,
627                                          const Standard_Boolean theIsOneSide)
628 {
629   // do not build any dimension for equal points
630   if (theFirstPoint.IsEqual (theSecondPoint, Precision::Confusion()))
631   {
632     Standard_ProgramError::Raise ("Can not build presentation for equal points.");
633   }
634
635   Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
636
637   // For extensions we need to know arrow size, text size and extension size: get it from aspect
638   Quantity_Length anArrowLength   = aDimensionAspect->ArrowAspect()->Length();
639   Standard_Real   anExtensionSize = aDimensionAspect->ExtensionSize();
640   // prepare label string and compute its geometrical width
641   Standard_Real aLabelWidth;
642   TCollection_ExtendedString aLabelString = GetValueString (aLabelWidth);
643
644   // add margins to cut dimension lines for 3d text
645   if (aDimensionAspect->IsText3d())
646   {
647     aLabelWidth += aDimensionAspect->TextAspect()->Height() * THE_3D_TEXT_MARGIN * 2.0;
648   }
649
650   // handle user-defined and automatic arrow placement
651   Standard_Boolean isArrowsExternal = Standard_False;
652   Standard_Integer aLabelPosition = LabelPosition_None;
653
654   Prs3d_DimensionTextHorizontalPosition aHorisontalTextPos = aDimensionAspect->TextHorizontalPosition();
655   if (IsTextPositionCustom())
656   {
657     if (!AdjustParametersForLinear (myFixedTextPosition, theFirstPoint, theSecondPoint,
658                                     anExtensionSize, aHorisontalTextPos, myFlyout, myPlane, myIsPlaneCustom))
659     {
660       Standard_ProgramError::Raise ("Can not adjust plane to the custom label position.");
661     }
662   }
663
664   FitTextAlignmentForLinear (theFirstPoint, theSecondPoint, theIsOneSide, aHorisontalTextPos,
665                              aLabelPosition, isArrowsExternal);
666
667     // compute dimension line points
668   gp_Ax1 aPlaneNormal = GetPlane().Axis();
669   gp_Dir aTargetPointsVector = gce_MakeDir (theFirstPoint, theSecondPoint);
670
671   // compute flyout direction vector
672   gp_Dir aFlyoutVector = aPlaneNormal.Direction() ^ aTargetPointsVector;
673
674   // create lines for layouts
675   gp_Lin aLine1 (theFirstPoint, aFlyoutVector);
676   gp_Lin aLine2 (theSecondPoint, aFlyoutVector);
677
678   // Get flyout end points
679   gp_Pnt aLineBegPoint = ElCLib::Value (ElCLib::Parameter (aLine1, theFirstPoint)  + GetFlyout(), aLine1);
680   gp_Pnt aLineEndPoint = ElCLib::Value (ElCLib::Parameter (aLine2, theSecondPoint) + GetFlyout(), aLine2);
681
682   gp_Lin aDimensionLine = gce_MakeLin (aLineBegPoint, aLineEndPoint);
683
684   // compute arrows positions and directions
685   gp_Dir aFirstArrowDir       = aDimensionLine.Direction().Reversed();
686   gp_Dir aSecondArrowDir      = aDimensionLine.Direction();
687   gp_Dir aFirstExtensionDir   = aDimensionLine.Direction().Reversed();
688   gp_Dir aSecondExtensionDir  = aDimensionLine.Direction();
689
690   gp_Pnt aFirstArrowBegin  (0.0, 0.0, 0.0);
691   gp_Pnt aFirstArrowEnd    (0.0, 0.0, 0.0);
692   gp_Pnt aSecondArrowBegin (0.0, 0.0, 0.0);
693   gp_Pnt aSecondArrowEnd   (0.0, 0.0, 0.0);
694
695   if (isArrowsExternal)
696   {
697     aFirstArrowDir.Reverse();
698     aSecondArrowDir.Reverse();
699   }
700
701   aFirstArrowBegin  = aLineBegPoint;
702   aSecondArrowBegin = aLineEndPoint;
703   aFirstArrowEnd    = aLineBegPoint.Translated (-gp_Vec (aFirstArrowDir).Scaled (anArrowLength));
704   aSecondArrowEnd   = aLineEndPoint.Translated (-gp_Vec (aSecondArrowDir).Scaled (anArrowLength));
705
706   gp_Pnt aCenterLineBegin = isArrowsExternal 
707     ? aLineBegPoint : aFirstArrowEnd;
708
709   gp_Pnt aCenterLineEnd = isArrowsExternal || theIsOneSide
710     ? aLineEndPoint : aSecondArrowEnd;
711
712
713   switch (aLabelPosition & LabelPosition_HMask)
714   {
715     // ------------------------------------------------------------------------ //
716     //                                CENTER                                    //
717     // -------------------------------------------------------------------------//
718     case LabelPosition_HCenter:
719     {
720       // add label on dimension or extension line to presentation
721       Prs3d_Root::NewGroup (thePresentation);
722
723       gp_Pnt aTextPos = IsTextPositionCustom() ? myFixedTextPosition
724                                               : (aCenterLineBegin.XYZ() + aCenterLineEnd.XYZ()) * 0.5;
725       gp_Dir aTextDir = aDimensionLine.Direction();
726
727       // add text primitives
728       if (theMode == ComputeMode_All || theMode == ComputeMode_Text)
729       {
730         DrawText (thePresentation,
731                   aTextPos,
732                   aTextDir,
733                   aLabelString,
734                   aLabelPosition);
735       }
736
737       // add dimension line primitives
738       if (theMode == ComputeMode_All || theMode == ComputeMode_Line)
739       {
740         Standard_Boolean isLineBreak = aDimensionAspect->TextVerticalPosition() == Prs3d_DTVP_Center
741                                     && aDimensionAspect->IsText3d();
742
743         Handle(Graphic3d_ArrayOfSegments) aPrimSegments = new Graphic3d_ArrayOfSegments (isLineBreak ? 4 : 2);
744
745         // compute continuous or sectioned main line segments
746         if (isLineBreak)
747         {
748           Standard_Real aPTextPosition = ElCLib::Parameter (aDimensionLine, aTextPos);
749           gp_Pnt aSection1Beg = aCenterLineBegin;
750           gp_Pnt aSection1End = ElCLib::Value (aPTextPosition - (aLabelWidth * 0.5), aDimensionLine);
751           gp_Pnt aSection2Beg = ElCLib::Value (aPTextPosition + (aLabelWidth * 0.5), aDimensionLine);
752           gp_Pnt aSection2End = aCenterLineEnd;
753
754           aPrimSegments->AddVertex (aSection1Beg);
755           aPrimSegments->AddVertex (aSection1End);
756           aPrimSegments->AddVertex (aSection2Beg);
757           aPrimSegments->AddVertex (aSection2End);
758
759           SelectionGeometry::Curve& aLeftSensitiveCurve  = mySelectionGeom.NewCurve();
760           SelectionGeometry::Curve& aRightSensitiveCurve = mySelectionGeom.NewCurve();
761           aLeftSensitiveCurve.Append (aSection1Beg);
762           aLeftSensitiveCurve.Append (aSection1End);
763           aRightSensitiveCurve.Append (aSection2Beg);
764           aRightSensitiveCurve.Append (aSection2End);
765         }
766         else
767         {
768           aPrimSegments->AddVertex (aCenterLineBegin);
769           aPrimSegments->AddVertex (aCenterLineEnd);
770
771           SelectionGeometry::Curve& aSensitiveCurve = mySelectionGeom.NewCurve();
772           aSensitiveCurve.Append (aCenterLineBegin);
773           aSensitiveCurve.Append (aCenterLineEnd);
774         }
775
776         // set text label justification
777         Graphic3d_VerticalTextAlignment aTextJustificaton = Graphic3d_VTA_BOTTOM;
778         switch (aLabelPosition & LabelPosition_VMask)
779         {
780           case LabelPosition_Above   :
781           case LabelPosition_VCenter : aTextJustificaton = Graphic3d_VTA_BOTTOM; break;
782           case LabelPosition_Below   : aTextJustificaton = Graphic3d_VTA_TOP;    break;
783         }
784         aDimensionAspect->TextAspect()->SetVerticalJustification (aTextJustificaton);
785
786         // main dimension line, short extension
787         if (!aDimensionAspect->IsText3d() && theMode == ComputeMode_All)
788         {
789           Prs3d_Root::CurrentGroup (thePresentation)->SetStencilTestOptions (Standard_True);
790         }
791         Prs3d_Root::CurrentGroup (thePresentation)->SetPrimitivesAspect (aDimensionAspect->LineAspect()->Aspect());
792         Prs3d_Root::CurrentGroup (thePresentation)->AddPrimitiveArray (aPrimSegments);
793         if (!aDimensionAspect->IsText3d() && theMode == ComputeMode_All)
794         {
795           Prs3d_Root::CurrentGroup (thePresentation)->SetStencilTestOptions (Standard_False);
796         }
797
798         // add arrows to presentation
799         Prs3d_Root::NewGroup (thePresentation);
800
801         DrawArrow (thePresentation, aFirstArrowBegin, aFirstArrowDir);
802         if (!theIsOneSide)
803         {
804           DrawArrow (thePresentation, aSecondArrowBegin, aSecondArrowDir);
805         }
806
807         if (!isArrowsExternal)
808         {
809           break;
810         }
811
812         // add arrow extension lines to presentation
813         Prs3d_Root::NewGroup (thePresentation);
814
815         DrawExtension (thePresentation, aDimensionAspect->ArrowTailSize(),
816                        aFirstArrowEnd, aFirstExtensionDir,
817                        THE_EMPTY_LABEL, 0.0, theMode, LabelPosition_None);
818         if (!theIsOneSide)
819         {
820           DrawExtension (thePresentation, aDimensionAspect->ArrowTailSize(),
821                          aSecondArrowEnd, aSecondExtensionDir,
822                          THE_EMPTY_LABEL, 0.0, theMode, LabelPosition_None);
823         }
824       }
825
826       break;
827     }
828     // ------------------------------------------------------------------------ //
829     //                                LEFT                                      //
830     // -------------------------------------------------------------------------//
831
832     case LabelPosition_Left:
833     {
834       // add label on dimension or extension line to presentation
835       Prs3d_Root::NewGroup (thePresentation);
836
837       // Left extension with the text
838       DrawExtension (thePresentation, anExtensionSize,
839                      isArrowsExternal
840                        ? aFirstArrowEnd
841                        : aFirstArrowBegin,
842                      aFirstExtensionDir,
843                      aLabelString,
844                      aLabelWidth,
845                      theMode,
846                      aLabelPosition);
847
848       // add dimension line primitives
849       if (theMode == ComputeMode_All || theMode == ComputeMode_Line)
850       {
851         // add central dimension line
852         Prs3d_Root::NewGroup (thePresentation);
853
854         // add graphical primitives
855         Handle(Graphic3d_ArrayOfSegments) aPrimSegments = new Graphic3d_ArrayOfSegments (2);
856         aPrimSegments->AddVertex (aCenterLineBegin);
857         aPrimSegments->AddVertex (aCenterLineEnd);
858
859         Prs3d_Root::CurrentGroup (thePresentation)->SetPrimitivesAspect (aDimensionAspect->LineAspect()->Aspect());
860         Prs3d_Root::CurrentGroup (thePresentation)->AddPrimitiveArray (aPrimSegments);
861
862         // add selection primitives
863         SelectionGeometry::Curve& aSensitiveCurve = mySelectionGeom.NewCurve();
864         aSensitiveCurve.Append (aCenterLineBegin);
865         aSensitiveCurve.Append (aCenterLineEnd);
866
867         // add arrows to presentation
868         Prs3d_Root::NewGroup (thePresentation);
869
870         DrawArrow (thePresentation, aFirstArrowBegin, aFirstArrowDir);
871         if (!theIsOneSide)
872         {
873           DrawArrow (thePresentation, aSecondArrowBegin, aSecondArrowDir);
874         }
875
876         if (!isArrowsExternal || theIsOneSide)
877         {
878           break;
879         }
880
881         // add extension lines for external arrows
882         Prs3d_Root::NewGroup (thePresentation);
883
884         DrawExtension (thePresentation, aDimensionAspect->ArrowTailSize(),
885                        aSecondArrowEnd, aSecondExtensionDir,
886                        THE_EMPTY_LABEL, 0.0, theMode, LabelPosition_None);
887       }
888
889       break;
890     }
891     // ------------------------------------------------------------------------ //
892     //                                RIGHT                                     //
893     // -------------------------------------------------------------------------//
894
895     case LabelPosition_Right:
896     {
897       // add label on dimension or extension line to presentation
898       Prs3d_Root::NewGroup (thePresentation);
899
900       // Right extension with text
901       DrawExtension (thePresentation, anExtensionSize,
902                      isArrowsExternal
903                        ? aSecondArrowEnd
904                        : aSecondArrowBegin,
905                      aSecondExtensionDir,
906                      aLabelString, aLabelWidth,
907                      theMode,
908                      aLabelPosition);
909
910       if (theMode == ComputeMode_All || theMode == ComputeMode_Line)
911       {
912         // add central dimension line
913         Prs3d_Root::NewGroup (thePresentation);
914
915         // add graphical primitives
916         Handle(Graphic3d_ArrayOfSegments) aPrimSegments = new Graphic3d_ArrayOfSegments (2);
917         aPrimSegments->AddVertex (aCenterLineBegin);
918         aPrimSegments->AddVertex (aCenterLineEnd);
919         Prs3d_Root::CurrentGroup (thePresentation)->SetPrimitivesAspect (aDimensionAspect->LineAspect()->Aspect());
920         Prs3d_Root::CurrentGroup (thePresentation)->AddPrimitiveArray (aPrimSegments);
921
922         // add selection primitives
923         SelectionGeometry::Curve& aSensitiveCurve = mySelectionGeom.NewCurve();
924         aSensitiveCurve.Append (aCenterLineBegin);
925         aSensitiveCurve.Append (aCenterLineEnd);
926
927         // add arrows to presentation
928         Prs3d_Root::NewGroup (thePresentation);
929
930         DrawArrow (thePresentation, aSecondArrowBegin, aSecondArrowDir);
931         if (!theIsOneSide)
932         {
933           DrawArrow (thePresentation, aFirstArrowBegin, aFirstArrowDir);
934         }
935
936         if (!isArrowsExternal || theIsOneSide)
937         {
938           break;
939         }
940
941         // add extension lines for external arrows
942         Prs3d_Root::NewGroup (thePresentation);
943
944         DrawExtension (thePresentation, aDimensionAspect->ArrowTailSize(),
945                        aFirstArrowEnd, aFirstExtensionDir,
946                        THE_EMPTY_LABEL, 0.0, theMode, LabelPosition_None);
947       }
948
949       break;
950     }
951   }
952
953   // add flyout lines to presentation
954   if (theMode == ComputeMode_All)
955   {
956     Prs3d_Root::NewGroup (thePresentation);
957
958     Handle(Graphic3d_ArrayOfSegments) aPrimSegments = new Graphic3d_ArrayOfSegments(4);
959     aPrimSegments->AddVertex (theFirstPoint);
960     aPrimSegments->AddVertex (aLineBegPoint);
961
962     aPrimSegments->AddVertex (theSecondPoint);
963     aPrimSegments->AddVertex (aLineEndPoint);
964
965     Prs3d_Root::CurrentGroup (thePresentation)->SetPrimitivesAspect (aDimensionAspect->LineAspect()->Aspect());
966     Prs3d_Root::CurrentGroup (thePresentation)->AddPrimitiveArray (aPrimSegments);
967   }
968
969   mySelectionGeom.IsComputed = Standard_True;
970 }
971
972 //=======================================================================
973 //function : ComputeLinearFlyouts
974 //purpose  :
975 //=======================================================================
976 void AIS_Dimension::ComputeLinearFlyouts (const Handle(SelectMgr_Selection)& theSelection,
977                                           const Handle(SelectMgr_EntityOwner)& theOwner,
978                                           const gp_Pnt& theFirstPoint,
979                                           const gp_Pnt& theSecondPoint)
980 {
981   // count flyout direction
982   gp_Ax1 aPlaneNormal = GetPlane().Axis();
983   gp_Dir aTargetPointsVector = gce_MakeDir (theFirstPoint, theSecondPoint);
984
985   // count a flyout direction vector.
986   gp_Dir aFlyoutVector = aPlaneNormal.Direction() ^ aTargetPointsVector;
987
988   // create lines for layouts
989   gp_Lin aLine1 (theFirstPoint,  aFlyoutVector);
990   gp_Lin aLine2 (theSecondPoint, aFlyoutVector);
991
992   // get flyout end points
993   gp_Pnt aFlyoutEnd1 = ElCLib::Value (ElCLib::Parameter (aLine1, theFirstPoint) + GetFlyout(), aLine1);
994   gp_Pnt aFlyoutEnd2 = ElCLib::Value (ElCLib::Parameter (aLine2, theSecondPoint) + GetFlyout(), aLine2);
995
996   // fill sensitive entity for flyouts
997   Handle(Select3D_SensitiveGroup) aSensitiveEntity = new Select3D_SensitiveGroup (theOwner);
998   aSensitiveEntity->Add (new Select3D_SensitiveSegment (theOwner, theFirstPoint, aFlyoutEnd1));
999   aSensitiveEntity->Add (new Select3D_SensitiveSegment (theOwner, theSecondPoint, aFlyoutEnd2));
1000   theSelection->Add (aSensitiveEntity);
1001 }
1002
1003 //=======================================================================
1004 //function : CircleFromPlanarFace
1005 //purpose  : if possible computes circle from planar face
1006 //=======================================================================
1007 Standard_Boolean AIS_Dimension::CircleFromPlanarFace (const TopoDS_Face& theFace,
1008                                                       Handle(Geom_Curve)& theCurve,
1009                                                       gp_Pnt& theFirstPoint,
1010                                                       gp_Pnt& theLastPoint)
1011 {
1012   TopExp_Explorer anIt (theFace, TopAbs_EDGE);
1013   for ( ; anIt.More(); anIt.Next())
1014   {
1015     TopoDS_Edge aCurEdge =  TopoDS::Edge (anIt.Current());
1016     if (AIS::ComputeGeometry (aCurEdge, theCurve, theFirstPoint, theLastPoint))
1017     {
1018       if (theCurve->IsInstance (STANDARD_TYPE(Geom_Circle)))
1019       {
1020         return Standard_True;
1021       }
1022     }
1023   }
1024   return Standard_False;
1025 }
1026
1027 //=======================================================================
1028 //function : CircleFromEdge
1029 //purpose  : if possible computes circle from edge
1030 //=======================================================================
1031 Standard_Boolean AIS_Dimension::CircleFromEdge (const TopoDS_Edge& theEdge,
1032                                                 gp_Circ&           theCircle,
1033                                                 gp_Pnt&            theFirstPoint,
1034                                                 gp_Pnt&            theLastPoint)
1035 {
1036   BRepAdaptor_Curve anAdaptedCurve (theEdge);
1037   switch (anAdaptedCurve.GetType())
1038   {
1039     case GeomAbs_Circle:
1040     {
1041       theCircle = anAdaptedCurve.Circle();
1042       break;
1043     }
1044     case GeomAbs_Ellipse:
1045     {
1046       gp_Elips anEll = anAdaptedCurve.Ellipse();
1047       if ((anEll.MinorRadius() - anEll.MajorRadius()) >= Precision::Confusion())
1048       {
1049         return Standard_False;
1050       }
1051       theCircle = gp_Circ(anEll.Position(),anEll.MinorRadius());
1052       break;
1053     }
1054     case GeomAbs_Line:
1055     case GeomAbs_Hyperbola:
1056     case GeomAbs_Parabola:
1057     case GeomAbs_BezierCurve:
1058     case GeomAbs_BSplineCurve:
1059     case GeomAbs_OtherCurve:
1060     default:
1061       return Standard_False;
1062   }
1063
1064   theFirstPoint = anAdaptedCurve.Value (anAdaptedCurve.FirstParameter());
1065   theLastPoint  = anAdaptedCurve.Value (anAdaptedCurve.LastParameter());
1066   return Standard_True;
1067 }
1068
1069 //=======================================================================
1070 //function : InitCircularDimension
1071 //purpose  : 
1072 //=======================================================================
1073 Standard_Boolean AIS_Dimension::InitCircularDimension (const TopoDS_Shape& theShape,
1074                                                        gp_Circ& theCircle,
1075                                                        gp_Pnt& theMiddleArcPoint,
1076                                                        Standard_Boolean& theIsClosed)
1077 {
1078   gp_Pln aPln;
1079   Handle(Geom_Surface) aBasisSurf;
1080   AIS_KindOfSurface aSurfType = AIS_KOS_OtherSurface;
1081   gp_Pnt aFirstPoint, aLastPoint;
1082   Standard_Real anOffset    = 0.0;
1083   Standard_Real aFirstParam = 0.0;
1084   Standard_Real aLastParam  = 0.0;
1085
1086   // Discover circular geometry
1087   switch (theShape.ShapeType())
1088   {
1089     case TopAbs_FACE:
1090     {
1091       AIS::GetPlaneFromFace (TopoDS::Face (theShape), aPln, aBasisSurf, aSurfType, anOffset);
1092
1093       if (aSurfType == AIS_KOS_Plane)
1094       {
1095         Handle(Geom_Curve) aCurve;
1096         if (!CircleFromPlanarFace (TopoDS::Face (theShape), aCurve, aFirstPoint, aLastPoint))
1097         {
1098           return Standard_False;
1099         }
1100
1101         theCircle = Handle(Geom_Circle)::DownCast (aCurve)->Circ();
1102       }
1103       else
1104       {
1105         gp_Pnt aCurPos;
1106         BRepAdaptor_Surface aSurf1 (TopoDS::Face (theShape));
1107         Standard_Real aFirstU = aSurf1.FirstUParameter();
1108         Standard_Real aLastU  = aSurf1.LastUParameter();
1109         Standard_Real aFirstV = aSurf1.FirstVParameter();
1110         Standard_Real aLastV  = aSurf1.LastVParameter();
1111         Standard_Real aMidU   = (aFirstU + aLastU) * 0.5;
1112         Standard_Real aMidV   = (aFirstV + aLastV) * 0.5;
1113         aSurf1.D0 (aMidU, aMidV, aCurPos);
1114         Handle (Adaptor3d_HCurve) aBasisCurve;
1115         Standard_Boolean isExpectedType = Standard_False;
1116         if (aSurfType == AIS_KOS_Cylinder)
1117         {
1118           isExpectedType = Standard_True;
1119         }
1120         else
1121         {
1122           if (aSurfType == AIS_KOS_Revolution)
1123           {
1124             aBasisCurve = aSurf1.BasisCurve();
1125             if (aBasisCurve->GetType() == GeomAbs_Line)
1126             {
1127               isExpectedType = Standard_True;
1128             }
1129           }
1130           else if (aSurfType == AIS_KOS_Extrusion)
1131           {
1132             aBasisCurve = aSurf1.BasisCurve();
1133             if (aBasisCurve->GetType() == GeomAbs_Circle)
1134             {
1135               isExpectedType = Standard_True;
1136             }
1137           }
1138         }
1139
1140         if (!isExpectedType)
1141         {
1142           return Standard_False;
1143         }
1144
1145         Handle(Geom_Curve) aCurve = aBasisSurf->VIso(aMidV);
1146         if (aCurve->DynamicType() == STANDARD_TYPE (Geom_Circle))
1147         {
1148           theCircle = Handle(Geom_Circle)::DownCast (aCurve)->Circ();
1149         }
1150         else if (aCurve->DynamicType() == STANDARD_TYPE (Geom_TrimmedCurve))
1151         {
1152           Handle(Geom_TrimmedCurve) aTrimmedCurve = Handle(Geom_TrimmedCurve)::DownCast (aCurve);
1153           aFirstU = aTrimmedCurve->FirstParameter();
1154           aLastU  = aTrimmedCurve->LastParameter();
1155           if (aTrimmedCurve->BasisCurve()->DynamicType() == STANDARD_TYPE (Geom_Circle))
1156           {
1157             theCircle = Handle(Geom_Circle)::DownCast(aTrimmedCurve->BasisCurve())->Circ();
1158           }
1159         }
1160         else
1161         {
1162           // Compute a circle from 3 points on "aCurve"
1163           gp_Pnt aP1, aP2;
1164           aSurf1.D0 (aFirstU, aMidV, aP1);
1165           aSurf1.D0 (aLastU, aMidV, aP2);
1166           GC_MakeCircle aMkCirc (aP1, aCurPos, aP2);
1167           theCircle = aMkCirc.Value()->Circ();
1168         }
1169
1170         aFirstPoint = ElCLib::Value (aFirstU, theCircle);
1171         aLastPoint = ElCLib::Value (aLastU,  theCircle);
1172       }
1173       break;
1174     }
1175     case TopAbs_WIRE:
1176     {
1177       TopoDS_Edge anEdge;
1178       TopExp_Explorer anIt (theShape, TopAbs_EDGE);
1179       if (anIt.More())
1180       {
1181         anEdge = TopoDS::Edge (anIt.Current());
1182       }
1183       if (!AIS_Dimension::CircleFromEdge (anEdge, theCircle, aFirstPoint, aLastPoint))
1184       {
1185         return Standard_False;
1186       }
1187       break;
1188     }
1189     case TopAbs_EDGE:
1190     {
1191       TopoDS_Edge anEdge = TopoDS::Edge (theShape);
1192       if (!AIS_Dimension::CircleFromEdge (anEdge, theCircle, aFirstPoint, aLastPoint))
1193       {
1194         return Standard_False;
1195       }
1196       break;
1197     }
1198     case TopAbs_COMPOUND:
1199     case TopAbs_COMPSOLID:
1200     case TopAbs_SOLID:
1201     case TopAbs_SHELL:
1202     case TopAbs_VERTEX:
1203     case TopAbs_SHAPE:
1204     default:
1205       return Standard_False;
1206   }
1207
1208   theIsClosed = aFirstPoint.IsEqual (aLastPoint, Precision::Confusion());
1209
1210   gp_Pnt aCenter = theCircle.Location();
1211
1212   if (theIsClosed) // Circle
1213   {
1214     gp_Dir anXDir = theCircle.XAxis().Direction();
1215     theMiddleArcPoint = aCenter.Translated (gp_Vec (anXDir) * theCircle.Radius());
1216   }
1217   else // Arc
1218   {
1219     aFirstParam = ElCLib::Parameter (theCircle, aFirstPoint);
1220     aLastParam  = ElCLib::Parameter (theCircle, aLastPoint);
1221     if (aFirstParam > aLastParam)
1222     {
1223       aFirstParam -= 2.0 * M_PI;
1224     }
1225
1226     Standard_Real aParCurPos = (aFirstParam + aLastParam) * 0.5;
1227     gp_Vec aVec = gp_Vec (aCenter, ElCLib::Value (aParCurPos, theCircle)).Normalized () * theCircle.Radius ();
1228     theMiddleArcPoint = aCenter.Translated (aVec);
1229   }
1230
1231   return Standard_True;
1232 }
1233
1234 //=======================================================================
1235 //function : ComputeSelection
1236 //purpose  : 
1237 //=======================================================================
1238 void AIS_Dimension::ComputeSelection (const Handle(SelectMgr_Selection)& theSelection,
1239                                       const Standard_Integer theMode)
1240 {
1241   if (!mySelectionGeom.IsComputed)
1242   {
1243     return;
1244   }
1245
1246   AIS_DimensionSelectionMode aSelectionMode = (AIS_DimensionSelectionMode)theMode;
1247
1248   // init appropriate entity owner
1249   Handle(SelectMgr_EntityOwner) aSensitiveOwner;
1250
1251   switch (aSelectionMode)
1252   {
1253     // neutral selection owner
1254     case AIS_DSM_All :
1255       aSensitiveOwner = new SelectMgr_EntityOwner (this, THE_NEUTRAL_SEL_PRIORITY);
1256       break;
1257
1258     // local selection owners
1259     case AIS_DSM_Line :
1260     case AIS_DSM_Text :
1261       aSensitiveOwner = new AIS_DimensionOwner (this, aSelectionMode, THE_LOCAL_SEL_PRIORITY);
1262       break;
1263   }
1264
1265   if (aSelectionMode == AIS_DSM_All || aSelectionMode == AIS_DSM_Line)
1266   {
1267     // sensitives for dimension line segments
1268     Handle(Select3D_SensitiveGroup) aGroupOfSensitives = new Select3D_SensitiveGroup (aSensitiveOwner);
1269
1270     SelectionGeometry::SeqOfCurves::Iterator aCurveIt (mySelectionGeom.DimensionLine);
1271     for (; aCurveIt.More(); aCurveIt.Next())
1272     {
1273       const SelectionGeometry::HCurve& aCurveData = aCurveIt.Value();
1274
1275       TColgp_Array1OfPnt aSensitivePnts (1, aCurveData->Length());
1276       for (Standard_Integer aPntIt = 1; aPntIt <= aCurveData->Length(); ++aPntIt)
1277       {
1278         aSensitivePnts.ChangeValue (aPntIt) = aCurveData->Value (aPntIt);
1279       }
1280
1281       aGroupOfSensitives->Add (new Select3D_SensitiveCurve (aSensitiveOwner, aSensitivePnts));
1282     }
1283
1284     Quantity_Length anArrowLength = myDrawer->DimensionAspect()->ArrowAspect()->Length();
1285     Standard_Real   anArrowAngle  = myDrawer->DimensionAspect()->ArrowAspect()->Angle();
1286
1287     // sensitives for arrows
1288     SelectionGeometry::SeqOfArrows::Iterator anArrowIt (mySelectionGeom.Arrows);
1289     for (; anArrowIt.More(); anArrowIt.Next())
1290     {
1291       const SelectionGeometry::HArrow& anArrow = anArrowIt.Value();
1292
1293       gp_Pnt aSidePnt1 (gp::Origin());
1294       gp_Pnt aSidePnt2 (gp::Origin());
1295       const gp_Dir& aPlane = GetPlane().Axis().Direction();
1296       const gp_Pnt& aPeak  = anArrow->Position;
1297       const gp_Dir& aDir   = anArrow->Direction;
1298
1299       // compute points for arrow in plane
1300       PointsForArrow (aPeak, aDir, aPlane, anArrowLength, anArrowAngle, aSidePnt1, aSidePnt2);
1301
1302       aGroupOfSensitives->Add (new Select3D_SensitiveTriangle (aSensitiveOwner, aPeak, aSidePnt1, aSidePnt2));
1303
1304       if (!myDrawer->DimensionAspect()->IsArrows3d())
1305       {
1306         continue;
1307       }
1308
1309       // compute points for orthogonal sensitive plane
1310       gp_Dir anOrthoPlane = anArrow->Direction.Crossed (aPlane);
1311
1312       PointsForArrow (aPeak, aDir, anOrthoPlane, anArrowLength, anArrowAngle, aSidePnt1, aSidePnt2);
1313
1314       aGroupOfSensitives->Add (new Select3D_SensitiveTriangle (aSensitiveOwner, aPeak, aSidePnt1, aSidePnt2));
1315     }
1316
1317     theSelection->Add (aGroupOfSensitives);
1318   }
1319
1320   // sensitives for text element
1321   if (aSelectionMode == AIS_DSM_All || aSelectionMode == AIS_DSM_Text)
1322   {
1323     Handle(Select3D_SensitiveEntity) aTextSensitive;
1324
1325     gp_Ax2 aTextAxes (mySelectionGeom.TextPos,
1326                       GetPlane().Axis().Direction(),
1327                       mySelectionGeom.TextDir);
1328
1329     if (myDrawer->DimensionAspect()->IsText3d())
1330     {
1331       // sensitive planar rectangle for text
1332       Standard_Real aDx = mySelectionGeom.TextWidth  * 0.5;
1333       Standard_Real aDy = mySelectionGeom.TextHeight * 0.5;
1334
1335       gp_Trsf aLabelPlane;
1336       aLabelPlane.SetTransformation (aTextAxes, gp::XOY());
1337
1338       TColgp_Array1OfPnt aRectanglePoints(1, 4);
1339       aRectanglePoints.ChangeValue(1) = gp_Pnt (-aDx, -aDy, 0.0).Transformed (aLabelPlane);
1340       aRectanglePoints.ChangeValue(2) = gp_Pnt (-aDx,  aDy, 0.0).Transformed (aLabelPlane);
1341       aRectanglePoints.ChangeValue(3) = gp_Pnt ( aDx,  aDy, 0.0).Transformed (aLabelPlane);
1342       aRectanglePoints.ChangeValue(4) = gp_Pnt ( aDx, -aDy, 0.0).Transformed (aLabelPlane);
1343
1344       Poly_Array1OfTriangle aTriangles(1, 2);
1345       aTriangles.ChangeValue(1) = Poly_Triangle(1, 2, 3);
1346       aTriangles.ChangeValue(2) = Poly_Triangle(1, 3, 4);
1347
1348       Handle(Poly_Triangulation) aRectanglePoly = 
1349         new Poly_Triangulation(aRectanglePoints, aTriangles);
1350
1351       aTextSensitive =
1352         new Select3D_SensitiveTriangulation (aSensitiveOwner, aRectanglePoly, TopLoc_Location(), Standard_True);
1353     }
1354     else
1355     {
1356       gp_Circ aTextGeom (aTextAxes, mySelToleranceForText2d != 0.0 
1357                                       ? mySelToleranceForText2d : 1.0);
1358
1359       Handle(Geom_Circle) aSensGeom = new Geom_Circle (aTextGeom);
1360
1361       aTextSensitive = new Select3D_SensitiveCircle (aSensitiveOwner, aSensGeom, Standard_True);
1362     }
1363
1364     theSelection->Add (aTextSensitive);
1365   }
1366
1367   // callback for flyout sensitive calculation
1368   if (aSelectionMode == AIS_DSM_All)
1369   {
1370     ComputeFlyoutSelection (theSelection, aSensitiveOwner);
1371   }
1372 }
1373
1374 //=======================================================================
1375 //function : PointsForArrow
1376 //purpose  : 
1377 //=======================================================================
1378 void AIS_Dimension::PointsForArrow (const gp_Pnt& thePeakPnt,
1379                                     const gp_Dir& theDirection,
1380                                     const gp_Dir& thePlane,
1381                                     const Standard_Real theArrowLength,
1382                                     const Standard_Real theArrowAngle,
1383                                     gp_Pnt& theSidePnt1,
1384                                     gp_Pnt& theSidePnt2)
1385 {
1386   gp_Lin anArrowLin (thePeakPnt, theDirection.Reversed());
1387   gp_Pnt anArrowEnd = ElCLib::Value (theArrowLength, anArrowLin);
1388   gp_Lin anEdgeLin (anArrowEnd, theDirection.Crossed (thePlane));
1389
1390   Standard_Real anEdgeLength = Tan (theArrowAngle) * theArrowLength;
1391
1392   theSidePnt1 = ElCLib::Value ( anEdgeLength, anEdgeLin);
1393   theSidePnt2 = ElCLib::Value (-anEdgeLength, anEdgeLin);
1394 }
1395
1396 //=======================================================================
1397 //function : GetTextPositionForLinear
1398 //purpose  : 
1399 //=======================================================================
1400 gp_Pnt AIS_Dimension::GetTextPositionForLinear (const gp_Pnt& theFirstPoint,
1401                                                 const gp_Pnt& theSecondPoint,
1402                                                 const Standard_Boolean theIsOneSide) const
1403 {
1404   if (!IsValid())
1405   {
1406     return gp::Origin();
1407   }
1408
1409   gp_Pnt aTextPosition (gp::Origin());
1410
1411   Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
1412
1413   // Get label alignment and arrow orientation.
1414   Standard_Integer aLabelPosition = 0;
1415   Standard_Boolean isArrowsExternal = Standard_False;
1416   FitTextAlignmentForLinear (theFirstPoint, theSecondPoint, theIsOneSide,
1417                              aDimensionAspect->TextHorizontalPosition(),
1418                              aLabelPosition, isArrowsExternal);
1419
1420   // Compute dimension line points.
1421   gp_Dir aPlaneNormal = GetPlane().Axis().Direction();
1422   gp_Vec aTargetPointsVec (theFirstPoint, theSecondPoint);
1423
1424   // Compute flyout direction vector
1425   gp_Dir aFlyoutVector = aPlaneNormal ^ gp_Dir (aTargetPointsVec);
1426
1427   // create lines for layouts
1428   gp_Lin aLine1 (theFirstPoint, aFlyoutVector);
1429   gp_Lin aLine2 (theSecondPoint, aFlyoutVector);
1430   // Get flyout end points
1431   gp_Pnt aLineBegPoint = ElCLib::Value (ElCLib::Parameter (aLine1, theFirstPoint)  + GetFlyout(), aLine1);
1432   gp_Pnt aLineEndPoint = ElCLib::Value (ElCLib::Parameter (aLine2, theSecondPoint) + GetFlyout(), aLine2);
1433
1434   // Get text position.
1435   switch (aLabelPosition & LabelPosition_HMask)
1436   {
1437   case LabelPosition_Left:
1438     {
1439       gp_Dir aTargetPointsDir = gce_MakeDir (theFirstPoint, theSecondPoint);
1440       Standard_Real anExtensionSize = aDimensionAspect->ExtensionSize();
1441
1442       Standard_Real anOffset = isArrowsExternal
1443                                  ? anExtensionSize + aDimensionAspect->ArrowAspect()->Length()
1444                                  : anExtensionSize;
1445       gp_Vec anExtensionVec = gp_Vec (aTargetPointsDir) * -anOffset;
1446       aTextPosition = aLineEndPoint.Translated (anExtensionVec);
1447     }
1448     break;
1449   case LabelPosition_Right:
1450     {
1451       gp_Dir aTargetPointsDir = gce_MakeDir (theFirstPoint, theSecondPoint);
1452       Standard_Real anExtensionSize = aDimensionAspect->ExtensionSize();
1453
1454       Standard_Real anOffset = isArrowsExternal
1455                                  ? anExtensionSize + aDimensionAspect->ArrowAspect()->Length()
1456                                  : anExtensionSize;
1457       gp_Vec anExtensionVec = gp_Vec (aTargetPointsDir) * anOffset;
1458       aTextPosition = aLineBegPoint.Translated (anExtensionVec);
1459     }
1460     break;
1461   case LabelPosition_HCenter:
1462     {
1463       aTextPosition = (aLineBegPoint.XYZ() + aLineEndPoint.XYZ()) * 0.5;
1464     }
1465     break;
1466   }
1467
1468   return aTextPosition;
1469 }
1470
1471 //=======================================================================
1472 //function : AdjustParametersForLinear
1473 //purpose  : 
1474 //=======================================================================
1475 Standard_Boolean AIS_Dimension::AdjustParametersForLinear (const gp_Pnt& theTextPos,
1476                                                            const gp_Pnt& theFirstPoint,
1477                                                            const gp_Pnt& theSecondPoint,
1478                                                            Standard_Real& theExtensionSize,
1479                                                            Prs3d_DimensionTextHorizontalPosition& theAlignment,
1480                                                            Standard_Real& theFlyout,
1481                                                            gp_Pln& thePlane,
1482                                                            Standard_Boolean& theIsPlaneOld) const
1483 {
1484   Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
1485   Standard_Real anArrowLength = aDimensionAspect->ArrowAspect()->Length();
1486
1487   gp_Dir aTargetPointsDir = gce_MakeDir (theFirstPoint, theSecondPoint);
1488   gp_Vec aTargetPointsVec (theFirstPoint, theSecondPoint);
1489
1490   // Don't set new plane if the text position lies on the attachment points line.
1491   gp_Lin aTargetPointsLin (theFirstPoint, aTargetPointsDir);
1492   if (!aTargetPointsLin.Contains (theTextPos, Precision::Confusion()))
1493   {
1494     //Set new automatic plane.
1495     thePlane = gce_MakePln (theTextPos, theFirstPoint, theSecondPoint);
1496     theIsPlaneOld = Standard_False;
1497   }
1498
1499   // Compute flyout direction vector.
1500   gp_Dir aPlaneNormal = GetPlane().Axis().Direction();
1501   gp_Dir aPositiveFlyout = aPlaneNormal ^ aTargetPointsDir;
1502
1503   // Additional check of collinearity of the plane normal and attachment points vector.
1504   if (aPlaneNormal.IsParallel (aTargetPointsDir, Precision::Angular()))
1505   {
1506     return Standard_False;
1507   }
1508
1509   // Set flyout.
1510   gp_Vec aFirstToTextVec (theFirstPoint, theTextPos);
1511
1512   Standard_Real aCos = aFirstToTextVec.Normalized() * gp_Vec (aTargetPointsDir);
1513
1514   gp_Pnt aTextPosProj = theFirstPoint.Translated
1515     (gp_Vec (aTargetPointsDir) * aFirstToTextVec.Magnitude() * aCos);
1516
1517   // Compute flyout value and direction.
1518   gp_Vec aFlyoutVector = gp_Vec (aTextPosProj, theTextPos);
1519
1520   theFlyout = 0.0;
1521   if (aFlyoutVector.Magnitude() > Precision::Confusion())
1522   {
1523     theFlyout = gp_Dir (aFlyoutVector).IsOpposite (aPositiveFlyout, Precision::Angular())
1524                 ? -aFlyoutVector.Magnitude()
1525                 :  aFlyoutVector.Magnitude();
1526   }
1527   
1528   // Compute attach points (through which main dimension line passes).
1529   gp_Pnt aFirstAttach  = theFirstPoint.Translated (aFlyoutVector);
1530   gp_Pnt aSecondAttach = theSecondPoint.Translated (aFlyoutVector);
1531
1532   // Set horizontal text alignment.
1533   if (aCos < 0.0)
1534   {
1535     theAlignment = Prs3d_DTHP_Left;
1536
1537     Standard_Real aNewExtSize = theTextPos.Distance (aFirstAttach) - anArrowLength;
1538     theExtensionSize = aNewExtSize < 0.0 ? 0.0 : aNewExtSize;
1539   }
1540   else if (aTextPosProj.Distance (theFirstPoint) > theFirstPoint.Distance (theSecondPoint))
1541   {
1542     theAlignment = Prs3d_DTHP_Right;
1543
1544     Standard_Real aNewExtSize = theTextPos.Distance (aSecondAttach) - anArrowLength;
1545     theExtensionSize = aNewExtSize < 0.0 ? 0.0 : aNewExtSize;
1546   }
1547   else
1548   {
1549     theAlignment = Prs3d_DTHP_Center;
1550   }
1551   return Standard_True;
1552 }
1553
1554 //=======================================================================
1555 //function : FitTextAlignmentForLinear
1556 //purpose  : 
1557 //=======================================================================
1558 void AIS_Dimension::FitTextAlignmentForLinear (const gp_Pnt& theFirstPoint,
1559                                                const gp_Pnt& theSecondPoint,
1560                                                const Standard_Boolean theIsOneSide,
1561                                                const Prs3d_DimensionTextHorizontalPosition& theHorizontalTextPos,
1562                                                Standard_Integer& theLabelPosition,
1563                                                Standard_Boolean& theIsArrowsExternal) const
1564 {
1565   theLabelPosition = LabelPosition_None;
1566   theIsArrowsExternal = Standard_False;
1567
1568   // Compute dimension line points
1569   gp_Ax1 aPlaneNormal = GetPlane().Axis();
1570   gp_Dir aTargetPointsVector = gce_MakeDir (theFirstPoint, theSecondPoint);
1571
1572   // compute flyout direction vector
1573   gp_Dir aFlyoutVector = aPlaneNormal.Direction() ^ aTargetPointsVector;
1574
1575   // create lines for layouts
1576   gp_Lin aLine1 (theFirstPoint, aFlyoutVector);
1577   gp_Lin aLine2 (theSecondPoint, aFlyoutVector);
1578
1579   // Get flyout end points
1580   gp_Pnt aLineBegPoint = ElCLib::Value (ElCLib::Parameter (aLine1, theFirstPoint)  + GetFlyout(), aLine1);
1581   gp_Pnt aLineEndPoint = ElCLib::Value (ElCLib::Parameter (aLine2, theSecondPoint) + GetFlyout(), aLine2);
1582
1583   Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
1584
1585   // For extensions we need to know arrow size, text size and extension size: get it from aspect
1586   Quantity_Length anArrowLength = aDimensionAspect->ArrowAspect()->Length();
1587
1588   // prepare label string and compute its geometrical width
1589   Standard_Real aLabelWidth;
1590   TCollection_ExtendedString aLabelString = GetValueString (aLabelWidth);
1591
1592   // Add margins to cut dimension lines for 3d text
1593   if (aDimensionAspect->IsText3d())
1594   {
1595     aLabelWidth += aDimensionAspect->TextAspect()->Height() * THE_3D_TEXT_MARGIN * 2.0;
1596   }
1597
1598   // Handle user-defined and automatic arrow placement
1599   switch (aDimensionAspect->ArrowOrientation())
1600   {
1601     case Prs3d_DAO_External: theIsArrowsExternal = true; break;
1602     case Prs3d_DAO_Internal: theIsArrowsExternal = false; break;
1603     case Prs3d_DAO_Fit:
1604     {
1605       // Add margin to ensure a small tail between text and arrow
1606       Standard_Real anArrowMargin   = aDimensionAspect->IsText3d() 
1607                                     ? aDimensionAspect->TextAspect()->Height() * THE_3D_TEXT_MARGIN
1608                                     : 0.0;
1609
1610       Standard_Real aDimensionWidth = aLineBegPoint.Distance (aLineEndPoint);
1611       Standard_Real anArrowsWidth   = theIsOneSide 
1612                                       ?  anArrowLength + anArrowMargin
1613                                       : (anArrowLength + anArrowMargin) * 2.0;
1614
1615       theIsArrowsExternal = aDimensionWidth < aLabelWidth + anArrowsWidth;
1616       break;
1617     }
1618   }
1619
1620   // Handle user-defined and automatic text placement
1621   switch (theHorizontalTextPos)
1622   {
1623     case Prs3d_DTHP_Left  : theLabelPosition |= LabelPosition_Left; break;
1624     case Prs3d_DTHP_Right : theLabelPosition |= LabelPosition_Right; break;
1625     case Prs3d_DTHP_Center: theLabelPosition |= LabelPosition_HCenter; break;
1626     case Prs3d_DTHP_Fit:
1627     {
1628       Standard_Real aDimensionWidth = aLineBegPoint.Distance (aLineEndPoint);
1629       Standard_Real anArrowsWidth   = theIsOneSide ? anArrowLength : 2.0 * anArrowLength;
1630       Standard_Real aContentWidth   = theIsArrowsExternal ? aLabelWidth : aLabelWidth + anArrowsWidth;
1631
1632       theLabelPosition |= aDimensionWidth < aContentWidth ? LabelPosition_Left : LabelPosition_HCenter;
1633       break;
1634     }
1635   }
1636
1637   // Handle vertical text placement options
1638   switch (aDimensionAspect->TextVerticalPosition())
1639   {
1640     case Prs3d_DTVP_Above  : theLabelPosition |= LabelPosition_Above; break;
1641     case Prs3d_DTVP_Below  : theLabelPosition |= LabelPosition_Below; break;
1642     case Prs3d_DTVP_Center : theLabelPosition |= LabelPosition_VCenter; break;
1643   }
1644 }
1645
1646 //=======================================================================
1647 //function : UnsetFixedTextPosition
1648 //purpose  : 
1649 //=======================================================================
1650 void AIS_Dimension::UnsetFixedTextPosition()
1651 {
1652   myIsTextPositionFixed = Standard_False;
1653   myFixedTextPosition = gp::Origin();
1654 }