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