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