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