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