0024293: Dimension extensions don't belong to the dimension sensitive entity: compute...
[occt.git] / src / AIS / AIS_Dimension.cxx
1 // Copyright (c) 1999-2013 OPEN CASCADE SAS
2 //
3 // The content of this file is subject to the Open CASCADE Technology Public
4 // License Version 6.5 (the "License"). You may not use the content of this file
5 // except in compliance with the License. Please obtain a copy of the License
6 // at http://www.opencascade.org and read it completely before using this file.
7 //
8 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
9 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
10 //
11 // The Original Code and all software distributed under the License is
12 // distributed on an "AS IS" basis, without warranty of any kind, and the
13 // Initial Developer hereby disclaims all such warranties, including without
14 // limitation, any warranties of merchantability, fitness for a particular
15 // purpose or non-infringement. Please see the License for the specific terms
16 // and conditions governing the rights and limitations under the License.
17
18 #include <AIS.hxx>
19 #include <AIS_Dimension.hxx>
20 #include <AIS_DimensionDisplayMode.hxx>
21 #include <AIS_DimensionOwner.hxx>
22 #include <AIS_Drawer.hxx>
23 #include <Adaptor3d_HCurve.hxx>
24 #include <BRepAdaptor_Curve.hxx>
25 #include <BRepAdaptor_Surface.hxx>
26 #include <BRepBuilderAPI_MakeEdge.hxx>
27 #include <BRepLib_MakeVertex.hxx>
28 #include <BRepBndLib.hxx>
29 #include <GeomAdaptor_Curve.hxx>
30 #include <ElCLib.hxx>
31 #include <Font_BRepFont.hxx>
32 #include <GC_MakeCircle.hxx>
33 #include <Geom_Circle.hxx>
34 #include <Geom_Plane.hxx>
35 #include <Geom_TrimmedCurve.hxx>
36 #include <gce_MakeDir.hxx>
37 #include <gce_MakeLin.hxx>
38 #include <Graphic3d_ArrayOfSegments.hxx>
39 #include <Graphic3d_ArrayOfTriangles.hxx>
40 #include <Graphic3d_AspectLine3d.hxx>
41 #include <Graphic3d_AspectFillArea3d.hxx>
42 #include <Graphic3d_AspectText3d.hxx>
43 #include <Graphic3d_Group.hxx>
44 #include <PrsMgr_PresentationManager3d.hxx>
45 #include <Prs3d_Arrow.hxx>
46 #include <Prs3d_ArrowAspect.hxx>
47 #include <Prs3d_Drawer.hxx>
48 #include <Prs3d_LineAspect.hxx>
49 #include <Prs3d_Presentation.hxx>
50 #include <Prs3d_Root.hxx>
51 #include <Prs3d_ShadingAspect.hxx>
52 #include <Prs3d_Text.hxx>
53 #include <SelectMgr_EntityOwner.hxx>
54 #include <SelectMgr_Selection.hxx>
55 #include <SelectMgr_SequenceOfOwner.hxx>
56 #include <Select3D_ListIteratorOfListOfSensitive.hxx>
57 #include <Select3D_ListOfSensitive.hxx>
58 #include <Select3D_SensitiveBox.hxx>
59 #include <Select3D_SensitiveCircle.hxx>
60 #include <Select3D_SensitiveGroup.hxx>
61 #include <Select3D_SensitiveSegment.hxx>
62 #include <Standard_CString.hxx>
63 #include <StdPrs_ShadedShape.hxx>
64 #include <StdPrs_WFShape.hxx>
65 #include <TCollection_AsciiString.hxx>
66 #include <TCollection_ExtendedString.hxx>
67 #include <TopExp_Explorer.hxx>
68 #include <TopoDS.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_HANDLE(AIS_Dimension, AIS_InteractiveObject)
76 IMPLEMENT_STANDARD_RTTIEXT(AIS_Dimension, AIS_InteractiveObject)
77
78 //=======================================================================
79 //function : Constructor
80 //purpose  : 
81 //=======================================================================
82
83 AIS_Dimension::AIS_Dimension (const Standard_Real theExtensionSize /*= 1.0*/)
84 : AIS_InteractiveObject(),
85   myDefaultPlane (gp_Pln (gp::XOY())),
86   myIsWorkingPlaneCustom (Standard_False),
87   myValue (0.0),
88   myIsValueCustom (Standard_False),
89   myUnitsQuantity (TCollection_AsciiString("LENGTH")),
90   myToDisplayUnits (Standard_False),
91   mySpecialSymbol (' '),
92   myDisplaySpecialSymbol (AIS_DSS_No),
93   myIsTextReversed (Standard_False),
94   myTextOffset (DimensionAspect()->ArrowAspect()->Length()),
95   myIsInitialized (Standard_False),
96   myFlyout (0.0),
97   myKindOfDimension (AIS_KOD_NONE),
98   myExtensionSize (theExtensionSize)
99 {
100   ResetWorkingPlane();
101   // Units default settings
102   UnitsAPI::SetLocalSystem (UnitsAPI_SI);
103   myModelUnits = Units::DictionaryOfUnits()->ActiveUnit (myUnitsQuantity.ToCString());
104   myDisplayUnits = Units::DictionaryOfUnits()->ActiveUnit (myUnitsQuantity.ToCString());
105 }
106
107 //=======================================================================
108 //function : Constructor
109 //purpose  : 
110 //=======================================================================
111
112 AIS_Dimension::AIS_Dimension (const Handle(Prs3d_DimensionAspect)& theAspect,
113                               const Standard_Real theExtensionSize /*= 1.0*/)
114 : AIS_InteractiveObject(),
115   myDefaultPlane (gp_Pln (gp::XOY())),
116   myIsWorkingPlaneCustom (Standard_False),
117   myValue (0.0),
118   myIsValueCustom (Standard_False),
119   myUnitsQuantity (TCollection_AsciiString("LENGTH")),
120   myToDisplayUnits (Standard_False),
121   mySpecialSymbol (' '),
122   myDisplaySpecialSymbol (AIS_DSS_No),
123   myIsTextReversed (Standard_False),
124   myTextOffset (DimensionAspect()->ArrowAspect()->Length()),
125   myIsInitialized (Standard_False),
126   myFlyout (0.0),
127   myKindOfDimension (AIS_KOD_NONE),
128   myExtensionSize (theExtensionSize)
129 {
130   ResetWorkingPlane();
131   // Units default settings
132   UnitsAPI::SetLocalSystem (UnitsAPI_SI);
133   myModelUnits = Units::DictionaryOfUnits()->ActiveUnit (myUnitsQuantity.ToCString());
134   myDisplayUnits = Units::DictionaryOfUnits()->ActiveUnit (myUnitsQuantity.ToCString());
135   SetDimensionAspect (theAspect);
136 }
137
138 //=======================================================================
139 //function : AcceptDisplayMode
140 //purpose  : Checks if display mode <theMode> is allowed to display object.
141 //=======================================================================
142
143 Standard_Boolean AIS_Dimension::AcceptDisplayMode (const Standard_Integer theMode) const
144 {
145   return theMode == 0 ? Standard_True : Standard_False;
146 }
147
148 //=======================================================================
149 //function : computeValue
150 //purpose  : Computes dimension value in display units.
151 //=======================================================================
152
153 void AIS_Dimension::computeValue()
154 {
155   UnitsAPI::SetCurrentUnit (myUnitsQuantity.ToCString(), myModelUnits.ToCString());
156   myValue = UnitsAPI::CurrentFromLS (myValue, myUnitsQuantity.ToCString());
157   myValue = valueToDisplayUnits();
158 }
159
160 //=======================================================================
161 //function : countDefaultPlane
162 //purpose  : 
163 //=======================================================================
164
165 void AIS_Dimension::countDefaultPlane()
166 {
167 }
168
169 //=======================================================================
170 //function : GetWorkingPlane
171 //purpose  : 
172 //=======================================================================
173
174 const gp_Pln& AIS_Dimension::GetWorkingPlane() const
175 {
176   return myWorkingPlane;
177 }
178
179 //=======================================================================
180 //function : SetWorkingPlane
181 //purpose  : 
182 //=======================================================================
183
184 void AIS_Dimension::SetWorkingPlane (const gp_Pln& thePlane)
185 {
186   myWorkingPlane = thePlane;
187   myIsWorkingPlaneCustom = Standard_True;
188 }
189
190 //=======================================================================
191 //function : ResetWorkingPlane
192 //purpose  : Set default value of working plane
193 //=======================================================================
194
195 void AIS_Dimension::ResetWorkingPlane()
196 {
197   myWorkingPlane = myDefaultPlane;
198   myIsWorkingPlaneCustom = Standard_False;
199 }
200
201 //=======================================================================
202 //function : resetWorkingPlane
203 //purpose  : Set default value of working plane
204 //           Only for internal use.
205 //=======================================================================
206
207 void AIS_Dimension::resetWorkingPlane (const gp_Pln& theNewDefaultPlane)
208 {
209   myDefaultPlane = theNewDefaultPlane;
210   ResetWorkingPlane();
211 }
212
213 //=======================================================================
214 //function : valueInDisplayUnits
215 //purpose  :
216 //=======================================================================
217
218 Standard_Real AIS_Dimension::valueToDisplayUnits()
219 {
220   return  UnitsAPI::AnyToAny (myValue,
221                               myModelUnits.ToCString(),
222                               myDisplayUnits.ToCString());
223 }
224
225 //=======================================================================
226 //function : KindOfDimension
227 //purpose  : 
228 //=======================================================================
229
230 AIS_KindOfDimension AIS_Dimension::KindOfDimension() const 
231 {
232   return myKindOfDimension;
233 }
234
235 //=======================================================================
236 //function : SetKindOfDimension
237 //purpose  : 
238 //=======================================================================
239
240 void AIS_Dimension::SetKindOfDimension (const AIS_KindOfDimension theKindOfDimension)
241 {
242   myKindOfDimension = theKindOfDimension;
243 }
244
245 //=======================================================================
246 //function : SetExtensionSize
247 //purpose  : 
248 //=======================================================================
249
250 void AIS_Dimension::SetExtensionSize (const Standard_Real theExtensionSize)
251 {
252   myExtensionSize = theExtensionSize;
253 }
254    
255 //=======================================================================
256 //function : GetExtensionSize
257 //purpose  : 
258 //=======================================================================
259
260 Standard_Real AIS_Dimension::GetExtensionSize() const
261 {
262   return myExtensionSize;
263 }
264
265 //=======================================================================
266 //function : GetValue
267 //purpose  : 
268 //=======================================================================
269
270 Standard_Real AIS_Dimension::GetValue() const
271  {
272   return myValue;
273  }
274
275 //=======================================================================
276 //function : SetCustomValue
277 //purpose  : 
278 //=======================================================================
279
280 void AIS_Dimension::SetCustomValue (const Standard_Real theValue)
281 {
282   myValue = theValue;
283   myIsValueCustom = Standard_True;
284 }
285
286 //=======================================================================
287 //function : SetFirstShape
288 //purpose  : 
289 //=======================================================================
290
291 void AIS_Dimension::SetFirstShape (const TopoDS_Shape& theShape)
292 {
293   myFirstShape = theShape;
294   myIsInitialized = Standard_False;
295   resetGeom();
296 }
297
298 //=======================================================================
299 //function : SetSecondShape
300 //purpose  : 
301 //=======================================================================
302
303 void AIS_Dimension::SetSecondShape (const TopoDS_Shape& theShape)
304 {
305   mySecondShape = theShape;
306   myIsInitialized = Standard_False;
307   resetGeom();
308 }
309
310 //=======================================================================
311 //function : getTextWidthAndString
312 //purpose  : 
313 //=======================================================================
314
315 void AIS_Dimension::getTextWidthAndString (Quantity_Length& theWidth,
316                                            TCollection_ExtendedString& theString) const
317 {
318   char aValueSimpleStr[25];
319   sprintf (aValueSimpleStr, "%g", GetValue());
320   theString = TCollection_ExtendedString (aValueSimpleStr);
321
322   if (IsUnitsDisplayed())
323   {
324     theString += " ";
325     theString += TCollection_ExtendedString (myDisplayUnits);
326   }
327
328   if (myDisplaySpecialSymbol == AIS_DSS_Before)
329   {
330     theString = TCollection_ExtendedString (mySpecialSymbol) + theString;
331   }
332   else if (myDisplaySpecialSymbol == AIS_DSS_After)
333   {
334     theString += TCollection_ExtendedString (mySpecialSymbol);
335   }
336
337   // Get font length
338   // Get expansion ratio for getting a width of symbols
339   Quantity_Color aColor; 
340   Standard_CString aFont;
341   Standard_Real aFactor;
342   Standard_Real aSpace;
343   myDrawer->DimensionAspect()->TextAspect()->Aspect()->Values (aColor, aFont, aFactor, aSpace);
344   theWidth = (myDrawer->DimensionAspect()->TextAspect()->Height() / aFactor) * theString.Length();
345 }
346
347 //=======================================================================
348 //function : drawArrow
349 //purpose  : 
350 //=======================================================================
351
352 void AIS_Dimension::drawArrow (const Handle(Prs3d_Presentation)& thePresentation,
353                                const gp_Pnt& theLocation,
354                                const gp_Dir& theDirection)
355 {
356   Prs3d_Root::NewGroup (thePresentation);
357   Quantity_Length anArrowLength = myDrawer->DimensionAspect()->ArrowAspect()->Length();
358
359   if (myDrawer->DimensionAspect()->IsArrows3d())
360   {
361     Prs3d_Arrow::Draw (thePresentation,
362                        theLocation,
363                        theDirection.Reversed(),
364                        myDrawer->DimensionAspect()->ArrowAspect()->Angle(),
365                        anArrowLength);
366   }
367   else
368   {
369     gp_Vec anArrowDir (theDirection);
370     Quantity_Length theCathetusLength = anArrowLength / Cos (M_PI / 9.0);
371     Handle(Graphic3d_ArrayOfTriangles) anArrow = new Graphic3d_ArrayOfTriangles(3);
372     gp_Pnt aLeftPoint (theLocation.Translated (anArrowDir.Rotated (myWorkingPlane.Axis(), M_PI / 9.0) * theCathetusLength));
373     gp_Pnt aRightPoint (theLocation.Translated (anArrowDir.Rotated (myWorkingPlane.Axis(), M_PI * 17.0 / 9.0) * theCathetusLength));
374
375     anArrow->AddVertex (aLeftPoint);
376     anArrow->AddVertex (theLocation);
377     anArrow->AddVertex (aRightPoint);
378
379     // Set aspect for arrow triangles
380     Quantity_Color aColor;
381     Aspect_TypeOfLine aTOL;
382     Standard_Real aWidth;
383     myDrawer->DimensionAspect()->ArrowAspect()->Aspect()->Values (aColor, aTOL, aWidth);
384     Graphic3d_MaterialAspect aShadeMat (Graphic3d_NOM_DEFAULT);
385     aShadeMat.SetReflectionModeOff (Graphic3d_TOR_AMBIENT);
386     aShadeMat.SetReflectionModeOff (Graphic3d_TOR_DIFFUSE);
387     aShadeMat.SetReflectionModeOff (Graphic3d_TOR_SPECULAR);
388     myDrawer->ShadingAspect()->Aspect()->SetInteriorColor (aColor);
389     myDrawer->ShadingAspect()->Aspect()->SetBackInteriorColor (aColor);
390     myDrawer->ShadingAspect()->SetMaterial (aShadeMat);
391     Prs3d_Root::CurrentGroup(thePresentation)->SetGroupPrimitivesAspect (myDrawer->ShadingAspect()->Aspect());
392     Prs3d_Root::CurrentGroup(thePresentation)->AddPrimitiveArray (anArrow);
393   }
394 }
395
396 //=======================================================================
397 //function : drawText
398 //purpose  : 
399 //=======================================================================
400
401 Standard_Real AIS_Dimension::drawText (const Handle(Prs3d_Presentation)& thePresentation,
402                                        const gp_Dir& theTextDir,
403                                        const TCollection_ExtendedString theText,
404                                        const AIS_DimensionDisplayMode theMode)
405 {
406   Standard_Real aTextWidth (0.0), aTextHeight (0.0);
407   if (theMode == AIS_DDM_Line)
408     return aTextWidth;
409   // Creating new group for text
410   Prs3d_Root::NewGroup (thePresentation);
411
412   if (myDrawer->DimensionAspect()->IsText3d())
413   {
414     // Getting font parameters
415     Quantity_Color aColor;
416     Standard_CString aFontName;
417     Standard_Real anExpansionFactor;
418     Standard_Real aSpace;
419     myDrawer->DimensionAspect()->TextAspect()->Aspect()->Values (aColor, aFontName, anExpansionFactor, aSpace);
420     Font_FontAspect aFontAspect = myDrawer->DimensionAspect()->TextAspect()->Aspect()->GetTextFontAspect();
421     Standard_Real aHeight = myDrawer->DimensionAspect()->TextAspect()->Height();
422
423     // Creating TopoDS_Shape for text
424     Font_BRepFont aFont (aFontName, aFontAspect, aHeight);
425     NCollection_String aText = (Standard_Utf16Char* )theText.ToExtString();
426     TopoDS_Shape aTextShape = aFont.RenderText (aText);
427
428     // Formating text position in XOY plane
429     Bnd_Box aTextBndBox;
430     BRepBndLib::AddClose (aTextShape, aTextBndBox);
431     Standard_Real aXMin, anYMin, aZMin, aXMax, anYMax, aZMax;
432     aTextBndBox.Get (aXMin, anYMin, aZMin, aXMax, anYMax, aZMax);
433     aTextWidth  = aXMax  - aXMin;
434     aTextHeight = anYMax - anYMin;
435     gp_Dir aTextDir (theTextDir);
436     Standard_Real aHorizontalOffset (0.0), aVerticalOffset (0.0);
437     switch (myDrawer->DimensionAspect()->HorizontalTextAlignment())
438     {
439       case Prs3d_HTA_Left:
440         aTextDir.Reverse();
441         aHorizontalOffset = -aTextWidth;
442         break;
443       case Prs3d_HTA_Center:
444         aHorizontalOffset = -(aTextWidth / 2.0);
445         break;
446       case Prs3d_HTA_Right:
447         aHorizontalOffset = 0.0;
448         break;
449     }
450     switch (myDrawer->DimensionAspect()->VerticalTextAlignment())
451     {
452       case Prs3d_VTA_Top:
453         aVerticalOffset = 0.0;
454         break;
455       case Prs3d_VTA_Center:
456         aVerticalOffset = -(aTextHeight / 2.0);
457         break;
458       case Prs3d_VTA_Bottom:
459         aVerticalOffset = -aTextHeight;
460         break;
461     }
462     gp_Trsf aTrsf;
463     aTrsf.SetTranslation (gp_Pnt (), gp_Pnt (aHorizontalOffset, aVerticalOffset, 0.0));
464     aTextShape.Move (aTrsf);
465
466     // Transform text to myWorkingPlane coordinate system
467     gp_Ax3 aPenAx3 (myGeom.myTextPosition, myWorkingPlane.Axis().Direction(), aTextDir);
468     aTrsf.SetTransformation (aPenAx3, gp_Ax3 (gp::XOY()));
469     aTextShape.Move (aTrsf);
470
471     // Set display parameters for advanced selection
472     BRepBndLib::AddClose (aTextShape, myGeom.myTextBndBox);
473     // Drawing text
474     if (myDrawer->DimensionAspect()->IsTextShaded())
475     {
476       // Setting text shading and color parameters
477       Graphic3d_MaterialAspect aShadeMat (Graphic3d_NOM_DEFAULT);
478       aShadeMat.SetReflectionModeOff (Graphic3d_TOR_AMBIENT);
479       aShadeMat.SetReflectionModeOff (Graphic3d_TOR_DIFFUSE);
480       aShadeMat.SetReflectionModeOff (Graphic3d_TOR_SPECULAR);
481       myDrawer->ShadingAspect()->Aspect()->SetInteriorColor (aColor);
482       myDrawer->ShadingAspect()->Aspect()->SetBackInteriorColor (aColor);
483       myDrawer->ShadingAspect()->SetMaterial (aShadeMat);
484
485       // Drawing text
486       StdPrs_ShadedShape::Add (thePresentation, aTextShape, myDrawer);
487     }
488     else
489     {
490       // Setting color for text
491       myDrawer->FreeBoundaryAspect()->Aspect()->SetColor (aColor);
492       // Drawing text
493       StdPrs_WFShape::Add (thePresentation, aTextShape, myDrawer);
494     }
495     // Creating new group for lines
496     Prs3d_Root::NewGroup (thePresentation);
497   }
498   else
499   {
500     myDrawer->DimensionAspect()->TextAspect()->Aspect()->SetDisplayType (Aspect_TODT_DIMENSION);
501     Prs3d_Text::Draw (thePresentation,
502                       myDrawer->DimensionAspect()->TextAspect(),
503                       theText,
504                       myGeom.myTextPosition);
505
506     // For 2d text we don not create new group for lines and draw them in the same group with text
507     // for the proper handling of stencil test buffer.
508   }
509
510   return aTextWidth;
511 }
512
513   //=======================================================================
514 //function : drawExtensionWithText
515 //purpose  : 
516 //=======================================================================
517
518 void AIS_Dimension::drawExtensionWithText (const Handle(Prs3d_Presentation)& thePresentation,
519                                            const gp_Pnt& theStartPoint,
520                                            const gp_Lin& theDimensionLine,
521                                            const TCollection_ExtendedString& theValueString,
522                                            const AIS_DimensionDisplayMode theMode)
523 {
524   Handle(SelectMgr_EntityOwner) anEmptyOwner;
525   Standard_Boolean isGapInCenter = (myDrawer->DimensionAspect()->VerticalTextAlignment() == Prs3d_VTA_Center
526                                     && myDrawer->DimensionAspect()->IsText3d());
527
528   Handle(Graphic3d_ArrayOfSegments) aPrimSegments = new Graphic3d_ArrayOfSegments (isGapInCenter ? 4 : 2);
529
530   gp_Dir anAttachPointsVector = myWorkingPlane.Axis().Direction() ^ gce_MakeDir (myFirstPoint, mySecondPoint);
531   Standard_Real aGap = 1.;
532   Standard_Real aStartParam = ElCLib::Parameter (theDimensionLine, theStartPoint);
533
534   // Text
535   Standard_Real aTextParam = isGapInCenter ? aStartParam + myTextOffset + aGap : aStartParam + myTextOffset;
536   myGeom.myTextPosition = ElCLib::Value (aTextParam, theDimensionLine);
537   Standard_Real aTextWidth = drawText (thePresentation,
538                                        myIsTextReversed ? theDimensionLine.Direction().Reversed()
539                                                         : theDimensionLine.Direction(),
540                                        theValueString,
541                                        theMode);
542   gp_Pnt aFirstPoint, aLastPoint;
543   aFirstPoint = theStartPoint;
544   Standard_Real aParam = isGapInCenter ? aTextParam + aTextWidth + aGap : aTextParam + aTextWidth;
545
546   // If text separates dimension line into two parts (4 points)
547   if (isGapInCenter)
548   {
549     aLastPoint = ElCLib::Value (aStartParam + myTextOffset, theDimensionLine);
550     aPrimSegments->AddVertex (aFirstPoint);
551     aPrimSegments->AddVertex (aLastPoint);
552     myGeom.mySensitiveSegments.Append (new Select3D_SensitiveSegment (anEmptyOwner, aFirstPoint, aLastPoint));
553     aFirstPoint = ElCLib::Value (aParam, theDimensionLine);
554   }
555
556   // Draw additional line segment only after 3D text
557   if (myDrawer->DimensionAspect()->IsText3d())
558   {
559     aParam += myTextOffset;
560   }
561
562   aLastPoint = ElCLib::Value (aParam, theDimensionLine);
563   aPrimSegments->AddVertex (aFirstPoint);
564   aPrimSegments->AddVertex (aLastPoint);
565   myGeom.mySensitiveSegments.Append (new Select3D_SensitiveSegment (anEmptyOwner, aFirstPoint, aLastPoint));
566
567   // Extension line in the same group
568   if (theMode != AIS_DDM_Text)
569   {
570     if (!myDrawer->DimensionAspect()->IsText3d() && theMode == AIS_DDM_All)
571     {
572       Prs3d_Root::CurrentGroup (thePresentation)->SetStencilTestOptions (Standard_True);
573     }
574     Prs3d_Root::CurrentGroup (thePresentation)->SetPrimitivesAspect (myDrawer->DimensionAspect()->LineAspect()->Aspect());
575     Prs3d_Root::CurrentGroup (thePresentation)->AddPrimitiveArray (aPrimSegments);
576     if (!myDrawer->DimensionAspect()->IsText3d() && theMode == AIS_DDM_All)
577     {
578       Prs3d_Root::CurrentGroup (thePresentation)->SetStencilTestOptions (Standard_False);
579     }
580   }
581 }
582
583 //=======================================================================
584 //function : SetDimensionAspect
585 //purpose  : 
586 //=======================================================================
587
588 void AIS_Dimension::SetDimensionAspect (const Handle(Prs3d_DimensionAspect)& theDimensionAspect)
589 {
590   myDrawer->SetDimensionAspect (theDimensionAspect);
591 }
592
593 //=======================================================================
594 //function : DimensionAspect
595 //purpose  : 
596 //=======================================================================
597
598 Handle(Prs3d_DimensionAspect) AIS_Dimension::DimensionAspect() const
599 {
600   return myDrawer->DimensionAspect();
601 }
602
603 //=======================================================================
604 //function : SetTextOffset
605 //purpose  : 
606 //=======================================================================
607
608 void AIS_Dimension::SetTextOffset (const Standard_Real theOffset)
609 {
610   myTextOffset = theOffset;
611 }
612
613 //=======================================================================
614 //function : TextOffset
615 //purpose  : 
616 //=======================================================================
617
618 Standard_Real AIS_Dimension::TextOffset() const
619 {
620   return myTextOffset;
621 }
622
623 //=======================================================================
624 //function : drawLinearDimension
625 //purpose  : 
626 //=======================================================================
627
628 void AIS_Dimension::drawLinearDimension (const Handle(Prs3d_Presentation)& thePresentation,
629                                          const gp_Pnt& theFirstAttach,
630                                          const gp_Pnt& theSecondAttach,
631                                          const AIS_DimensionDisplayMode theMode,
632                                          const Standard_Boolean isOneSideDimension/* = Standard_False*/)
633 {
634   // Don't build any dimension for equal points
635   if (myFirstPoint.IsEqual (mySecondPoint, Precision::Confusion()))
636   {
637     setComputed (Standard_False);
638     return;
639   }
640   Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
641   Handle(SelectMgr_EntityOwner) anEmptyOwner;
642   myGeom.mySensitiveSegments.Clear();
643
644   gp_Dir aAttachPointsVector = GetWorkingPlane().Axis().Direction()^gce_MakeDir (myFirstPoint, mySecondPoint);
645   // Get line of the dimension
646   gp_Lin aDimensionLine = gce_MakeLin (theFirstAttach, theSecondAttach);
647
648   // Get parameters on dimension line of two layout points
649   Standard_Real aParam1 = ElCLib::Parameter (aDimensionLine, theFirstAttach);
650   Standard_Real aParam2 = ElCLib::Parameter (aDimensionLine, theSecondAttach);
651
652   // For extensions we need to know arrow size and text size, get it from aspect
653   Quantity_Length anArrowLength = aDimensionAspect->ArrowAspect()->Length();
654   // Set line parameters
655   Standard_Real aGap = 0.; // gap between line and text if AIS_VTA_Center
656   if (!myIsValueCustom)
657   {
658    computeValue();
659   }
660
661   TCollection_ExtendedString aValueString;
662   Standard_Real aTextLength;
663   getTextWidthAndString (aTextLength, aValueString);
664
665   // Automatical text and arrow placement
666   Standard_Real aValue = myFirstPoint.Distance (mySecondPoint);
667   if (aDimensionAspect->HorizontalTextAlignment() == Prs3d_HTA_Center)
668   {
669     aDimensionAspect->SetArrowOrientation (Prs3d_DAO_Internal);
670     if (aValue < aTextLength + (isOneSideDimension ? anArrowLength : 2.0 * anArrowLength))
671     {
672       aDimensionAspect->SetArrowOrientation (Prs3d_DAO_External);
673       aDimensionAspect->SetHorizontalTextAlignment (Prs3d_HTA_Left);
674     }
675   }
676   else
677   {
678     aDimensionAspect->SetArrowOrientation (Prs3d_DAO_External);
679   }
680
681   // Arrows positions and directions
682   gp_Pnt aFirstArrowPosition = ElCLib::Value (aParam1, aDimensionLine);
683   gp_Pnt aSecondArrowPosition = ElCLib::Value (aParam2, aDimensionLine);
684   gp_Dir aFirstArrowDir = aDimensionLine.Direction();
685   gp_Dir aSecondArrowDir = aDimensionLine.Direction().Reversed();
686   Standard_Real aFirstArrowBegin, aFirstArrowEnd, aSecondArrowBegin, aSecondArrowEnd;
687
688   if (aDimensionAspect->GetArrowOrientation() == Prs3d_DAO_External)
689   {
690     aFirstArrowDir.Reverse();
691     aSecondArrowDir.Reverse();
692
693     aFirstArrowBegin  = aParam1 - anArrowLength;
694     aFirstArrowEnd    = aParam1;
695     aSecondArrowBegin = aParam2;
696     aSecondArrowEnd   = aParam2 + anArrowLength;
697   }
698   else
699   {
700     aFirstArrowBegin  = aParam1;
701     aFirstArrowEnd    = aParam1 + anArrowLength;
702     aSecondArrowBegin = aParam2 - anArrowLength;
703     aSecondArrowEnd   = aParam2;
704   }
705
706   Handle(Graphic3d_ArrayOfSegments) aPrimSegments;
707   gp_Pnt aFirstPoint, aLastPoint;
708   // Take into account vertical text alignment:
709   // only for 3D text! subtract the text length if it is in the center.
710   Standard_Boolean isGapInCenter = (aDimensionAspect->VerticalTextAlignment() == Prs3d_VTA_Center
711                                      && aDimensionAspect->IsText3d());
712   if (isGapInCenter)
713   {
714     aGap = 1.0;
715   }
716
717   switch (aDimensionAspect->HorizontalTextAlignment())
718   {
719     // Default case - text is to be in the center of length dimension line
720     case Prs3d_HTA_Center:
721     {
722       // Group1: arrows
723       if (theMode != AIS_DDM_Text)
724       {
725         drawArrow (thePresentation, aFirstArrowPosition, aFirstArrowDir);
726         if (!isOneSideDimension)
727         {
728           drawArrow (thePresentation, aSecondArrowPosition, aSecondArrowDir);
729         }
730       }
731
732       // Group 2: Text and dimension line
733       aPrimSegments = new Graphic3d_ArrayOfSegments (isGapInCenter ? 4 : 2);
734       myGeom.myTextPosition = ElCLib::Value ((aParam1 + aParam2) / 2.0, aDimensionLine);
735
736       gp_Vec aTextDir (myFirstPoint, mySecondPoint);
737       Standard_Real aTextWidth = drawText (thePresentation,
738                                            myIsTextReversed ? aTextDir.Reversed() : aTextDir,
739                                            aValueString,
740                                            theMode);
741
742       aFirstPoint = ElCLib::Value (aFirstArrowEnd, aDimensionLine);
743       if (isGapInCenter)
744       {
745         aLastPoint = ElCLib::Value (ElCLib::Parameter (aDimensionLine,myGeom.myTextPosition) - aGap - (aTextWidth / 2.0), aDimensionLine);
746         aPrimSegments->AddVertex (aFirstPoint);
747         aPrimSegments->AddVertex (aLastPoint);
748         myGeom.mySensitiveSegments.Append (new Select3D_SensitiveSegment (anEmptyOwner,aFirstPoint,aLastPoint));
749         aFirstPoint = ElCLib::Value (ElCLib::Parameter(aDimensionLine,myGeom.myTextPosition) + (aTextWidth / 2.0) + aGap, aDimensionLine);
750       }
751       else if (aDimensionAspect->VerticalTextAlignment() == Prs3d_VTA_Top)
752       {
753         aDimensionAspect->TextAspect()->SetVerticalJustification (Graphic3d_VTA_BOTTOM);
754       }
755       else if (aDimensionAspect->VerticalTextAlignment() == Prs3d_VTA_Bottom)
756       {
757         aDimensionAspect->TextAspect()->SetVerticalJustification(Graphic3d_VTA_TOP);
758       }
759
760       aLastPoint = isOneSideDimension ? theSecondAttach : ElCLib::Value (aSecondArrowBegin, aDimensionLine);
761
762       aPrimSegments->AddVertex (aFirstPoint);
763       aPrimSegments->AddVertex (aLastPoint);
764       myGeom.mySensitiveSegments.Append (new Select3D_SensitiveSegment (anEmptyOwner, aFirstPoint, aLastPoint));
765
766       // Main dimension line, short extension
767       if (theMode != AIS_DDM_Text)
768       {
769         if (!aDimensionAspect->IsText3d() && theMode == AIS_DDM_All)
770         {
771           Prs3d_Root::CurrentGroup (thePresentation)->SetStencilTestOptions (Standard_True);
772         }
773         Prs3d_Root::CurrentGroup (thePresentation)->SetPrimitivesAspect (aDimensionAspect->LineAspect()->Aspect());
774         Prs3d_Root::CurrentGroup (thePresentation)->AddPrimitiveArray (aPrimSegments);
775         if (!aDimensionAspect->IsText3d() && theMode == AIS_DDM_All)
776         {
777           Prs3d_Root::CurrentGroup (thePresentation)->SetStencilTestOptions (Standard_False);
778         }
779       }
780       break;
781     }
782     // Text is disposed from the left side of length dimension (after the left flyout line)
783     // Needs to create extensions: left for text and right for proper view of dimensions.
784     case Prs3d_HTA_Left:
785     {
786       aPrimSegments = new Graphic3d_ArrayOfSegments (4);
787
788       gp_Pnt aFirstArrowBeginPnt = ElCLib::Value (aFirstArrowBegin, aDimensionLine);
789       gp_Lin aLongExtLine (aDimensionLine.Location(), aDimensionLine.Direction().Reversed());
790       gp_Pnt aStartPoint = ElCLib::Value (aFirstArrowBegin, aDimensionLine);
791       // Left extension with the text
792       drawExtensionWithText (thePresentation, aStartPoint, aLongExtLine, aValueString, theMode);
793
794       // Central(main) dimension line
795       aFirstPoint = ElCLib::Value (aFirstArrowEnd, aDimensionLine);
796       aLastPoint = isOneSideDimension ? theSecondAttach : ElCLib::Value (aSecondArrowBegin, aDimensionLine);
797       aPrimSegments->AddVertex (aFirstPoint);
798       aPrimSegments->AddVertex (aLastPoint);
799       myGeom.mySensitiveSegments.Append (new Select3D_SensitiveSegment (anEmptyOwner, aFirstPoint, aLastPoint));
800
801       // Right extension
802       if (!isOneSideDimension)
803       {
804         aFirstPoint = ElCLib::Value (aSecondArrowEnd, aDimensionLine);
805         aLastPoint = ElCLib::Value (aSecondArrowEnd + anArrowLength, aDimensionLine);
806         aPrimSegments->AddVertex (aFirstPoint);
807         aPrimSegments->AddVertex (aLastPoint);
808         myGeom.mySensitiveSegments.Append(new Select3D_SensitiveSegment (anEmptyOwner, aFirstPoint, aLastPoint));
809       }
810       if (theMode != AIS_DDM_Text)
811       {
812         // Main dimension line, short extension
813         Prs3d_Root::NewGroup (thePresentation)->SetPrimitivesAspect (aDimensionAspect->LineAspect()->Aspect());
814         Prs3d_Root::CurrentGroup (thePresentation)->AddPrimitiveArray (aPrimSegments);
815         // Group1: Add arrows to a group
816         drawArrow (thePresentation, aFirstArrowPosition, aFirstArrowDir);
817         if (!isOneSideDimension)
818         {
819           drawArrow (thePresentation, aSecondArrowPosition, aSecondArrowDir);
820         }
821       }
822       break;
823     }
824     case Prs3d_HTA_Right:
825     {
826       aPrimSegments = new Graphic3d_ArrayOfSegments (4);
827       // Left extension
828       if (!isOneSideDimension)
829       {
830         aFirstPoint = ElCLib::Value (aFirstArrowBegin - anArrowLength, aDimensionLine);
831         aLastPoint = ElCLib::Value (aFirstArrowEnd, aDimensionLine);
832         aPrimSegments->AddVertex (aFirstPoint);
833         aPrimSegments->AddVertex (aLastPoint);
834         myGeom.mySensitiveSegments.Append (new Select3D_SensitiveSegment (anEmptyOwner, aFirstPoint, aLastPoint));
835       }
836
837       // Central(main) dimension line
838       aFirstPoint = isOneSideDimension ? theFirstAttach :  ElCLib::Value (aFirstArrowEnd, aDimensionLine);
839       aLastPoint = ElCLib::Value (aSecondArrowBegin, aDimensionLine);
840       aPrimSegments->AddVertex (aFirstPoint);
841       aPrimSegments->AddVertex (aLastPoint);
842       myGeom.mySensitiveSegments.Append (new Select3D_SensitiveSegment (anEmptyOwner, aFirstPoint, aLastPoint));
843
844       // Right extension with text
845       aFirstPoint = ElCLib::Value (aSecondArrowEnd, aDimensionLine);
846       drawExtensionWithText (thePresentation, aFirstPoint, aDimensionLine, aValueString, theMode);
847
848       if (theMode != AIS_DDM_Text)
849       {
850         // Main dimension line, short extension
851         Prs3d_Root::NewGroup(thePresentation)->SetPrimitivesAspect (aDimensionAspect->LineAspect()->Aspect());
852         Prs3d_Root::CurrentGroup(thePresentation)->AddPrimitiveArray (aPrimSegments);
853         // Group1, 2: Add arrows to a group
854         if (!isOneSideDimension)
855         {
856           drawArrow (thePresentation, aFirstArrowPosition, aFirstArrowDir);
857         }
858
859         drawArrow (thePresentation, aSecondArrowPosition, aSecondArrowDir);
860       }
861       break;
862     }
863   }
864
865   setComputed (Standard_True);
866 }
867
868 //=======================================================================
869 //function : SetFirstPoint
870 //purpose  : 
871 //=======================================================================
872
873 void AIS_Dimension::SetFirstPoint (const gp_Pnt& thePoint)
874 {
875   myFirstPoint = thePoint;
876 }
877
878 //=======================================================================
879 //function : SetSecondPoint
880 //purpose  : 
881 //=======================================================================
882
883 void AIS_Dimension::SetSecondPoint (const gp_Pnt& thePoint)
884 {
885   mySecondPoint = thePoint;
886 }
887
888 //=======================================================================
889 //function : Type
890 //purpose  :
891 //=======================================================================
892
893 AIS_KindOfInteractive AIS_Dimension::Type() const
894 {
895   return AIS_KOI_Relation;
896 }
897
898 //=======================================================================
899 //function : circleFromPlanarFace
900 //purpose  : if possible computes circle from planar face
901 //=======================================================================
902
903 Standard_Boolean AIS_Dimension::circleFromPlanarFace (const TopoDS_Face& theFace,
904                                                       Handle(Geom_Curve)& theCurve,
905                                                       gp_Pnt & theFirstPoint,
906                                                       gp_Pnt & theLastPoint)
907 {
908   TopExp_Explorer anIt (theFace, TopAbs_EDGE);
909   for ( ; anIt.More(); anIt.Next())
910   {
911     TopoDS_Edge aCurEdge =  TopoDS::Edge (anIt.Current());
912     if (AIS::ComputeGeometry (aCurEdge, theCurve, theFirstPoint, theLastPoint))
913     {
914       if (theCurve->IsInstance (STANDARD_TYPE(Geom_Circle)))
915       {
916         return Standard_True;
917       }
918     }
919   }
920   return Standard_False;
921 }
922
923 //=======================================================================
924 //function : initCircularDimension
925 //purpose  : if it's possible computes circle from planar face
926 //=======================================================================
927
928 Standard_Boolean AIS_Dimension::initCircularDimension (const TopoDS_Shape& theShape,
929                                                        gp_Circ& theCircle,
930                                                        gp_Pnt& theMiddleArcPoint,
931                                                        gp_Pnt& theOppositeDiameterPoint)
932 {
933   gp_Pln aPln;
934   Handle(Geom_Surface) aBasisSurf;
935   AIS_KindOfSurface aSurfType = AIS_KOS_OtherSurface;
936   gp_Pnt aFirstPoint, aLastPoint;
937   Standard_Real anOffset    = 0.0;
938   Standard_Real aFirstParam = 0.0;
939   Standard_Real aLastParam  = 0.0;
940   Standard_Boolean isAnArc  = Standard_False;
941
942   if (theShape.ShapeType() == TopAbs_FACE)
943   {
944     AIS::GetPlaneFromFace (TopoDS::Face (theShape), aPln, aBasisSurf, aSurfType, anOffset);
945
946     if (aSurfType == AIS_KOS_Plane)
947     {
948       Handle(Geom_Curve) aCurve;
949       if (!circleFromPlanarFace (TopoDS::Face (theShape), aCurve, aFirstPoint, aLastPoint))
950       {
951         Standard_ConstructionError::Raise ("AIS_Dimension:: Curve is not a circle or is Null") ;
952         return Standard_False;
953       }
954
955       theCircle = Handle(Geom_Circle)::DownCast (aCurve)->Circ();
956       isAnArc = !(aFirstPoint.IsEqual (aLastPoint, Precision::Confusion()));
957     }
958     else
959     {
960       gp_Pnt aCurPos;
961       BRepAdaptor_Surface aSurf1 (TopoDS::Face (theShape));
962       Standard_Real aFirstU = aSurf1.FirstUParameter();
963       Standard_Real aLastU  = aSurf1.LastUParameter();
964       Standard_Real aFirstV = aSurf1.FirstVParameter();
965       Standard_Real aLastV  = aSurf1.LastVParameter();
966       Standard_Real aMidU   = (aFirstU + aLastU) * 0.5;
967       Standard_Real aMidV   = (aFirstV + aLastV) * 0.5;
968       aSurf1.D0(aMidU, aMidV, aCurPos);
969       Handle (Adaptor3d_HCurve) aBasisCurve;
970       Standard_Boolean isExpectedType = Standard_False;
971       if (aSurfType == AIS_KOS_Cylinder)
972       {
973         isExpectedType = Standard_True;
974       }
975       else
976       {
977         if (aSurfType == AIS_KOS_Revolution)
978         {
979           aBasisCurve = aSurf1.BasisCurve();
980           if (aBasisCurve->GetType() == GeomAbs_Line)
981           {
982             isExpectedType = Standard_True;
983           }
984         }
985         else if (aSurfType == AIS_KOS_Extrusion)
986         {
987           aBasisCurve = aSurf1.BasisCurve();
988           if (aBasisCurve->GetType() == GeomAbs_Circle)
989           {
990             isExpectedType = Standard_True;
991           }
992         }
993       }
994
995       if (!isExpectedType)
996       {
997         Standard_ConstructionError::Raise ("AIS_Dimension:: Unexpected type of surface") ;
998         return Standard_False;
999       }
1000       Handle(Geom_Curve) aCurve;
1001       aCurve = aBasisSurf->VIso(aMidV);
1002       if (aCurve->DynamicType() == STANDARD_TYPE (Geom_Circle))
1003       {
1004         theCircle = Handle(Geom_Circle)::DownCast (aCurve)->Circ();
1005       }
1006       else if (aCurve->DynamicType() == STANDARD_TYPE (Geom_TrimmedCurve))
1007       {
1008         Handle(Geom_TrimmedCurve) aTrimmedCurve = Handle(Geom_TrimmedCurve)::DownCast (aCurve);
1009         aFirstU = aTrimmedCurve->FirstParameter();
1010         aLastU  = aTrimmedCurve->LastParameter();
1011         if (aTrimmedCurve->DynamicType() == STANDARD_TYPE (Geom_Circle))
1012         {
1013           theCircle = Handle(Geom_Circle)::DownCast(aTrimmedCurve)->Circ();
1014         }
1015       }
1016       else
1017       {
1018         // Compute a circle from 3 points on "aCurve"
1019         gp_Pnt aP1, aP2;
1020         aSurf1.D0 (aFirstU, aMidV, aP1);
1021         aSurf1.D0 (aLastU, aMidV, aP2);
1022         GC_MakeCircle aMkCirc (aP1, aCurPos, aP2);
1023         theCircle = aMkCirc.Value()->Circ();
1024       }
1025
1026       gp_Vec aVec = gp_Vec (theCircle.Location(), aCurPos).Normalized();
1027       aFirstPoint = ElCLib::Value (aFirstU, theCircle);
1028       aLastPoint = ElCLib::Value (aLastU,  theCircle);
1029     }
1030   }
1031   else // TopAbs_EDGE | TopAbs_WIRE
1032   {
1033     TopoDS_Edge anEdge;
1034     if (theShape.ShapeType() == TopAbs_WIRE)
1035     {
1036       TopExp_Explorer anIt (theShape, TopAbs_EDGE);
1037       if (anIt.More())
1038       {
1039         anEdge = TopoDS::Edge (anIt.Current());
1040       }
1041     }
1042     else if (theShape.ShapeType() == TopAbs_EDGE)
1043     {
1044       anEdge = TopoDS::Edge (theShape);
1045     }
1046     else // Unexpected type of shape
1047     {
1048       Standard_ConstructionError::Raise ("AIS_Dimension:: Unexpected type of shape");
1049       return Standard_False;
1050     }
1051     BRepAdaptor_Curve anAdaptedCurve (anEdge);
1052     if (!anAdaptedCurve.GetType() == GeomAbs_Circle)
1053     {
1054       return Standard_False;
1055     }
1056     theCircle = anAdaptedCurve.Circle();
1057     aFirstPoint = anAdaptedCurve.Value (anAdaptedCurve.FirstParameter());
1058     aLastPoint = anAdaptedCurve.Value (anAdaptedCurve.LastParameter());
1059   }
1060   // Get <theMiddleArcPoint> and <theOppositeDiameterPoint> values from <theCircle>
1061   isAnArc = !(aFirstPoint.IsEqual (aLastPoint, Precision::Confusion()));
1062   gp_Pnt aCenter = theCircle.Location();
1063   if (!isAnArc)
1064   {
1065     // Circle
1066     gp_Dir anXDir = theCircle.XAxis().Direction();
1067     theMiddleArcPoint = aCenter.Translated (gp_Vec (anXDir) * theCircle.Radius());
1068     theOppositeDiameterPoint = aCenter.Translated (-gp_Vec (anXDir) * theCircle.Radius());
1069   }
1070   else
1071   {
1072     // Arc
1073     aFirstParam = ElCLib::Parameter (theCircle, aFirstPoint);
1074     aLastParam  = ElCLib::Parameter (theCircle, aLastPoint);
1075     if (aFirstParam > aLastParam)
1076     {
1077       aFirstParam -= 2.0 * M_PI;
1078     }
1079     Standard_Real aParCurPos = (aFirstParam + aLastParam) * 0.5;
1080     gp_Vec aVec = gp_Vec (aCenter, ElCLib::Value (aParCurPos, theCircle)).Normalized () * theCircle.Radius ();
1081     theMiddleArcPoint = aCenter.Translated (aVec);
1082     theOppositeDiameterPoint = aCenter.Translated (-aVec);
1083   }
1084
1085   return Standard_True;
1086 }
1087
1088 //=======================================================================
1089 //function : SetDisplaySpecialSymbol
1090 //purpose  : specifies dimension special symbol display options
1091 //=======================================================================
1092
1093 void AIS_Dimension::SetDisplaySpecialSymbol (const AIS_DisplaySpecialSymbol theDisplaySpecSymbol)
1094 {
1095   myDisplaySpecialSymbol = theDisplaySpecSymbol;
1096 }
1097
1098 //=======================================================================
1099 //function : DisplaySpecialSymbol
1100 //purpose  : shows dimension special symbol display options
1101 //=======================================================================
1102
1103 AIS_DisplaySpecialSymbol AIS_Dimension::DisplaySpecialSymbol() const
1104 {
1105   return myDisplaySpecialSymbol;
1106 }
1107
1108 //=======================================================================
1109 //function : SetSpecialSymbol
1110 //purpose  : specifies special symbol
1111 //=======================================================================
1112
1113 void AIS_Dimension::SetSpecialSymbol (const Standard_ExtCharacter theSpecialSymbol)
1114 {
1115   mySpecialSymbol = theSpecialSymbol;
1116 }
1117
1118 //=======================================================================
1119 //function : SpecialSymbol
1120 //purpose  : returns special symbol
1121 //=======================================================================
1122
1123 Standard_ExtCharacter AIS_Dimension::SpecialSymbol() const
1124 {
1125   return mySpecialSymbol;
1126 }
1127
1128 //=======================================================================
1129 //function : IsUnitsDisplayed
1130 //purpose  : shows if Units are to be displayed along with dimension value
1131 //=======================================================================
1132
1133 Standard_Boolean AIS_Dimension::IsUnitsDisplayed() const
1134 {
1135   return myToDisplayUnits;
1136 }
1137
1138 //=======================================================================
1139 //function : MakeUnitsDisplayed
1140 //purpose  : sets to display units along with the dimension value or no
1141 //=======================================================================
1142
1143 void AIS_Dimension::MakeUnitsDisplayed (const Standard_Boolean toDisplayUnits)
1144 {
1145   myToDisplayUnits = toDisplayUnits;
1146 }
1147
1148 //=======================================================================
1149 //function : MakeUnitsDisplayed
1150 //purpose  : returns the current type of units
1151 //=======================================================================
1152
1153 TCollection_AsciiString AIS_Dimension::UnitsQuantity() const
1154 {
1155   return myUnitsQuantity;
1156 }
1157
1158 //=======================================================================
1159 //function : SetUnitsQuantity
1160 //purpose  : sets the current type of units
1161 //=======================================================================
1162
1163 void AIS_Dimension::SetUnitsQuantity (const TCollection_AsciiString& theUnitsQuantity)
1164 {
1165   myUnitsQuantity = theUnitsQuantity;
1166 }
1167
1168 //=======================================================================
1169 //function : ModelUnits
1170 //purpose  : returns the current model units
1171 //=======================================================================
1172
1173 TCollection_AsciiString AIS_Dimension::ModelUnits() const
1174 {
1175   return myModelUnits;
1176 }
1177
1178 //=======================================================================
1179 //function : SetModelUnits
1180 //purpose  : sets the current model units
1181 //=======================================================================
1182
1183 void AIS_Dimension::SetModelUnits (const TCollection_AsciiString& theUnits)
1184 {
1185   myModelUnits = theUnits;
1186 }
1187
1188 //=======================================================================
1189 //function : DisplayUnits
1190 //purpose  : returns the current display units
1191 //=======================================================================
1192
1193 TCollection_AsciiString AIS_Dimension::DisplayUnits() const
1194 {
1195   return myDisplayUnits;
1196 }
1197
1198 //=======================================================================
1199 //function : SetDisplayUnits
1200 //purpose  : sets the current display units
1201 //=======================================================================
1202
1203 void AIS_Dimension::SetDisplayUnits (const TCollection_AsciiString& theUnits)
1204 {
1205   myDisplayUnits = theUnits;
1206 }
1207
1208 //=======================================================================
1209 //function : isComputed
1210 //purpose  :
1211 //=======================================================================
1212
1213 Standard_Boolean AIS_Dimension::isComputed() const
1214 {
1215   return myGeom.myIsComputed;
1216 }
1217
1218 //=======================================================================
1219 //function : setComputed
1220 //purpose  :
1221 //=======================================================================
1222
1223 void AIS_Dimension::setComputed (Standard_Boolean isComputed)
1224 {
1225   myGeom.myIsComputed = isComputed;
1226 }
1227
1228 //=======================================================================
1229 //function : textPosition
1230 //purpose  :
1231 //=======================================================================
1232
1233 gp_Pnt AIS_Dimension::textPosition() const
1234 {
1235   return myGeom.myTextPosition;
1236 }
1237
1238 //=======================================================================
1239 //function : setTextPosition
1240 //purpose  :
1241 //=======================================================================
1242
1243 void AIS_Dimension::setTextPosition (const gp_Pnt thePosition)
1244 {
1245   myGeom.myTextPosition = thePosition;
1246 }
1247
1248 //=======================================================================
1249 //function : resetGeom
1250 //purpose  :
1251 //=======================================================================
1252
1253 void AIS_Dimension::resetGeom()
1254 {
1255   setComputed (Standard_False);
1256 }
1257
1258 //=======================================================================
1259 //function : IsTextReversed
1260 //purpose  :
1261 //=======================================================================
1262
1263 Standard_Boolean AIS_Dimension::IsTextReversed() const
1264 {
1265   return myIsTextReversed;
1266 }
1267
1268 //=======================================================================
1269 //function : MakeTextReversed
1270 //purpose  :
1271 //=======================================================================
1272
1273 void AIS_Dimension::MakeTextReversed (const Standard_Boolean isTextReversed)
1274 {
1275   myIsTextReversed = isTextReversed;
1276 }
1277
1278 //=======================================================================
1279 //function : SetSelToleranceForText2d
1280 //purpose  :
1281 //=======================================================================
1282
1283 void AIS_Dimension::SetSelToleranceForText2d (const Standard_Real theTol)
1284 {
1285   myGeom.mySelToleranceForText2d = theTol;
1286 }
1287
1288 //=======================================================================
1289 //function : SelToleranceForText2d
1290 //purpose  :
1291 //=======================================================================
1292
1293 Standard_Real AIS_Dimension::SelToleranceForText2d() const
1294 {
1295   return myGeom.mySelToleranceForText2d;
1296 }
1297
1298 //=======================================================================
1299 //function : SetFlyout
1300 //purpose  : 
1301 //=======================================================================
1302
1303 void AIS_Dimension::SetFlyout (const Standard_Real theFlyout)
1304 {
1305  myFlyout = theFlyout;
1306 }
1307
1308 //=======================================================================
1309 //function : GetFlyout
1310 //purpose  : 
1311 //=======================================================================
1312
1313 Standard_Real AIS_Dimension::GetFlyout () const
1314 {
1315  return myFlyout;
1316 }
1317
1318 //=======================================================================
1319 //function : computeFlyoutSelection
1320 //purpose  : computes selection for flyouts
1321 //=======================================================================
1322
1323 void AIS_Dimension::computeFlyoutSelection (const Handle(SelectMgr_Selection)& theSelection,
1324                                            const Handle(AIS_DimensionOwner)& theOwner)
1325 {
1326  //Count flyout direction
1327  gp_Ax1 aWorkingPlaneNormal = GetWorkingPlane().Axis();
1328  gp_Dir aTargetPointsVector = gce_MakeDir (myFirstPoint, mySecondPoint);
1329  // Count a flyout direction vector.
1330  gp_Dir aFlyoutVector = aWorkingPlaneNormal.Direction()^aTargetPointsVector;
1331  // Create lines for layouts
1332  gp_Lin aLine1 (myFirstPoint, aFlyoutVector);
1333  gp_Lin aLine2 (mySecondPoint, aFlyoutVector);
1334  // Get flyout end points
1335  gp_Pnt aFlyoutEnd1 = ElCLib::Value (ElCLib::Parameter (aLine1, myFirstPoint) + GetFlyout(), aLine1);
1336  gp_Pnt aFlyoutEnd2 = ElCLib::Value (ElCLib::Parameter (aLine2, mySecondPoint) + GetFlyout(), aLine2);
1337
1338  // Fill sensitive entity for flyouts
1339  Handle(Select3D_SensitiveGroup) aSensitiveEntity = new Select3D_SensitiveGroup (theOwner);
1340  aSensitiveEntity->Add (new Select3D_SensitiveSegment (theOwner, myFirstPoint, aFlyoutEnd1));
1341  aSensitiveEntity->Add (new Select3D_SensitiveSegment (theOwner, mySecondPoint, aFlyoutEnd2));
1342  theSelection->Add (aSensitiveEntity);
1343 }
1344
1345 //=======================================================================
1346 //function : ComputeSelection
1347 //purpose  : 
1348 //=======================================================================
1349
1350 void AIS_Dimension::ComputeSelection (const Handle(SelectMgr_Selection)& theSelection,
1351                                       const Standard_Integer theMode)
1352 {
1353   if (!isComputed())
1354   {
1355     return;
1356   }
1357
1358   Handle(Select3D_SensitiveGroup) aSensitiveForLine;
1359   Handle(Select3D_SensitiveEntity) aSensitiveForText;
1360   Select3D_ListOfSensitive aSensitiveList;
1361   aSensitiveList.Assign (myGeom.mySensitiveSegments);
1362
1363   // Full dimension selection
1364   Handle(AIS_DimensionOwner) anOwner = new AIS_DimensionOwner (this, AIS_DDM_All, theMode == 0 ? 5 : 6);
1365   for (Select3D_ListIteratorOfListOfSensitive anIt (aSensitiveList); anIt.More(); anIt.Next())
1366   {
1367     anIt.Value()->Set (anOwner);
1368   }
1369   aSensitiveForLine = new Select3D_SensitiveGroup (anOwner, aSensitiveList);
1370
1371   // Text
1372   if (myDrawer->DimensionAspect()->IsText3d())
1373   {
1374     aSensitiveForText = new Select3D_SensitiveBox (anOwner,myGeom.myTextBndBox);
1375   }
1376   else
1377   {
1378     Handle(Geom_Circle) aSensitiveGeom = new Geom_Circle (gp_Circ (gp_Ax2 (myGeom.myTextPosition,
1379                                                             myWorkingPlane.Position().XDirection()),
1380                                                             myGeom.mySelToleranceForText2d != 0
1381                                                           ? myGeom.mySelToleranceForText2d : 1.0));
1382     aSensitiveForText = new Select3D_SensitiveCircle (anOwner, aSensitiveGeom, Standard_True);
1383   }
1384   if (theMode > 0)
1385   {
1386     anOwner->SetDisplayMode (AIS_DDM_Line);
1387     Handle(AIS_DimensionOwner) aTextOwner = new AIS_DimensionOwner (this, AIS_DDM_Text, 7);
1388     aSensitiveForText->Set (aTextOwner);
1389   }
1390   else
1391     computeFlyoutSelection (theSelection, anOwner);
1392
1393   theSelection->Add (aSensitiveForLine);
1394   theSelection->Add (aSensitiveForText);
1395 }