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