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