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