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