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