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