1 // Created on: 2013-11-11
2 // Created by: Anastasia BORISOVA
3 // Copyright (c) 2013-2014 OPEN CASCADE SAS
5 // This file is part of Open CASCADE Technology software library.
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
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.
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
16 #include <AIS_Dimension.hxx>
19 #include <AIS_DimensionOwner.hxx>
20 #include <Adaptor3d_HCurve.hxx>
21 #include <BRepAdaptor_Curve.hxx>
22 #include <BRepAdaptor_Surface.hxx>
23 #include <BRepBndLib.hxx>
24 #include <Bnd_Box.hxx>
26 #include <Font_BRepFont.hxx>
27 #include <GC_MakeCircle.hxx>
28 #include <Geom_Line.hxx>
29 #include <GeomAdaptor_Curve.hxx>
30 #include <Geom_Circle.hxx>
31 #include <Geom_TrimmedCurve.hxx>
32 #include <gce_MakeDir.hxx>
33 #include <gce_MakeLin.hxx>
34 #include <gce_MakePln.hxx>
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>
55 #include <Select3D_SensitiveCircle.hxx>
56 #include <Select3D_SensitiveGroup.hxx>
57 #include <Select3D_SensitiveCurve.hxx>
58 #include <Select3D_SensitiveSegment.hxx>
59 #include <Select3D_SensitiveTriangle.hxx>
60 #include <Select3D_SensitiveTriangulation.hxx>
61 #include <Poly_Array1OfTriangle.hxx>
62 #include <Poly_Triangulation.hxx>
63 #include <Standard_CString.hxx>
64 #include <Standard_ProgramError.hxx>
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>
71 #include <TopoDS_Vertex.hxx>
73 #include <Units_UnitsDictionary.hxx>
74 #include <UnitsAPI.hxx>
75 #include <UnitsAPI_SystemUnits.hxx>
77 IMPLEMENT_STANDARD_HANDLE(AIS_Dimension, AIS_InteractiveObject)
78 IMPLEMENT_STANDARD_RTTIEXT(AIS_Dimension, AIS_InteractiveObject)
82 // default text strings
83 static const Standard_Utf32Char THE_FILL_CHARACTER ('0');
84 static const TCollection_ExtendedString THE_EMPTY_LABEL;
85 static const TCollection_AsciiString THE_UNDEFINED_UNITS;
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;
91 // default selection priorities
92 static const Standard_Integer THE_NEUTRAL_SEL_PRIORITY = 5;
93 static const Standard_Integer THE_LOCAL_SEL_PRIORITY = 6;
96 //=======================================================================
97 //function : Constructor
99 //=======================================================================
100 AIS_Dimension::AIS_Dimension (const AIS_KindOfDimension theType)
101 : AIS_InteractiveObject(),
103 myIsValueCustom (Standard_False),
104 mySpecialSymbol (' '),
105 myDisplaySpecialSymbol (AIS_DSS_No),
106 myGeometryType (GeometryType_UndefShapes),
107 myIsPlaneCustom (Standard_False),
109 myIsGeometryValid (Standard_False),
110 myKindOfDimension (theType)
114 //=======================================================================
115 //function : SetCustomValue
117 //=======================================================================
118 void AIS_Dimension::SetCustomValue (const Standard_Real theValue)
120 if (myIsValueCustom && myCustomValue == theValue)
125 myIsValueCustom = Standard_True;
127 myCustomValue = theValue;
132 //=======================================================================
133 //function : GetPlane
135 //=======================================================================
136 const gp_Pln& AIS_Dimension::GetPlane() const
141 //=======================================================================
142 //function : GetGeometryType
144 //=======================================================================
145 const Standard_Integer AIS_Dimension::GetGeometryType () const
147 return myGeometryType;
150 //=======================================================================
151 //function : SetUserPlane
153 //=======================================================================
154 void AIS_Dimension::SetCustomPlane (const gp_Pln& thePlane)
157 myIsPlaneCustom = Standard_True;
159 // Disable fixed (custom) text position
160 UnsetFixedTextPosition();
162 // Check validity if geometry has been set already.
169 //=======================================================================
170 //function : SetDimensionAspect
172 //=======================================================================
173 void AIS_Dimension::SetDimensionAspect (const Handle(Prs3d_DimensionAspect)& theDimensionAspect)
175 myDrawer->SetDimensionAspect (theDimensionAspect);
180 //=======================================================================
181 //function : SetDisplaySpecialSymbol
183 //=======================================================================
184 void AIS_Dimension::SetDisplaySpecialSymbol (const AIS_DisplaySpecialSymbol theDisplaySpecSymbol)
186 if (myDisplaySpecialSymbol == theDisplaySpecSymbol)
191 myDisplaySpecialSymbol = theDisplaySpecSymbol;
196 //=======================================================================
197 //function : SetSpecialSymbol
199 //=======================================================================
200 void AIS_Dimension::SetSpecialSymbol (const Standard_ExtCharacter theSpecialSymbol)
202 if (mySpecialSymbol == theSpecialSymbol)
207 mySpecialSymbol = theSpecialSymbol;
212 //=======================================================================
213 //function : SetSelToleranceForText2d
215 //=======================================================================
216 void AIS_Dimension::SetSelToleranceForText2d (const Standard_Real theTol)
218 if (mySelToleranceForText2d == theTol)
223 mySelToleranceForText2d = theTol;
228 //=======================================================================
229 //function : SetFlyout
231 //=======================================================================
232 void AIS_Dimension::SetFlyout (const Standard_Real theFlyout)
234 if (myFlyout == theFlyout)
239 myFlyout = theFlyout;
241 // Disable fixed text position
242 UnsetFixedTextPosition();
247 //=======================================================================
248 //function : GetDisplayUnits
250 //=======================================================================
251 const TCollection_AsciiString& AIS_Dimension::GetDisplayUnits() const
253 return THE_UNDEFINED_UNITS;
256 //=======================================================================
257 //function : GetModelUnits
259 //=======================================================================
260 const TCollection_AsciiString& AIS_Dimension::GetModelUnits() const
262 return THE_UNDEFINED_UNITS;
265 //=======================================================================
266 //function : ValueToDisplayUnits
268 //=======================================================================
269 Standard_Real AIS_Dimension::ValueToDisplayUnits() const
271 return UnitsAPI::AnyToAny (GetValue(),
272 GetModelUnits().ToCString(),
273 GetDisplayUnits().ToCString());
276 //=======================================================================
277 //function : GetValueString
279 //=======================================================================
280 TCollection_ExtendedString AIS_Dimension::GetValueString (Standard_Real& theWidth) const
282 // format value string using "sprintf"
283 TCollection_AsciiString aFormatStr = myDrawer->DimensionAspect()->ValueStringFormat();
285 char aFmtBuffer[256];
286 sprintf (aFmtBuffer, aFormatStr.ToCString(), ValueToDisplayUnits());
287 TCollection_ExtendedString aValueStr = TCollection_ExtendedString (aFmtBuffer);
289 // add units to values string
290 if (myDrawer->DimensionAspect()->IsUnitsDisplayed())
293 aValueStr += TCollection_ExtendedString (GetDisplayUnits());
296 switch (myDisplaySpecialSymbol)
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;
303 // Get text style parameters
304 Quantity_Color aColor;
305 Standard_CString aFontName;
306 Standard_Real aFactor;
307 Standard_Real aSpace;
308 myDrawer->DimensionAspect()->TextAspect()->Aspect()->Values (aColor, aFontName, aFactor, aSpace);
309 Font_FontAspect aFontAspect = myDrawer->DimensionAspect()->TextAspect()->Aspect()->GetTextFontAspect();
310 Standard_Real aFontHeight = myDrawer->DimensionAspect()->TextAspect()->Height();
312 NCollection_Utf8String anUTFString = (Standard_Utf16Char* )aValueStr.ToExtString();
316 if (myDrawer->DimensionAspect()->IsText3d())
318 // text width produced by BRepFont
319 Font_BRepFont aFont (aFontName, aFontAspect, aFontHeight);
321 for (NCollection_Utf8Iter anIter = anUTFString.Iterator(); *anIter != 0; )
323 Standard_Utf32Char aCurrChar = *anIter;
324 Standard_Utf32Char aNextChar = *(++anIter);
325 theWidth += aFont.AdvanceX (aCurrChar, aNextChar);
330 // Text width for 1:1 scale 2D case
331 Handle(Font_FTFont) aFont = new Font_FTFont();
332 aFont->Init (aFontName, aFontAspect, (const unsigned int)aFontHeight, THE_2D_TEXT_RESOLUTION);
334 for (NCollection_Utf8Iter anIter = anUTFString.Iterator(); *anIter != 0; )
336 Standard_Utf32Char aCurrChar = *anIter;
337 Standard_Utf32Char aNextChar = *(++anIter);
338 theWidth += (Standard_Real) aFont->AdvanceX (aCurrChar, aNextChar);
345 //=======================================================================
346 //function : DrawArrow
348 //=======================================================================
349 void AIS_Dimension::DrawArrow (const Handle(Prs3d_Presentation)& thePresentation,
350 const gp_Pnt& theLocation,
351 const gp_Dir& theDirection)
353 Prs3d_Root::NewGroup (thePresentation);
355 Quantity_Length aLength = myDrawer->DimensionAspect()->ArrowAspect()->Length();
356 Standard_Real anAngle = myDrawer->DimensionAspect()->ArrowAspect()->Angle();
358 if (myDrawer->DimensionAspect()->IsArrows3d())
360 Prs3d_Arrow::Draw (thePresentation,
368 gp_Pnt aLeftPoint (gp::Origin());
369 gp_Pnt aRightPoint (gp::Origin());
370 const gp_Dir& aPlane = GetPlane().Axis().Direction();
372 PointsForArrow (theLocation, theDirection, aPlane, aLength, anAngle, aLeftPoint, aRightPoint);
374 Handle(Graphic3d_ArrayOfTriangles) anArrow = new Graphic3d_ArrayOfTriangles(3);
376 anArrow->AddVertex (aLeftPoint);
377 anArrow->AddVertex (theLocation);
378 anArrow->AddVertex (aRightPoint);
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);
390 Handle(Prs3d_ShadingAspect) aShadingStyle = new Prs3d_ShadingAspect();
391 aShadingStyle->SetColor (aColor);
392 aShadingStyle->SetMaterial (aShadeMat);
394 Prs3d_Root::CurrentGroup (thePresentation)->SetPrimitivesAspect (aShadingStyle->Aspect());
395 Prs3d_Root::CurrentGroup (thePresentation)->AddPrimitiveArray (anArrow);
398 SelectionGeometry::Arrow& aSensitiveArrow = mySelectionGeom.NewArrow();
399 aSensitiveArrow.Position = theLocation;
400 aSensitiveArrow.Direction = theDirection;
403 //=======================================================================
404 //function : DrawText
406 //=======================================================================
407 void AIS_Dimension::DrawText (const Handle(Prs3d_Presentation)& thePresentation,
408 const gp_Pnt& theTextPos,
409 const gp_Dir& theTextDir,
410 const TCollection_ExtendedString& theText,
411 const Standard_Integer theLabelPosition)
413 if (myDrawer->DimensionAspect()->IsText3d())
415 // getting font parameters
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();
422 Standard_Real aFontHeight = myDrawer->DimensionAspect()->TextAspect()->Height();
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);
429 // compute text width with kerning
430 Standard_Real aTextWidth = 0.0;
431 Standard_Real aTextHeight = aFont.Ascender() + aFont.Descender();
433 for (NCollection_Utf8Iter anIter = anUTFString.Iterator(); *anIter != 0; )
435 Standard_Utf32Char aCurrChar = *anIter;
436 Standard_Utf32Char aNextChar = *(++anIter);
437 aTextWidth += aFont.AdvanceX (aCurrChar, aNextChar);
440 // formating text position in XOY plane
441 Standard_Integer aHLabelPos = theLabelPosition & LabelPosition_HMask;
442 Standard_Integer aVLabelPos = theLabelPosition & LabelPosition_VMask;
444 gp_Dir aTextDir (aHLabelPos == LabelPosition_Left ? -theTextDir : theTextDir);
446 // compute label offsets
447 Standard_Real aMarginSize = aFontHeight * THE_3D_TEXT_MARGIN;
448 Standard_Real aCenterHOffset = 0.0;
449 Standard_Real aCenterVOffset = 0.0;
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;
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;
463 // compute shape offset transformation
464 Standard_Real aShapeHOffset = aCenterHOffset - aTextWidth / 2.0;
465 Standard_Real aShapeVOffset = aCenterVOffset - aTextHeight / 2.0;
467 // center shape in its bounding box (suppress border spacing added by FT_Font)
469 BRepBndLib::AddClose (aTextShape, aShapeBnd);
471 Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
472 aShapeBnd.Get (aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
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;
479 gp_Trsf anOffsetTrsf;
480 anOffsetTrsf.SetTranslation (gp::Origin(), gp_Pnt (aShapeHOffset, aShapeVOffset, 0.0));
481 aTextShape.Move (anOffsetTrsf);
483 // transform text to myWorkingPlane coordinate system
484 gp_Ax3 aTextCoordSystem (theTextPos, GetPlane().Axis().Direction(), aTextDir);
485 gp_Trsf aTextPlaneTrsf;
486 aTextPlaneTrsf.SetTransformation (aTextCoordSystem, gp_Ax3 (gp::XOY()));
487 aTextShape.Move (aTextPlaneTrsf);
489 // set text flipping anchors
490 gp_Trsf aCenterOffsetTrsf;
491 gp_Pnt aCenterOffset (aCenterHOffset, aCenterVOffset, 0.0);
492 aCenterOffsetTrsf.SetTranslation (gp::Origin(), aCenterOffset);
494 gp_Pnt aCenterOfLabel (gp::Origin());
495 aCenterOfLabel.Transform (aCenterOffsetTrsf);
496 aCenterOfLabel.Transform (aTextPlaneTrsf);
498 gp_Ax2 aFlippingAxes (aCenterOfLabel, GetPlane().Axis().Direction(), aTextDir);
499 Prs3d_Root::CurrentGroup (thePresentation)->SetFlippingOptions (Standard_True, aFlippingAxes);
502 if (myDrawer->DimensionAspect()->IsTextShaded())
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);
514 StdPrs_ShadedShape::Add (thePresentation, aTextShape, myDrawer);
518 // setting color for text
519 myDrawer->FreeBoundaryAspect()->Aspect()->SetColor (aColor);
521 StdPrs_WFShape::Add (thePresentation, aTextShape, myDrawer);
523 Prs3d_Root::CurrentGroup (thePresentation)->SetFlippingOptions (Standard_False, gp_Ax2());
525 mySelectionGeom.TextPos = aCenterOfLabel;
526 mySelectionGeom.TextDir = aTextDir;
527 mySelectionGeom.TextWidth = aTextWidth + aMarginSize * 2.0;
528 mySelectionGeom.TextHeight = aTextHeight;
533 // generate primitives for 2D text
534 myDrawer->DimensionAspect()->TextAspect()->Aspect()->SetDisplayType (Aspect_TODT_DIMENSION);
536 Prs3d_Text::Draw (thePresentation,
537 myDrawer->DimensionAspect()->TextAspect(),
541 mySelectionGeom.TextPos = theTextPos;
542 mySelectionGeom.TextDir = theTextDir;
543 mySelectionGeom.TextWidth = 0.0;
544 mySelectionGeom.TextHeight = 0.0;
547 //=======================================================================
548 //function : DrawExtension
550 //=======================================================================
551 void AIS_Dimension::DrawExtension (const Handle(Prs3d_Presentation)& thePresentation,
552 const Standard_Real theExtensionSize,
553 const gp_Pnt& theExtensionStart,
554 const gp_Dir& theExtensionDir,
555 const TCollection_ExtendedString& theLabelString,
556 const Standard_Real theLabelWidth,
557 const Standard_Integer theMode,
558 const Standard_Integer theLabelPosition)
560 // reference line for extension starting at its connection point
561 gp_Lin anExtensionLine (theExtensionStart, theExtensionDir);
563 Standard_Boolean hasLabel = theLabelString.Length() > 0;
564 if (hasLabel && (theMode == ComputeMode_All || theMode == ComputeMode_Text))
566 // compute text primitives; get its model width
567 gp_Pnt aTextPos = ElCLib::Value (theExtensionSize, anExtensionLine);
568 gp_Dir aTextDir = theExtensionDir;
570 DrawText (thePresentation,
577 if (theMode != ComputeMode_All && theMode != ComputeMode_Line)
582 Standard_Boolean isShortLine = !myDrawer->DimensionAspect()->IsText3d()
583 || theLabelPosition & LabelPosition_VCenter;
585 // compute graphical primitives and sensitives for extension line
586 gp_Pnt anExtStart = theExtensionStart;
587 gp_Pnt anExtEnd = !hasLabel || isShortLine
588 ? ElCLib::Value (theExtensionSize, anExtensionLine)
589 : ElCLib::Value (theExtensionSize + theLabelWidth, anExtensionLine);
591 // add graphical primitives
592 Handle(Graphic3d_ArrayOfSegments) anExtPrimitive = new Graphic3d_ArrayOfSegments (2);
593 anExtPrimitive->AddVertex (anExtStart);
594 anExtPrimitive->AddVertex (anExtEnd);
596 // add selection primitives
597 SelectionGeometry::Curve& aSensitiveCurve = mySelectionGeom.NewCurve();
598 aSensitiveCurve.Append (anExtStart);
599 aSensitiveCurve.Append (anExtEnd);
601 if (!myDrawer->DimensionAspect()->IsText3d() && theMode == ComputeMode_All)
603 Prs3d_Root::CurrentGroup (thePresentation)->SetStencilTestOptions (Standard_True);
605 Handle(Graphic3d_AspectLine3d) aDimensionLineStyle = myDrawer->DimensionAspect()->LineAspect()->Aspect();
606 Prs3d_Root::CurrentGroup (thePresentation)->SetPrimitivesAspect (aDimensionLineStyle);
607 Prs3d_Root::CurrentGroup (thePresentation)->AddPrimitiveArray (anExtPrimitive);
608 if (!myDrawer->DimensionAspect()->IsText3d() && theMode == ComputeMode_All)
610 Prs3d_Root::CurrentGroup (thePresentation)->SetStencilTestOptions (Standard_False);
614 //=======================================================================
615 //function : DrawLinearDimension
617 //=======================================================================
618 void AIS_Dimension::DrawLinearDimension (const Handle(Prs3d_Presentation)& thePresentation,
619 const Standard_Integer theMode,
620 const gp_Pnt& theFirstPoint,
621 const gp_Pnt& theSecondPoint,
622 const Standard_Boolean theIsOneSide)
624 // do not build any dimension for equal points
625 if (theFirstPoint.IsEqual (theSecondPoint, Precision::Confusion()))
627 Standard_ProgramError::Raise ("Can not build presentation for equal points.");
630 Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
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();
635 // prepare label string and compute its geometrical width
636 Standard_Real aLabelWidth;
637 TCollection_ExtendedString aLabelString = GetValueString (aLabelWidth);
639 // add margins to cut dimension lines for 3d text
640 if (aDimensionAspect->IsText3d())
642 aLabelWidth += aDimensionAspect->TextAspect()->Height() * THE_3D_TEXT_MARGIN * 2.0;
645 // handle user-defined and automatic arrow placement
646 Standard_Boolean isArrowsExternal = Standard_False;
647 Standard_Integer aLabelPosition = LabelPosition_None;
649 Prs3d_DimensionTextHorizontalPosition aHorisontalTextPos = aDimensionAspect->TextHorizontalPosition();
650 if (IsTextPositionCustom())
652 if (!AdjustParametersForLinear (myFixedTextPosition, theFirstPoint, theSecondPoint,
653 anExtensionSize, aHorisontalTextPos, myFlyout, myPlane, myIsPlaneCustom))
655 Standard_ProgramError::Raise ("Can not adjust plane to the custom label position.");
659 FitTextAlignmentForLinear (theFirstPoint, theSecondPoint, theIsOneSide, aHorisontalTextPos,
660 aLabelPosition, isArrowsExternal);
662 // compute dimension line points
663 gp_Ax1 aPlaneNormal = GetPlane().Axis();
664 gp_Dir aTargetPointsVector = gce_MakeDir (theFirstPoint, theSecondPoint);
666 // compute flyout direction vector
667 gp_Dir aFlyoutVector = aPlaneNormal.Direction() ^ aTargetPointsVector;
669 // create lines for layouts
670 gp_Lin aLine1 (theFirstPoint, aFlyoutVector);
671 gp_Lin aLine2 (theSecondPoint, aFlyoutVector);
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);
677 gp_Lin aDimensionLine = gce_MakeLin (aLineBegPoint, aLineEndPoint);
679 // compute arrows positions and directions
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();
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);
690 if (isArrowsExternal)
692 aFirstArrowDir.Reverse();
693 aSecondArrowDir.Reverse();
696 aFirstArrowBegin = aLineBegPoint;
697 aSecondArrowBegin = aLineEndPoint;
698 aFirstArrowEnd = aLineBegPoint.Translated (-gp_Vec (aFirstArrowDir).Scaled (anArrowLength));
699 aSecondArrowEnd = aLineEndPoint.Translated (-gp_Vec (aSecondArrowDir).Scaled (anArrowLength));
701 gp_Pnt aCenterLineBegin = isArrowsExternal
702 ? aLineBegPoint : aFirstArrowEnd;
704 gp_Pnt aCenterLineEnd = isArrowsExternal || theIsOneSide
705 ? aLineEndPoint : aSecondArrowEnd;
708 switch (aLabelPosition & LabelPosition_HMask)
710 // ------------------------------------------------------------------------ //
712 // -------------------------------------------------------------------------//
713 case LabelPosition_HCenter:
715 // add label on dimension or extension line to presentation
716 Prs3d_Root::NewGroup (thePresentation);
718 gp_Pnt aTextPos = IsTextPositionCustom() ? myFixedTextPosition
719 : (aCenterLineBegin.XYZ() + aCenterLineEnd.XYZ()) * 0.5;
720 gp_Dir aTextDir = aDimensionLine.Direction();
722 // add text primitives
723 if (theMode == ComputeMode_All || theMode == ComputeMode_Text)
725 DrawText (thePresentation,
732 // add dimension line primitives
733 if (theMode == ComputeMode_All || theMode == ComputeMode_Line)
735 Standard_Boolean isLineBreak = aDimensionAspect->TextVerticalPosition() == Prs3d_DTVP_Center
736 && aDimensionAspect->IsText3d();
738 Handle(Graphic3d_ArrayOfSegments) aPrimSegments = new Graphic3d_ArrayOfSegments (isLineBreak ? 4 : 2);
740 // compute continuous or sectioned main line segments
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;
749 aPrimSegments->AddVertex (aSection1Beg);
750 aPrimSegments->AddVertex (aSection1End);
751 aPrimSegments->AddVertex (aSection2Beg);
752 aPrimSegments->AddVertex (aSection2End);
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);
763 aPrimSegments->AddVertex (aCenterLineBegin);
764 aPrimSegments->AddVertex (aCenterLineEnd);
766 SelectionGeometry::Curve& aSensitiveCurve = mySelectionGeom.NewCurve();
767 aSensitiveCurve.Append (aCenterLineBegin);
768 aSensitiveCurve.Append (aCenterLineEnd);
771 // set text label justification
772 Graphic3d_VerticalTextAlignment aTextJustificaton = Graphic3d_VTA_BOTTOM;
773 switch (aLabelPosition & LabelPosition_VMask)
775 case LabelPosition_Above :
776 case LabelPosition_VCenter : aTextJustificaton = Graphic3d_VTA_BOTTOM; break;
777 case LabelPosition_Below : aTextJustificaton = Graphic3d_VTA_TOP; break;
779 aDimensionAspect->TextAspect()->SetVerticalJustification (aTextJustificaton);
781 // main dimension line, short extension
782 if (!aDimensionAspect->IsText3d() && theMode == ComputeMode_All)
784 Prs3d_Root::CurrentGroup (thePresentation)->SetStencilTestOptions (Standard_True);
786 Prs3d_Root::CurrentGroup (thePresentation)->SetPrimitivesAspect (aDimensionAspect->LineAspect()->Aspect());
787 Prs3d_Root::CurrentGroup (thePresentation)->AddPrimitiveArray (aPrimSegments);
788 if (!aDimensionAspect->IsText3d() && theMode == ComputeMode_All)
790 Prs3d_Root::CurrentGroup (thePresentation)->SetStencilTestOptions (Standard_False);
793 // add arrows to presentation
794 Prs3d_Root::NewGroup (thePresentation);
796 DrawArrow (thePresentation, aFirstArrowBegin, aFirstArrowDir);
799 DrawArrow (thePresentation, aSecondArrowBegin, aSecondArrowDir);
802 if (!isArrowsExternal)
807 // add arrow extension lines to presentation
808 Prs3d_Root::NewGroup (thePresentation);
810 DrawExtension (thePresentation, aDimensionAspect->ArrowTailSize(),
811 aFirstArrowEnd, aFirstExtensionDir,
812 THE_EMPTY_LABEL, 0.0, theMode, LabelPosition_None);
815 DrawExtension (thePresentation, aDimensionAspect->ArrowTailSize(),
816 aSecondArrowEnd, aSecondExtensionDir,
817 THE_EMPTY_LABEL, 0.0, theMode, LabelPosition_None);
823 // ------------------------------------------------------------------------ //
825 // -------------------------------------------------------------------------//
827 case LabelPosition_Left:
829 // add label on dimension or extension line to presentation
830 Prs3d_Root::NewGroup (thePresentation);
832 // Left extension with the text
833 DrawExtension (thePresentation, anExtensionSize,
843 // add dimension line primitives
844 if (theMode == ComputeMode_All || theMode == ComputeMode_Line)
846 // add central dimension line
847 Prs3d_Root::NewGroup (thePresentation);
849 // add graphical primitives
850 Handle(Graphic3d_ArrayOfSegments) aPrimSegments = new Graphic3d_ArrayOfSegments (2);
851 aPrimSegments->AddVertex (aCenterLineBegin);
852 aPrimSegments->AddVertex (aCenterLineEnd);
854 Prs3d_Root::CurrentGroup (thePresentation)->SetPrimitivesAspect (aDimensionAspect->LineAspect()->Aspect());
855 Prs3d_Root::CurrentGroup (thePresentation)->AddPrimitiveArray (aPrimSegments);
857 // add selection primitives
858 SelectionGeometry::Curve& aSensitiveCurve = mySelectionGeom.NewCurve();
859 aSensitiveCurve.Append (aCenterLineBegin);
860 aSensitiveCurve.Append (aCenterLineEnd);
862 // add arrows to presentation
863 Prs3d_Root::NewGroup (thePresentation);
865 DrawArrow (thePresentation, aFirstArrowBegin, aFirstArrowDir);
868 DrawArrow (thePresentation, aSecondArrowBegin, aSecondArrowDir);
871 if (!isArrowsExternal || theIsOneSide)
876 // add extension lines for external arrows
877 Prs3d_Root::NewGroup (thePresentation);
879 DrawExtension (thePresentation, aDimensionAspect->ArrowTailSize(),
880 aSecondArrowEnd, aSecondExtensionDir,
881 THE_EMPTY_LABEL, 0.0, theMode, LabelPosition_None);
886 // ------------------------------------------------------------------------ //
888 // -------------------------------------------------------------------------//
890 case LabelPosition_Right:
892 // add label on dimension or extension line to presentation
893 Prs3d_Root::NewGroup (thePresentation);
895 // Right extension with text
896 DrawExtension (thePresentation, anExtensionSize,
901 aLabelString, aLabelWidth,
905 if (theMode == ComputeMode_All || theMode == ComputeMode_Line)
907 // add central dimension line
908 Prs3d_Root::NewGroup (thePresentation);
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);
917 // add selection primitives
918 SelectionGeometry::Curve& aSensitiveCurve = mySelectionGeom.NewCurve();
919 aSensitiveCurve.Append (aCenterLineBegin);
920 aSensitiveCurve.Append (aCenterLineEnd);
922 // add arrows to presentation
923 Prs3d_Root::NewGroup (thePresentation);
925 DrawArrow (thePresentation, aSecondArrowBegin, aSecondArrowDir);
928 DrawArrow (thePresentation, aFirstArrowBegin, aFirstArrowDir);
931 if (!isArrowsExternal || theIsOneSide)
936 // add extension lines for external arrows
937 Prs3d_Root::NewGroup (thePresentation);
939 DrawExtension (thePresentation, aDimensionAspect->ArrowTailSize(),
940 aFirstArrowEnd, aFirstExtensionDir,
941 THE_EMPTY_LABEL, 0.0, theMode, LabelPosition_None);
948 // add flyout lines to presentation
949 if (theMode == ComputeMode_All)
951 Prs3d_Root::NewGroup (thePresentation);
953 Handle(Graphic3d_ArrayOfSegments) aPrimSegments = new Graphic3d_ArrayOfSegments(4);
954 aPrimSegments->AddVertex (theFirstPoint);
955 aPrimSegments->AddVertex (aLineBegPoint);
957 aPrimSegments->AddVertex (theSecondPoint);
958 aPrimSegments->AddVertex (aLineEndPoint);
960 Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
961 Prs3d_Root::CurrentGroup (thePresentation)->SetPrimitivesAspect (aDimensionAspect->LineAspect()->Aspect());
962 Prs3d_Root::CurrentGroup (thePresentation)->AddPrimitiveArray (aPrimSegments);
965 mySelectionGeom.IsComputed = Standard_True;
968 //=======================================================================
969 //function : ComputeLinearFlyouts
971 //=======================================================================
972 void AIS_Dimension::ComputeLinearFlyouts (const Handle(SelectMgr_Selection)& theSelection,
973 const Handle(SelectMgr_EntityOwner)& theOwner,
974 const gp_Pnt& theFirstPoint,
975 const gp_Pnt& theSecondPoint)
977 // count flyout direction
978 gp_Ax1 aPlaneNormal = GetPlane().Axis();
979 gp_Dir aTargetPointsVector = gce_MakeDir (theFirstPoint, theSecondPoint);
981 // count a flyout direction vector.
982 gp_Dir aFlyoutVector = aPlaneNormal.Direction() ^ aTargetPointsVector;
984 // create lines for layouts
985 gp_Lin aLine1 (theFirstPoint, aFlyoutVector);
986 gp_Lin aLine2 (theSecondPoint, aFlyoutVector);
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);
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);
999 //=======================================================================
1000 //function : CircleFromPlanarFace
1001 //purpose : if possible computes circle from planar face
1002 //=======================================================================
1003 Standard_Boolean AIS_Dimension::CircleFromPlanarFace (const TopoDS_Face& theFace,
1004 Handle(Geom_Curve)& theCurve,
1005 gp_Pnt& theFirstPoint,
1006 gp_Pnt& theLastPoint)
1008 TopExp_Explorer anIt (theFace, TopAbs_EDGE);
1009 for ( ; anIt.More(); anIt.Next())
1011 TopoDS_Edge aCurEdge = TopoDS::Edge (anIt.Current());
1012 if (AIS::ComputeGeometry (aCurEdge, theCurve, theFirstPoint, theLastPoint))
1014 if (theCurve->IsInstance (STANDARD_TYPE(Geom_Circle)))
1016 return Standard_True;
1020 return Standard_False;
1023 //=======================================================================
1024 //function : InitCircularDimension
1026 //=======================================================================
1027 Standard_Boolean AIS_Dimension::InitCircularDimension (const TopoDS_Shape& theShape,
1029 gp_Pnt& theMiddleArcPoint,
1030 Standard_Boolean& theIsClosed)
1033 Handle(Geom_Surface) aBasisSurf;
1034 AIS_KindOfSurface aSurfType = AIS_KOS_OtherSurface;
1035 gp_Pnt aFirstPoint, aLastPoint;
1036 Standard_Real anOffset = 0.0;
1037 Standard_Real aFirstParam = 0.0;
1038 Standard_Real aLastParam = 0.0;
1040 // discover circular geometry
1041 if (theShape.ShapeType() == TopAbs_FACE)
1043 AIS::GetPlaneFromFace (TopoDS::Face (theShape), aPln, aBasisSurf, aSurfType, anOffset);
1045 if (aSurfType == AIS_KOS_Plane)
1047 Handle(Geom_Curve) aCurve;
1048 if (!CircleFromPlanarFace (TopoDS::Face (theShape), aCurve, aFirstPoint, aLastPoint))
1050 return Standard_False;
1053 theCircle = Handle(Geom_Circle)::DownCast (aCurve)->Circ();
1058 BRepAdaptor_Surface aSurf1 (TopoDS::Face (theShape));
1059 Standard_Real aFirstU = aSurf1.FirstUParameter();
1060 Standard_Real aLastU = aSurf1.LastUParameter();
1061 Standard_Real aFirstV = aSurf1.FirstVParameter();
1062 Standard_Real aLastV = aSurf1.LastVParameter();
1063 Standard_Real aMidU = (aFirstU + aLastU) * 0.5;
1064 Standard_Real aMidV = (aFirstV + aLastV) * 0.5;
1065 aSurf1.D0 (aMidU, aMidV, aCurPos);
1066 Handle (Adaptor3d_HCurve) aBasisCurve;
1067 Standard_Boolean isExpectedType = Standard_False;
1068 if (aSurfType == AIS_KOS_Cylinder)
1070 isExpectedType = Standard_True;
1074 if (aSurfType == AIS_KOS_Revolution)
1076 aBasisCurve = aSurf1.BasisCurve();
1077 if (aBasisCurve->GetType() == GeomAbs_Line)
1079 isExpectedType = Standard_True;
1082 else if (aSurfType == AIS_KOS_Extrusion)
1084 aBasisCurve = aSurf1.BasisCurve();
1085 if (aBasisCurve->GetType() == GeomAbs_Circle)
1087 isExpectedType = Standard_True;
1092 if (!isExpectedType)
1094 return Standard_False;
1097 Handle(Geom_Curve) aCurve;
1098 aCurve = aBasisSurf->VIso(aMidV);
1099 if (aCurve->DynamicType() == STANDARD_TYPE (Geom_Circle))
1101 theCircle = Handle(Geom_Circle)::DownCast (aCurve)->Circ();
1103 else if (aCurve->DynamicType() == STANDARD_TYPE (Geom_TrimmedCurve))
1105 Handle(Geom_TrimmedCurve) aTrimmedCurve = Handle(Geom_TrimmedCurve)::DownCast (aCurve);
1106 aFirstU = aTrimmedCurve->FirstParameter();
1107 aLastU = aTrimmedCurve->LastParameter();
1108 if (aTrimmedCurve->DynamicType() == STANDARD_TYPE (Geom_Circle))
1110 theCircle = Handle(Geom_Circle)::DownCast(aTrimmedCurve)->Circ();
1115 // Compute a circle from 3 points on "aCurve"
1117 aSurf1.D0 (aFirstU, aMidV, aP1);
1118 aSurf1.D0 (aLastU, aMidV, aP2);
1119 GC_MakeCircle aMkCirc (aP1, aCurPos, aP2);
1120 theCircle = aMkCirc.Value()->Circ();
1123 aFirstPoint = ElCLib::Value (aFirstU, theCircle);
1124 aLastPoint = ElCLib::Value (aLastU, theCircle);
1127 else // TopAbs_EDGE | TopAbs_WIRE
1130 if (theShape.ShapeType() == TopAbs_WIRE)
1132 TopExp_Explorer anIt (theShape, TopAbs_EDGE);
1135 anEdge = TopoDS::Edge (anIt.Current());
1138 else if (theShape.ShapeType() == TopAbs_EDGE)
1140 anEdge = TopoDS::Edge (theShape);
1142 else // Unexpected type of shape
1144 return Standard_False;
1147 BRepAdaptor_Curve anAdaptedCurve (anEdge);
1148 if (anAdaptedCurve.GetType() != GeomAbs_Circle)
1150 return Standard_False;
1153 theCircle = anAdaptedCurve.Circle();
1154 aFirstPoint = anAdaptedCurve.Value (anAdaptedCurve.FirstParameter());
1155 aLastPoint = anAdaptedCurve.Value (anAdaptedCurve.LastParameter());
1158 theIsClosed = aFirstPoint.IsEqual (aLastPoint, Precision::Confusion());
1160 gp_Pnt aCenter = theCircle.Location();
1162 if (theIsClosed) // Circle
1164 gp_Dir anXDir = theCircle.XAxis().Direction();
1165 theMiddleArcPoint = aCenter.Translated (gp_Vec (anXDir) * theCircle.Radius());
1169 aFirstParam = ElCLib::Parameter (theCircle, aFirstPoint);
1170 aLastParam = ElCLib::Parameter (theCircle, aLastPoint);
1171 if (aFirstParam > aLastParam)
1173 aFirstParam -= 2.0 * M_PI;
1176 Standard_Real aParCurPos = (aFirstParam + aLastParam) * 0.5;
1177 gp_Vec aVec = gp_Vec (aCenter, ElCLib::Value (aParCurPos, theCircle)).Normalized () * theCircle.Radius ();
1178 theMiddleArcPoint = aCenter.Translated (aVec);
1181 return Standard_True;
1184 //=======================================================================
1185 //function : ComputeSelection
1187 //=======================================================================
1188 void AIS_Dimension::ComputeSelection (const Handle(SelectMgr_Selection)& theSelection,
1189 const Standard_Integer theMode)
1191 if (!mySelectionGeom.IsComputed)
1196 AIS_DimensionSelectionMode aSelectionMode = (AIS_DimensionSelectionMode)theMode;
1198 // init appropriate entity owner
1199 Handle(SelectMgr_EntityOwner) aSensitiveOwner;
1201 switch (aSelectionMode)
1203 // neutral selection owner
1205 aSensitiveOwner = new SelectMgr_EntityOwner (this, THE_NEUTRAL_SEL_PRIORITY);
1208 // local selection owners
1211 aSensitiveOwner = new AIS_DimensionOwner (this, aSelectionMode, THE_LOCAL_SEL_PRIORITY);
1215 if (aSelectionMode == AIS_DSM_All || aSelectionMode == AIS_DSM_Line)
1217 // sensitives for dimension line segments
1218 Handle(Select3D_SensitiveGroup) aGroupOfSensitives = new Select3D_SensitiveGroup (aSensitiveOwner);
1220 SelectionGeometry::SeqOfCurves::Iterator aCurveIt (mySelectionGeom.DimensionLine);
1221 for (; aCurveIt.More(); aCurveIt.Next())
1223 const SelectionGeometry::HCurve& aCurveData = aCurveIt.Value();
1225 TColgp_Array1OfPnt aSensitivePnts (1, aCurveData->Length());
1226 for (Standard_Integer aPntIt = 1; aPntIt <= aCurveData->Length(); ++aPntIt)
1228 aSensitivePnts.ChangeValue (aPntIt) = aCurveData->Value (aPntIt);
1231 aGroupOfSensitives->Add (new Select3D_SensitiveCurve (aSensitiveOwner, aSensitivePnts));
1234 Quantity_Length anArrowLength = myDrawer->DimensionAspect()->ArrowAspect()->Length();
1235 Standard_Real anArrowAngle = myDrawer->DimensionAspect()->ArrowAspect()->Angle();
1237 // sensitives for arrows
1238 SelectionGeometry::SeqOfArrows::Iterator anArrowIt (mySelectionGeom.Arrows);
1239 for (; anArrowIt.More(); anArrowIt.Next())
1241 const SelectionGeometry::HArrow& anArrow = anArrowIt.Value();
1243 gp_Pnt aSidePnt1 (gp::Origin());
1244 gp_Pnt aSidePnt2 (gp::Origin());
1245 const gp_Dir& aPlane = GetPlane().Axis().Direction();
1246 const gp_Pnt& aPeak = anArrow->Position;
1247 const gp_Dir& aDir = anArrow->Direction;
1249 // compute points for arrow in plane
1250 PointsForArrow (aPeak, aDir, aPlane, anArrowLength, anArrowAngle, aSidePnt1, aSidePnt2);
1252 aGroupOfSensitives->Add (new Select3D_SensitiveTriangle (aSensitiveOwner, aPeak, aSidePnt1, aSidePnt2));
1254 if (!myDrawer->DimensionAspect()->IsArrows3d())
1259 // compute points for orthogonal sensitive plane
1260 gp_Dir anOrthoPlane = anArrow->Direction.Crossed (aPlane);
1262 PointsForArrow (aPeak, aDir, anOrthoPlane, anArrowLength, anArrowAngle, aSidePnt1, aSidePnt2);
1264 aGroupOfSensitives->Add (new Select3D_SensitiveTriangle (aSensitiveOwner, aPeak, aSidePnt1, aSidePnt2));
1267 theSelection->Add (aGroupOfSensitives);
1270 // sensitives for text element
1271 if (aSelectionMode == AIS_DSM_All || aSelectionMode == AIS_DSM_Text)
1273 Handle(Select3D_SensitiveEntity) aTextSensitive;
1275 gp_Ax2 aTextAxes (mySelectionGeom.TextPos,
1276 GetPlane().Axis().Direction(),
1277 mySelectionGeom.TextDir);
1279 if (myDrawer->DimensionAspect()->IsText3d())
1281 // sensitive planar rectangle for text
1282 Standard_Real aDx = mySelectionGeom.TextWidth * 0.5;
1283 Standard_Real aDy = mySelectionGeom.TextHeight * 0.5;
1285 gp_Trsf aLabelPlane;
1286 aLabelPlane.SetTransformation (aTextAxes, gp::XOY());
1288 TColgp_Array1OfPnt aRectanglePoints(1, 4);
1289 aRectanglePoints.ChangeValue(1) = gp_Pnt (-aDx, -aDy, 0.0).Transformed (aLabelPlane);
1290 aRectanglePoints.ChangeValue(2) = gp_Pnt (-aDx, aDy, 0.0).Transformed (aLabelPlane);
1291 aRectanglePoints.ChangeValue(3) = gp_Pnt ( aDx, aDy, 0.0).Transformed (aLabelPlane);
1292 aRectanglePoints.ChangeValue(4) = gp_Pnt ( aDx, -aDy, 0.0).Transformed (aLabelPlane);
1294 Poly_Array1OfTriangle aTriangles(1, 2);
1295 aTriangles.ChangeValue(1) = Poly_Triangle(1, 2, 3);
1296 aTriangles.ChangeValue(2) = Poly_Triangle(1, 3, 4);
1298 Handle(Poly_Triangulation) aRectanglePoly =
1299 new Poly_Triangulation(aRectanglePoints, aTriangles);
1302 new Select3D_SensitiveTriangulation (aSensitiveOwner, aRectanglePoly, TopLoc_Location(), Standard_True);
1306 gp_Circ aTextGeom (aTextAxes, mySelToleranceForText2d != 0.0
1307 ? mySelToleranceForText2d : 1.0);
1309 Handle(Geom_Circle) aSensGeom = new Geom_Circle (aTextGeom);
1311 aTextSensitive = new Select3D_SensitiveCircle (aSensitiveOwner, aSensGeom, Standard_True);
1314 theSelection->Add (aTextSensitive);
1317 // callback for flyout sensitive calculation
1318 if (aSelectionMode == AIS_DSM_All)
1320 ComputeFlyoutSelection (theSelection, aSensitiveOwner);
1324 //=======================================================================
1325 //function : PointsForArrow
1327 //=======================================================================
1328 void AIS_Dimension::PointsForArrow (const gp_Pnt& thePeakPnt,
1329 const gp_Dir& theDirection,
1330 const gp_Dir& thePlane,
1331 const Standard_Real theArrowLength,
1332 const Standard_Real theArrowAngle,
1333 gp_Pnt& theSidePnt1,
1334 gp_Pnt& theSidePnt2)
1336 gp_Lin anArrowLin (thePeakPnt, theDirection.Reversed());
1337 gp_Pnt anArrowEnd = ElCLib::Value (theArrowLength, anArrowLin);
1338 gp_Lin anEdgeLin (anArrowEnd, theDirection.Crossed (thePlane));
1340 Standard_Real anEdgeLength = Tan (theArrowAngle) * theArrowLength;
1342 theSidePnt1 = ElCLib::Value ( anEdgeLength, anEdgeLin);
1343 theSidePnt2 = ElCLib::Value (-anEdgeLength, anEdgeLin);
1346 //=======================================================================
1347 //function : GetTextPositionForLinear
1349 //=======================================================================
1350 gp_Pnt AIS_Dimension::GetTextPositionForLinear (const gp_Pnt& theFirstPoint,
1351 const gp_Pnt& theSecondPoint,
1352 const Standard_Boolean theIsOneSide) const
1356 return gp::Origin();
1359 gp_Pnt aTextPosition (gp::Origin());
1361 Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
1363 // Get label alignment and arrow orientation.
1364 Standard_Integer aLabelPosition = 0;
1365 Standard_Boolean isArrowsExternal = Standard_False;
1366 FitTextAlignmentForLinear (theFirstPoint, theSecondPoint, theIsOneSide,
1367 aDimensionAspect->TextHorizontalPosition(),
1368 aLabelPosition, isArrowsExternal);
1370 // Compute dimension line points.
1371 gp_Dir aPlaneNormal = GetPlane().Axis().Direction();
1372 gp_Vec aTargetPointsVec (theFirstPoint, theSecondPoint);
1374 // Compute flyout direction vector
1375 gp_Dir aFlyoutVector = aPlaneNormal ^ gp_Dir (aTargetPointsVec);
1377 // create lines for layouts
1378 gp_Lin aLine1 (theFirstPoint, aFlyoutVector);
1379 gp_Lin aLine2 (theSecondPoint, aFlyoutVector);
1380 // Get flyout end points
1381 gp_Pnt aLineBegPoint = ElCLib::Value (ElCLib::Parameter (aLine1, theFirstPoint) + GetFlyout(), aLine1);
1382 gp_Pnt aLineEndPoint = ElCLib::Value (ElCLib::Parameter (aLine2, theSecondPoint) + GetFlyout(), aLine2);
1384 // Get text position.
1385 switch (aLabelPosition & LabelPosition_HMask)
1387 case LabelPosition_Left:
1389 gp_Dir aTargetPointsDir = gce_MakeDir (theFirstPoint, theSecondPoint);
1390 Standard_Real anExtensionSize = aDimensionAspect->ExtensionSize();
1392 Standard_Real anOffset = isArrowsExternal
1393 ? anExtensionSize + aDimensionAspect->ArrowAspect()->Length()
1395 gp_Vec anExtensionVec = gp_Vec (aTargetPointsDir) * -anOffset;
1396 aTextPosition = aLineEndPoint.Translated (anExtensionVec);
1399 case LabelPosition_Right:
1401 gp_Dir aTargetPointsDir = gce_MakeDir (theFirstPoint, theSecondPoint);
1402 Standard_Real anExtensionSize = aDimensionAspect->ExtensionSize();
1404 Standard_Real anOffset = isArrowsExternal
1405 ? anExtensionSize + aDimensionAspect->ArrowAspect()->Length()
1407 gp_Vec anExtensionVec = gp_Vec (aTargetPointsDir) * anOffset;
1408 aTextPosition = aLineBegPoint.Translated (anExtensionVec);
1411 case LabelPosition_HCenter:
1413 aTextPosition = (aLineBegPoint.XYZ() + aLineEndPoint.XYZ()) * 0.5;
1418 return aTextPosition;
1421 //=======================================================================
1422 //function : AdjustParametersForLinear
1424 //=======================================================================
1425 Standard_Boolean AIS_Dimension::AdjustParametersForLinear (const gp_Pnt& theTextPos,
1426 const gp_Pnt& theFirstPoint,
1427 const gp_Pnt& theSecondPoint,
1428 Standard_Real& theExtensionSize,
1429 Prs3d_DimensionTextHorizontalPosition& theAlignment,
1430 Standard_Real& theFlyout,
1432 Standard_Boolean& theIsPlaneOld) const
1434 Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
1435 Standard_Real anArrowLength = aDimensionAspect->ArrowAspect()->Length();
1437 gp_Dir aTargetPointsDir = gce_MakeDir (theFirstPoint, theSecondPoint);
1438 gp_Vec aTargetPointsVec (theFirstPoint, theSecondPoint);
1440 // Don't set new plane if the text position lies on the attachment points line.
1441 gp_Lin aTargetPointsLin (theFirstPoint, aTargetPointsDir);
1442 if (!aTargetPointsLin.Contains (theTextPos, Precision::Confusion()))
1444 //Set new automatic plane.
1445 thePlane = gce_MakePln (theTextPos, theFirstPoint, theSecondPoint);
1446 theIsPlaneOld = Standard_False;
1449 // Compute flyout direction vector.
1450 gp_Dir aPlaneNormal = GetPlane().Axis().Direction();
1451 gp_Dir aPositiveFlyout = aPlaneNormal ^ aTargetPointsDir;
1453 // Additional check of collinearity of the plane normal and attachment points vector.
1454 if (aPlaneNormal.IsParallel (aTargetPointsDir, Precision::Angular()))
1456 return Standard_False;
1460 gp_Vec aFirstToTextVec (theFirstPoint, theTextPos);
1462 Standard_Real aCos = aFirstToTextVec.Normalized() * gp_Vec (aTargetPointsDir);
1464 gp_Pnt aTextPosProj = theFirstPoint.Translated
1465 (gp_Vec (aTargetPointsDir) * aFirstToTextVec.Magnitude() * aCos);
1467 // Compute flyout value and direction.
1468 gp_Vec aFlyoutVector = gp_Vec (aTextPosProj, theTextPos);
1471 if (aFlyoutVector.Magnitude() > Precision::Confusion())
1473 theFlyout = gp_Dir (aFlyoutVector).IsOpposite (aPositiveFlyout, Precision::Angular())
1474 ? -aFlyoutVector.Magnitude()
1475 : aFlyoutVector.Magnitude();
1478 // Compute attach points (through which main dimension line passes).
1479 gp_Pnt aFirstAttach = theFirstPoint.Translated (aFlyoutVector);
1480 gp_Pnt aSecondAttach = theSecondPoint.Translated (aFlyoutVector);
1482 // Set horizontal text alignment.
1485 theAlignment = Prs3d_DTHP_Left;
1487 Standard_Real aNewExtSize = theTextPos.Distance (aFirstAttach) - anArrowLength;
1488 theExtensionSize = aNewExtSize < 0.0 ? 0.0 : aNewExtSize;
1490 else if (aTextPosProj.Distance (theFirstPoint) > theFirstPoint.Distance (theSecondPoint))
1492 theAlignment = Prs3d_DTHP_Right;
1494 Standard_Real aNewExtSize = theTextPos.Distance (aSecondAttach) - anArrowLength;
1495 theExtensionSize = aNewExtSize < 0.0 ? 0.0 : aNewExtSize;
1499 theAlignment = Prs3d_DTHP_Center;
1501 return Standard_True;
1504 //=======================================================================
1505 //function : FitTextAlignmentForLinear
1507 //=======================================================================
1508 void AIS_Dimension::FitTextAlignmentForLinear (const gp_Pnt& theFirstPoint,
1509 const gp_Pnt& theSecondPoint,
1510 const Standard_Boolean theIsOneSide,
1511 const Prs3d_DimensionTextHorizontalPosition& theHorizontalTextPos,
1512 Standard_Integer& theLabelPosition,
1513 Standard_Boolean& theIsArrowsExternal) const
1515 theLabelPosition = LabelPosition_None;
1516 theIsArrowsExternal = Standard_False;
1518 // Compute dimension line points
1519 gp_Ax1 aPlaneNormal = GetPlane().Axis();
1520 gp_Dir aTargetPointsVector = gce_MakeDir (theFirstPoint, theSecondPoint);
1522 // compute flyout direction vector
1523 gp_Dir aFlyoutVector = aPlaneNormal.Direction() ^ aTargetPointsVector;
1525 // create lines for layouts
1526 gp_Lin aLine1 (theFirstPoint, aFlyoutVector);
1527 gp_Lin aLine2 (theSecondPoint, aFlyoutVector);
1529 // Get flyout end points
1530 gp_Pnt aLineBegPoint = ElCLib::Value (ElCLib::Parameter (aLine1, theFirstPoint) + GetFlyout(), aLine1);
1531 gp_Pnt aLineEndPoint = ElCLib::Value (ElCLib::Parameter (aLine2, theSecondPoint) + GetFlyout(), aLine2);
1533 Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
1535 gp_Lin aDimensionLine = gce_MakeLin (aLineBegPoint, aLineEndPoint);
1537 // For extensions we need to know arrow size, text size and extension size: get it from aspect
1538 Quantity_Length anArrowLength = aDimensionAspect->ArrowAspect()->Length();
1540 // prepare label string and compute its geometrical width
1541 Standard_Real aLabelWidth;
1542 TCollection_ExtendedString aLabelString = GetValueString (aLabelWidth);
1544 // Add margins to cut dimension lines for 3d text
1545 if (aDimensionAspect->IsText3d())
1547 aLabelWidth += aDimensionAspect->TextAspect()->Height() * THE_3D_TEXT_MARGIN * 2.0;
1550 // Handle user-defined and automatic arrow placement
1551 switch (aDimensionAspect->ArrowOrientation())
1553 case Prs3d_DAO_External: theIsArrowsExternal = true; break;
1554 case Prs3d_DAO_Internal: theIsArrowsExternal = false; break;
1557 // Add margin to ensure a small tail between text and arrow
1558 Standard_Real anArrowMargin = aDimensionAspect->IsText3d()
1559 ? aDimensionAspect->TextAspect()->Height() * THE_3D_TEXT_MARGIN
1562 Standard_Real aDimensionWidth = aLineBegPoint.Distance (aLineEndPoint);
1563 Standard_Real anArrowsWidth = theIsOneSide
1564 ? anArrowLength + anArrowMargin
1565 : (anArrowLength + anArrowMargin) * 2.0;
1567 theIsArrowsExternal = aDimensionWidth < aLabelWidth + anArrowsWidth;
1572 // Handle user-defined and automatic text placement
1573 switch (theHorizontalTextPos)
1575 case Prs3d_DTHP_Left : theLabelPosition |= LabelPosition_Left; break;
1576 case Prs3d_DTHP_Right : theLabelPosition |= LabelPosition_Right; break;
1577 case Prs3d_DTHP_Center: theLabelPosition |= LabelPosition_HCenter; break;
1578 case Prs3d_DTHP_Fit:
1580 Standard_Real aDimensionWidth = aLineBegPoint.Distance (aLineEndPoint);
1581 Standard_Real anArrowsWidth = theIsOneSide ? anArrowLength : 2.0 * anArrowLength;
1582 Standard_Real aContentWidth = theIsArrowsExternal ? aLabelWidth : aLabelWidth + anArrowsWidth;
1584 theLabelPosition |= aDimensionWidth < aContentWidth ? LabelPosition_Left : LabelPosition_HCenter;
1589 // Handle vertical text placement options
1590 switch (aDimensionAspect->TextVerticalPosition())
1592 case Prs3d_DTVP_Above : theLabelPosition |= LabelPosition_Above; break;
1593 case Prs3d_DTVP_Below : theLabelPosition |= LabelPosition_Below; break;
1594 case Prs3d_DTVP_Center : theLabelPosition |= LabelPosition_VCenter; break;
1598 //=======================================================================
1599 //function : UnsetFixedTextPosition
1601 //=======================================================================
1602 void AIS_Dimension::UnsetFixedTextPosition()
1604 myIsTextPositionFixed = Standard_False;
1605 myFixedTextPosition = gp::Origin();