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