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