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 <Font_BRepTextBuilder.hxx>
28 #include <GC_MakeCircle.hxx>
29 #include <Geom_Line.hxx>
30 #include <GeomAdaptor_Curve.hxx>
31 #include <Geom_Circle.hxx>
32 #include <Geom_TrimmedCurve.hxx>
33 #include <gce_MakeDir.hxx>
34 #include <gce_MakeLin.hxx>
35 #include <gce_MakePln.hxx>
36 #include <Graphic3d_ArrayOfSegments.hxx>
37 #include <Graphic3d_ArrayOfTriangles.hxx>
38 #include <Graphic3d_AspectLine3d.hxx>
39 #include <Graphic3d_AspectFillArea3d.hxx>
40 #include <Graphic3d_AspectText3d.hxx>
41 #include <Graphic3d_Group.hxx>
42 #include <PrsMgr_PresentationManager3d.hxx>
43 #include <Prs3d_Arrow.hxx>
44 #include <Prs3d_ArrowAspect.hxx>
45 #include <Prs3d_Drawer.hxx>
46 #include <Prs3d_LineAspect.hxx>
47 #include <Prs3d_Presentation.hxx>
48 #include <Prs3d_Root.hxx>
49 #include <Prs3d_ShadingAspect.hxx>
50 #include <Prs3d_Text.hxx>
51 #include <SelectMgr_EntityOwner.hxx>
52 #include <SelectMgr_Selection.hxx>
53 #include <SelectMgr_SequenceOfOwner.hxx>
54 #include <Select3D_SensitiveCircle.hxx>
55 #include <Select3D_SensitiveGroup.hxx>
56 #include <Select3D_SensitiveCurve.hxx>
57 #include <Select3D_SensitiveSegment.hxx>
58 #include <Select3D_SensitiveTriangle.hxx>
59 #include <Select3D_SensitiveTriangulation.hxx>
60 #include <Poly_Array1OfTriangle.hxx>
61 #include <Poly_Triangulation.hxx>
62 #include <Standard_CString.hxx>
63 #include <Standard_ProgramError.hxx>
64 #include <StdPrs_ShadedShape.hxx>
65 #include <StdPrs_WFShape.hxx>
66 #include <TCollection_AsciiString.hxx>
67 #include <TCollection_ExtendedString.hxx>
68 #include <TopExp_Explorer.hxx>
70 #include <TopoDS_Edge.hxx>
71 #include <TopoDS_Vertex.hxx>
73 #include <Units_UnitsDictionary.hxx>
74 #include <UnitsAPI.hxx>
75 #include <UnitsAPI_SystemUnits.hxx>
78 IMPLEMENT_STANDARD_RTTIEXT(AIS_Dimension,AIS_InteractiveObject)
82 // default text strings
83 static const TCollection_ExtendedString THE_EMPTY_LABEL;
84 static const TCollection_AsciiString THE_UNDEFINED_UNITS;
86 // default text margin and resolution
87 static const Standard_Real THE_3D_TEXT_MARGIN = 0.1;
88 static const unsigned int THE_2D_TEXT_RESOLUTION = 72;
90 // default selection priorities
91 static const Standard_Integer THE_NEUTRAL_SEL_PRIORITY = 5;
92 static const Standard_Integer THE_LOCAL_SEL_PRIORITY = 6;
95 //=======================================================================
96 //function : Constructor
98 //=======================================================================
99 AIS_Dimension::AIS_Dimension (const AIS_KindOfDimension theType)
100 : AIS_InteractiveObject (),
101 mySelToleranceForText2d(0.0),
102 myValueType (ValueType_Computed),
104 myCustomStringValue (),
105 myIsTextPositionFixed (Standard_False),
106 mySpecialSymbol (' '),
107 myDisplaySpecialSymbol (AIS_DSS_No),
108 myGeometryType (GeometryType_UndefShapes),
109 myIsPlaneCustom (Standard_False),
111 myIsGeometryValid (Standard_False),
112 myKindOfDimension (theType)
116 //=======================================================================
117 //function : SetCustomValue
119 //=======================================================================
120 void AIS_Dimension::SetCustomValue (const Standard_Real theValue)
122 if (myValueType == ValueType_CustomReal && myCustomValue == theValue)
127 myValueType = ValueType_CustomReal;
128 myCustomValue = theValue;
133 //=======================================================================
134 //function : SetCustomValue
136 //=======================================================================
137 void AIS_Dimension::SetCustomValue (const TCollection_ExtendedString& theValue)
139 if (myValueType == ValueType_CustomText && myCustomStringValue == theValue)
144 myValueType = ValueType_CustomText;
145 myCustomStringValue = theValue;
150 //=======================================================================
151 //function : GetCustomValue
153 //=======================================================================
154 const TCollection_ExtendedString& AIS_Dimension::GetCustomValue () const
156 return myCustomStringValue;
159 //=======================================================================
160 //function : GetPlane
162 //=======================================================================
163 const gp_Pln& AIS_Dimension::GetPlane() const
168 //=======================================================================
169 //function : SetUserPlane
171 //=======================================================================
172 void AIS_Dimension::SetCustomPlane (const gp_Pln& thePlane)
175 myIsPlaneCustom = Standard_True;
177 // Disable fixed (custom) text position
178 UnsetFixedTextPosition();
180 // Check validity if geometry has been set already.
187 //=======================================================================
188 //function : SetDimensionAspect
190 //=======================================================================
191 void AIS_Dimension::SetDimensionAspect (const Handle(Prs3d_DimensionAspect)& theDimensionAspect)
193 myDrawer->SetDimensionAspect (theDimensionAspect);
198 //=======================================================================
199 //function : SetDisplaySpecialSymbol
201 //=======================================================================
202 void AIS_Dimension::SetDisplaySpecialSymbol (const AIS_DisplaySpecialSymbol theDisplaySpecSymbol)
204 if (myDisplaySpecialSymbol == theDisplaySpecSymbol)
209 myDisplaySpecialSymbol = theDisplaySpecSymbol;
214 //=======================================================================
215 //function : SetSpecialSymbol
217 //=======================================================================
218 void AIS_Dimension::SetSpecialSymbol (const Standard_ExtCharacter theSpecialSymbol)
220 if (mySpecialSymbol == theSpecialSymbol)
225 mySpecialSymbol = theSpecialSymbol;
230 //=======================================================================
231 //function : SetSelToleranceForText2d
233 //=======================================================================
234 void AIS_Dimension::SetSelToleranceForText2d (const Standard_Real theTol)
236 if (mySelToleranceForText2d == theTol)
241 mySelToleranceForText2d = theTol;
246 //=======================================================================
247 //function : SetFlyout
249 //=======================================================================
250 void AIS_Dimension::SetFlyout (const Standard_Real theFlyout)
252 if (myFlyout == theFlyout)
257 myFlyout = theFlyout;
259 // Disable fixed text position
260 UnsetFixedTextPosition();
265 //=======================================================================
266 //function : GetDisplayUnits
268 //=======================================================================
269 const TCollection_AsciiString& AIS_Dimension::GetDisplayUnits() const
271 return THE_UNDEFINED_UNITS;
274 //=======================================================================
275 //function : GetModelUnits
277 //=======================================================================
278 const TCollection_AsciiString& AIS_Dimension::GetModelUnits() const
280 return THE_UNDEFINED_UNITS;
283 //=======================================================================
284 //function : ValueToDisplayUnits
286 //=======================================================================
287 Standard_Real AIS_Dimension::ValueToDisplayUnits() const
289 return UnitsAPI::AnyToAny (GetValue(),
290 GetModelUnits().ToCString(),
291 GetDisplayUnits().ToCString());
294 //=======================================================================
295 //function : GetValueString
297 //=======================================================================
298 TCollection_ExtendedString AIS_Dimension::GetValueString (Standard_Real& theWidth) const
300 TCollection_ExtendedString aValueStr;
301 if (myValueType == ValueType_CustomText)
303 aValueStr = myCustomStringValue;
307 // format value string using "sprintf"
308 TCollection_AsciiString aFormatStr = myDrawer->DimensionAspect()->ValueStringFormat();
310 char aFmtBuffer[256];
311 sprintf (aFmtBuffer, aFormatStr.ToCString(), ValueToDisplayUnits());
312 aValueStr = TCollection_ExtendedString (aFmtBuffer);
315 // add units to values string
316 if (myDrawer->DimensionAspect()->IsUnitsDisplayed())
319 aValueStr += TCollection_ExtendedString (GetDisplayUnits());
322 switch (myDisplaySpecialSymbol)
324 case AIS_DSS_Before : aValueStr.Insert (1, mySpecialSymbol); break;
325 case AIS_DSS_After : aValueStr.Insert (aValueStr.Length() + 1, mySpecialSymbol); break;
326 case AIS_DSS_No : break;
329 // Get text style parameters
330 Handle(Prs3d_TextAspect) aTextAspect = myDrawer->DimensionAspect()->TextAspect();
331 NCollection_Utf8String anUTFString (aValueStr.ToExtString());
335 if (myDrawer->DimensionAspect()->IsText3d())
337 // text width produced by BRepFont
338 Font_BRepFont aFont (aTextAspect->Aspect()->Font().ToCString(),
339 aTextAspect->Aspect()->GetTextFontAspect(),
340 aTextAspect->Height());
342 for (NCollection_Utf8Iter anIter = anUTFString.Iterator(); *anIter != 0; )
344 Standard_Utf32Char aCurrChar = *anIter;
345 Standard_Utf32Char aNextChar = *(++anIter);
346 theWidth += aFont.AdvanceX (aCurrChar, aNextChar);
351 // Text width for 1:1 scale 2D case
352 Handle(Font_FTFont) aFont = new Font_FTFont();
353 aFont->Init (aTextAspect->Aspect()->Font().ToCString(),
354 aTextAspect->Aspect()->GetTextFontAspect(),
355 (const unsigned int)aTextAspect->Height(),
356 THE_2D_TEXT_RESOLUTION);
358 for (NCollection_Utf8Iter anIter = anUTFString.Iterator(); *anIter != 0; )
360 Standard_Utf32Char aCurrChar = *anIter;
361 Standard_Utf32Char aNextChar = *(++anIter);
362 theWidth += (Standard_Real) aFont->AdvanceX (aCurrChar, aNextChar);
369 //=======================================================================
370 //function : DrawArrow
372 //=======================================================================
373 void AIS_Dimension::DrawArrow (const Handle(Prs3d_Presentation)& thePresentation,
374 const gp_Pnt& theLocation,
375 const gp_Dir& theDirection)
377 Handle(Graphic3d_Group) aGroup = Prs3d_Root::NewGroup (thePresentation);
379 Quantity_Length aLength = myDrawer->DimensionAspect()->ArrowAspect()->Length();
380 Standard_Real anAngle = myDrawer->DimensionAspect()->ArrowAspect()->Angle();
382 if (myDrawer->DimensionAspect()->IsArrows3d())
384 Prs3d_Arrow::Draw (aGroup,
389 aGroup->SetGroupPrimitivesAspect (myDrawer->DimensionAspect()->ArrowAspect()->Aspect());
393 gp_Pnt aLeftPoint (gp::Origin());
394 gp_Pnt aRightPoint (gp::Origin());
395 const gp_Dir& aPlane = GetPlane().Axis().Direction();
397 PointsForArrow (theLocation, theDirection, aPlane, aLength, anAngle, aLeftPoint, aRightPoint);
399 Handle(Graphic3d_ArrayOfTriangles) anArrow = new Graphic3d_ArrayOfTriangles(3);
401 anArrow->AddVertex (aLeftPoint);
402 anArrow->AddVertex (theLocation);
403 anArrow->AddVertex (aRightPoint);
405 // Set aspect for arrow triangles
406 Graphic3d_MaterialAspect aShadeMat (Graphic3d_NOM_DEFAULT);
407 aShadeMat.SetReflectionModeOff (Graphic3d_TOR_AMBIENT);
408 aShadeMat.SetReflectionModeOff (Graphic3d_TOR_DIFFUSE);
409 aShadeMat.SetReflectionModeOff (Graphic3d_TOR_SPECULAR);
411 Handle(Prs3d_ShadingAspect) aShadingStyle = new Prs3d_ShadingAspect();
412 aShadingStyle->SetColor (myDrawer->DimensionAspect()->ArrowAspect()->Aspect()->Color());
413 aShadingStyle->SetMaterial (aShadeMat);
415 aGroup->SetPrimitivesAspect (aShadingStyle->Aspect());
416 aGroup->AddPrimitiveArray (anArrow);
419 SelectionGeometry::Arrow& aSensitiveArrow = mySelectionGeom.NewArrow();
420 aSensitiveArrow.Position = theLocation;
421 aSensitiveArrow.Direction = theDirection;
424 //=======================================================================
425 //function : drawText
427 //=======================================================================
428 void AIS_Dimension::drawText (const Handle(Prs3d_Presentation)& thePresentation,
429 const gp_Pnt& theTextPos,
430 const gp_Dir& theTextDir,
431 const TCollection_ExtendedString& theText,
432 const Standard_Integer theLabelPosition)
434 if (myDrawer->DimensionAspect()->IsText3d())
436 // getting font parameters
437 Handle(Prs3d_TextAspect) aTextAspect = myDrawer->DimensionAspect()->TextAspect();
438 Quantity_Color aColor = aTextAspect->Aspect()->Color();
439 Font_FontAspect aFontAspect = aTextAspect->Aspect()->GetTextFontAspect();
440 Standard_Real aFontHeight = aTextAspect->Height();
442 // creating TopoDS_Shape for text
443 Font_BRepFont aFont (aTextAspect->Aspect()->Font().ToCString(),
444 aFontAspect, aFontHeight);
445 NCollection_Utf8String anUTFString (theText.ToExtString());
447 Font_BRepTextBuilder aBuilder;
448 TopoDS_Shape aTextShape = aBuilder.Perform (aFont, anUTFString);
450 // compute text width with kerning
451 Standard_Real aTextWidth = 0.0;
452 Standard_Real aTextHeight = aFont.Ascender() + aFont.Descender();
454 for (NCollection_Utf8Iter anIter = anUTFString.Iterator(); *anIter != 0; )
456 Standard_Utf32Char aCurrChar = *anIter;
457 Standard_Utf32Char aNextChar = *(++anIter);
458 aTextWidth += aFont.AdvanceX (aCurrChar, aNextChar);
461 // formating text position in XOY plane
462 Standard_Integer aHLabelPos = theLabelPosition & LabelPosition_HMask;
463 Standard_Integer aVLabelPos = theLabelPosition & LabelPosition_VMask;
465 gp_Dir aTextDir (aHLabelPos == LabelPosition_Left ? -theTextDir : theTextDir);
467 // compute label offsets
468 Standard_Real aMarginSize = aFontHeight * THE_3D_TEXT_MARGIN;
469 Standard_Real aCenterHOffset = 0.0;
470 Standard_Real aCenterVOffset = 0.0;
473 case LabelPosition_HCenter : aCenterHOffset = 0.0; break;
474 case LabelPosition_Right : aCenterHOffset = aTextWidth / 2.0 + aMarginSize; break;
475 case LabelPosition_Left : aCenterHOffset = -aTextWidth / 2.0 - aMarginSize; break;
479 case LabelPosition_VCenter : aCenterVOffset = 0.0; break;
480 case LabelPosition_Above : aCenterVOffset = aTextHeight / 2.0 + aMarginSize; break;
481 case LabelPosition_Below : aCenterVOffset = -aTextHeight / 2.0 - aMarginSize; break;
484 // compute shape offset transformation
485 Standard_Real aShapeHOffset = aCenterHOffset - aTextWidth / 2.0;
486 Standard_Real aShapeVOffset = aCenterVOffset - aTextHeight / 2.0;
488 // center shape in its bounding box (suppress border spacing added by FT_Font)
490 BRepBndLib::AddClose (aTextShape, aShapeBnd);
492 Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
493 aShapeBnd.Get (aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
495 Standard_Real aXalign = aTextWidth * 0.5 - (aXmax + aXmin) * 0.5;
496 Standard_Real aYalign = aTextHeight * 0.5 - (aYmax + aYmin) * 0.5;
497 aShapeHOffset += aXalign;
498 aShapeVOffset += aYalign;
500 gp_Trsf anOffsetTrsf;
501 anOffsetTrsf.SetTranslation (gp::Origin(), gp_Pnt (aShapeHOffset, aShapeVOffset, 0.0));
502 aTextShape.Move (anOffsetTrsf);
504 // transform text to myWorkingPlane coordinate system
505 gp_Ax3 aTextCoordSystem (theTextPos, GetPlane().Axis().Direction(), aTextDir);
506 gp_Trsf aTextPlaneTrsf;
507 aTextPlaneTrsf.SetTransformation (aTextCoordSystem, gp_Ax3 (gp::XOY()));
508 aTextShape.Move (aTextPlaneTrsf);
510 // set text flipping anchors
511 gp_Trsf aCenterOffsetTrsf;
512 gp_Pnt aCenterOffset (aCenterHOffset, aCenterVOffset, 0.0);
513 aCenterOffsetTrsf.SetTranslation (gp::Origin(), aCenterOffset);
515 gp_Pnt aCenterOfLabel (gp::Origin());
516 aCenterOfLabel.Transform (aCenterOffsetTrsf);
517 aCenterOfLabel.Transform (aTextPlaneTrsf);
519 gp_Ax2 aFlippingAxes (aCenterOfLabel, GetPlane().Axis().Direction(), aTextDir);
520 Prs3d_Root::CurrentGroup (thePresentation)->SetFlippingOptions (Standard_True, aFlippingAxes);
523 if (myDrawer->DimensionAspect()->IsTextShaded())
525 // Setting text shading and color parameters
526 if (!myDrawer->HasOwnShadingAspect())
528 myDrawer->SetShadingAspect (new Prs3d_ShadingAspect());
531 Graphic3d_MaterialAspect aShadeMat (Graphic3d_NOM_DEFAULT);
532 aShadeMat.SetReflectionModeOff (Graphic3d_TOR_AMBIENT);
533 aShadeMat.SetReflectionModeOff (Graphic3d_TOR_DIFFUSE);
534 aShadeMat.SetReflectionModeOff (Graphic3d_TOR_SPECULAR);
535 myDrawer->ShadingAspect()->Aspect()->SetInteriorColor (aColor);
536 myDrawer->ShadingAspect()->Aspect()->SetBackInteriorColor (aColor);
537 myDrawer->ShadingAspect()->SetMaterial (aShadeMat);
540 StdPrs_ShadedShape::Add (thePresentation, aTextShape, myDrawer);
544 // Setting color for text
545 if (!myDrawer->HasOwnFreeBoundaryAspect())
547 myDrawer->SetFreeBoundaryAspect (new Prs3d_LineAspect (aColor, Aspect_TOL_SOLID, 1.0));
550 myDrawer->FreeBoundaryAspect()->Aspect()->SetColor (aColor);
553 StdPrs_WFShape::Add (thePresentation, aTextShape, myDrawer);
555 Prs3d_Root::CurrentGroup (thePresentation)->SetFlippingOptions (Standard_False, gp_Ax2());
557 mySelectionGeom.TextPos = aCenterOfLabel;
558 mySelectionGeom.TextDir = aTextDir;
559 mySelectionGeom.TextWidth = aTextWidth + aMarginSize * 2.0;
560 mySelectionGeom.TextHeight = aTextHeight;
565 // generate primitives for 2D text
566 myDrawer->DimensionAspect()->TextAspect()->Aspect()->SetDisplayType (Aspect_TODT_DIMENSION);
568 Prs3d_Text::Draw (Prs3d_Root::CurrentGroup (thePresentation),
569 myDrawer->DimensionAspect()->TextAspect(),
573 mySelectionGeom.TextPos = theTextPos;
574 mySelectionGeom.TextDir = theTextDir;
575 mySelectionGeom.TextWidth = 0.0;
576 mySelectionGeom.TextHeight = 0.0;
579 //=======================================================================
580 //function : DrawExtension
582 //=======================================================================
583 void AIS_Dimension::DrawExtension (const Handle(Prs3d_Presentation)& thePresentation,
584 const Standard_Real theExtensionSize,
585 const gp_Pnt& theExtensionStart,
586 const gp_Dir& theExtensionDir,
587 const TCollection_ExtendedString& theLabelString,
588 const Standard_Real theLabelWidth,
589 const Standard_Integer theMode,
590 const Standard_Integer theLabelPosition)
592 // reference line for extension starting at its connection point
593 gp_Lin anExtensionLine (theExtensionStart, theExtensionDir);
595 Standard_Boolean hasLabel = theLabelString.Length() > 0;
596 if (hasLabel && (theMode == ComputeMode_All || theMode == ComputeMode_Text))
598 // compute text primitives; get its model width
599 gp_Pnt aTextPos = ElCLib::Value (theExtensionSize, anExtensionLine);
600 gp_Dir aTextDir = theExtensionDir;
602 drawText (thePresentation,
609 if (theMode != ComputeMode_All && theMode != ComputeMode_Line)
614 Standard_Boolean isShortLine = !myDrawer->DimensionAspect()->IsText3d()
615 || theLabelPosition & LabelPosition_VCenter;
617 // compute graphical primitives and sensitives for extension line
618 gp_Pnt anExtStart = theExtensionStart;
619 gp_Pnt anExtEnd = !hasLabel || isShortLine
620 ? ElCLib::Value (theExtensionSize, anExtensionLine)
621 : ElCLib::Value (theExtensionSize + theLabelWidth, anExtensionLine);
623 // add graphical primitives
624 Handle(Graphic3d_ArrayOfSegments) anExtPrimitive = new Graphic3d_ArrayOfSegments (2);
625 anExtPrimitive->AddVertex (anExtStart);
626 anExtPrimitive->AddVertex (anExtEnd);
628 // add selection primitives
629 SelectionGeometry::Curve& aSensitiveCurve = mySelectionGeom.NewCurve();
630 aSensitiveCurve.Append (anExtStart);
631 aSensitiveCurve.Append (anExtEnd);
633 if (!myDrawer->DimensionAspect()->IsText3d() && theMode == ComputeMode_All)
635 Prs3d_Root::CurrentGroup (thePresentation)->SetStencilTestOptions (Standard_True);
637 Handle(Graphic3d_AspectLine3d) aDimensionLineStyle = myDrawer->DimensionAspect()->LineAspect()->Aspect();
638 Prs3d_Root::CurrentGroup (thePresentation)->SetPrimitivesAspect (aDimensionLineStyle);
639 Prs3d_Root::CurrentGroup (thePresentation)->AddPrimitiveArray (anExtPrimitive);
640 if (!myDrawer->DimensionAspect()->IsText3d() && theMode == ComputeMode_All)
642 Prs3d_Root::CurrentGroup (thePresentation)->SetStencilTestOptions (Standard_False);
646 //=======================================================================
647 //function : DrawLinearDimension
649 //=======================================================================
650 void AIS_Dimension::DrawLinearDimension (const Handle(Prs3d_Presentation)& thePresentation,
651 const Standard_Integer theMode,
652 const gp_Pnt& theFirstPoint,
653 const gp_Pnt& theSecondPoint,
654 const Standard_Boolean theIsOneSide)
656 // do not build any dimension for equal points
657 if (theFirstPoint.IsEqual (theSecondPoint, Precision::Confusion()))
659 Standard_ProgramError::Raise ("Can not build presentation for equal points.");
662 Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
664 // For extensions we need to know arrow size, text size and extension size: get it from aspect
665 Quantity_Length anArrowLength = aDimensionAspect->ArrowAspect()->Length();
666 Standard_Real anExtensionSize = aDimensionAspect->ExtensionSize();
667 // prepare label string and compute its geometrical width
668 Standard_Real aLabelWidth;
669 TCollection_ExtendedString aLabelString = GetValueString (aLabelWidth);
671 // add margins to cut dimension lines for 3d text
672 if (aDimensionAspect->IsText3d())
674 aLabelWidth += aDimensionAspect->TextAspect()->Height() * THE_3D_TEXT_MARGIN * 2.0;
677 // handle user-defined and automatic arrow placement
678 Standard_Boolean isArrowsExternal = Standard_False;
679 Standard_Integer aLabelPosition = LabelPosition_None;
681 Prs3d_DimensionTextHorizontalPosition aHorisontalTextPos = aDimensionAspect->TextHorizontalPosition();
682 if (IsTextPositionCustom())
684 if (!AdjustParametersForLinear (myFixedTextPosition, theFirstPoint, theSecondPoint,
685 anExtensionSize, aHorisontalTextPos, myFlyout, myPlane, myIsPlaneCustom))
687 Standard_ProgramError::Raise ("Can not adjust plane to the custom label position.");
691 FitTextAlignmentForLinear (theFirstPoint, theSecondPoint, theIsOneSide, aHorisontalTextPos,
692 aLabelPosition, isArrowsExternal);
694 // compute dimension line points
695 gp_Ax1 aPlaneNormal = GetPlane().Axis();
696 gp_Dir aTargetPointsVector = gce_MakeDir (theFirstPoint, theSecondPoint);
698 // compute flyout direction vector
699 gp_Dir aFlyoutVector = aPlaneNormal.Direction() ^ aTargetPointsVector;
701 // create lines for layouts
702 gp_Lin aLine1 (theFirstPoint, aFlyoutVector);
703 gp_Lin aLine2 (theSecondPoint, aFlyoutVector);
705 // Get flyout end points
706 gp_Pnt aLineBegPoint = ElCLib::Value (ElCLib::Parameter (aLine1, theFirstPoint) + GetFlyout(), aLine1);
707 gp_Pnt aLineEndPoint = ElCLib::Value (ElCLib::Parameter (aLine2, theSecondPoint) + GetFlyout(), aLine2);
709 gp_Lin aDimensionLine = gce_MakeLin (aLineBegPoint, aLineEndPoint);
711 // compute arrows positions and directions
712 gp_Dir aFirstArrowDir = aDimensionLine.Direction().Reversed();
713 gp_Dir aSecondArrowDir = aDimensionLine.Direction();
714 gp_Dir aFirstExtensionDir = aDimensionLine.Direction().Reversed();
715 gp_Dir aSecondExtensionDir = aDimensionLine.Direction();
717 gp_Pnt aFirstArrowBegin (0.0, 0.0, 0.0);
718 gp_Pnt aFirstArrowEnd (0.0, 0.0, 0.0);
719 gp_Pnt aSecondArrowBegin (0.0, 0.0, 0.0);
720 gp_Pnt aSecondArrowEnd (0.0, 0.0, 0.0);
722 if (isArrowsExternal)
724 aFirstArrowDir.Reverse();
725 aSecondArrowDir.Reverse();
728 aFirstArrowBegin = aLineBegPoint;
729 aSecondArrowBegin = aLineEndPoint;
730 aFirstArrowEnd = aLineBegPoint.Translated (-gp_Vec (aFirstArrowDir).Scaled (anArrowLength));
731 aSecondArrowEnd = aLineEndPoint.Translated (-gp_Vec (aSecondArrowDir).Scaled (anArrowLength));
733 gp_Pnt aCenterLineBegin = isArrowsExternal
734 ? aLineBegPoint : aFirstArrowEnd;
736 gp_Pnt aCenterLineEnd = isArrowsExternal || theIsOneSide
737 ? aLineEndPoint : aSecondArrowEnd;
740 switch (aLabelPosition & LabelPosition_HMask)
742 // ------------------------------------------------------------------------ //
744 // -------------------------------------------------------------------------//
745 case LabelPosition_HCenter:
747 // add label on dimension or extension line to presentation
748 Prs3d_Root::NewGroup (thePresentation);
750 gp_Pnt aTextPos = IsTextPositionCustom() ? myFixedTextPosition
751 : (aCenterLineBegin.XYZ() + aCenterLineEnd.XYZ()) * 0.5;
752 gp_Dir aTextDir = aDimensionLine.Direction();
754 // add text primitives
755 if (theMode == ComputeMode_All || theMode == ComputeMode_Text)
757 drawText (thePresentation,
764 // add dimension line primitives
765 if (theMode == ComputeMode_All || theMode == ComputeMode_Line)
767 Standard_Boolean isLineBreak = aDimensionAspect->TextVerticalPosition() == Prs3d_DTVP_Center
768 && aDimensionAspect->IsText3d();
770 Handle(Graphic3d_ArrayOfSegments) aPrimSegments = new Graphic3d_ArrayOfSegments (isLineBreak ? 4 : 2);
772 // compute continuous or sectioned main line segments
775 Standard_Real aPTextPosition = ElCLib::Parameter (aDimensionLine, aTextPos);
776 gp_Pnt aSection1Beg = aCenterLineBegin;
777 gp_Pnt aSection1End = ElCLib::Value (aPTextPosition - (aLabelWidth * 0.5), aDimensionLine);
778 gp_Pnt aSection2Beg = ElCLib::Value (aPTextPosition + (aLabelWidth * 0.5), aDimensionLine);
779 gp_Pnt aSection2End = aCenterLineEnd;
781 aPrimSegments->AddVertex (aSection1Beg);
782 aPrimSegments->AddVertex (aSection1End);
783 aPrimSegments->AddVertex (aSection2Beg);
784 aPrimSegments->AddVertex (aSection2End);
786 SelectionGeometry::Curve& aLeftSensitiveCurve = mySelectionGeom.NewCurve();
787 SelectionGeometry::Curve& aRightSensitiveCurve = mySelectionGeom.NewCurve();
788 aLeftSensitiveCurve.Append (aSection1Beg);
789 aLeftSensitiveCurve.Append (aSection1End);
790 aRightSensitiveCurve.Append (aSection2Beg);
791 aRightSensitiveCurve.Append (aSection2End);
795 aPrimSegments->AddVertex (aCenterLineBegin);
796 aPrimSegments->AddVertex (aCenterLineEnd);
798 SelectionGeometry::Curve& aSensitiveCurve = mySelectionGeom.NewCurve();
799 aSensitiveCurve.Append (aCenterLineBegin);
800 aSensitiveCurve.Append (aCenterLineEnd);
803 // set text label justification
804 Graphic3d_VerticalTextAlignment aTextJustificaton = Graphic3d_VTA_BOTTOM;
805 switch (aLabelPosition & LabelPosition_VMask)
807 case LabelPosition_Above :
808 case LabelPosition_VCenter : aTextJustificaton = Graphic3d_VTA_BOTTOM; break;
809 case LabelPosition_Below : aTextJustificaton = Graphic3d_VTA_TOP; break;
811 aDimensionAspect->TextAspect()->SetVerticalJustification (aTextJustificaton);
813 // main dimension line, short extension
814 if (!aDimensionAspect->IsText3d() && theMode == ComputeMode_All)
816 Prs3d_Root::CurrentGroup (thePresentation)->SetStencilTestOptions (Standard_True);
818 Prs3d_Root::CurrentGroup (thePresentation)->SetPrimitivesAspect (aDimensionAspect->LineAspect()->Aspect());
819 Prs3d_Root::CurrentGroup (thePresentation)->AddPrimitiveArray (aPrimSegments);
820 if (!aDimensionAspect->IsText3d() && theMode == ComputeMode_All)
822 Prs3d_Root::CurrentGroup (thePresentation)->SetStencilTestOptions (Standard_False);
825 // add arrows to presentation
826 Prs3d_Root::NewGroup (thePresentation);
828 DrawArrow (thePresentation, aFirstArrowBegin, aFirstArrowDir);
831 DrawArrow (thePresentation, aSecondArrowBegin, aSecondArrowDir);
834 if (!isArrowsExternal)
839 // add arrow extension lines to presentation
840 Prs3d_Root::NewGroup (thePresentation);
842 DrawExtension (thePresentation, aDimensionAspect->ArrowTailSize(),
843 aFirstArrowEnd, aFirstExtensionDir,
844 THE_EMPTY_LABEL, 0.0, theMode, LabelPosition_None);
847 DrawExtension (thePresentation, aDimensionAspect->ArrowTailSize(),
848 aSecondArrowEnd, aSecondExtensionDir,
849 THE_EMPTY_LABEL, 0.0, theMode, LabelPosition_None);
855 // ------------------------------------------------------------------------ //
857 // -------------------------------------------------------------------------//
859 case LabelPosition_Left:
861 // add label on dimension or extension line to presentation
862 Prs3d_Root::NewGroup (thePresentation);
864 // Left extension with the text
865 DrawExtension (thePresentation, anExtensionSize,
875 // add dimension line primitives
876 if (theMode == ComputeMode_All || theMode == ComputeMode_Line)
878 // add central dimension line
879 Prs3d_Root::NewGroup (thePresentation);
881 // add graphical primitives
882 Handle(Graphic3d_ArrayOfSegments) aPrimSegments = new Graphic3d_ArrayOfSegments (2);
883 aPrimSegments->AddVertex (aCenterLineBegin);
884 aPrimSegments->AddVertex (aCenterLineEnd);
886 Prs3d_Root::CurrentGroup (thePresentation)->SetPrimitivesAspect (aDimensionAspect->LineAspect()->Aspect());
887 Prs3d_Root::CurrentGroup (thePresentation)->AddPrimitiveArray (aPrimSegments);
889 // add selection primitives
890 SelectionGeometry::Curve& aSensitiveCurve = mySelectionGeom.NewCurve();
891 aSensitiveCurve.Append (aCenterLineBegin);
892 aSensitiveCurve.Append (aCenterLineEnd);
894 // add arrows to presentation
895 Prs3d_Root::NewGroup (thePresentation);
897 DrawArrow (thePresentation, aFirstArrowBegin, aFirstArrowDir);
900 DrawArrow (thePresentation, aSecondArrowBegin, aSecondArrowDir);
903 if (!isArrowsExternal || theIsOneSide)
908 // add extension lines for external arrows
909 Prs3d_Root::NewGroup (thePresentation);
911 DrawExtension (thePresentation, aDimensionAspect->ArrowTailSize(),
912 aSecondArrowEnd, aSecondExtensionDir,
913 THE_EMPTY_LABEL, 0.0, theMode, LabelPosition_None);
918 // ------------------------------------------------------------------------ //
920 // -------------------------------------------------------------------------//
922 case LabelPosition_Right:
924 // add label on dimension or extension line to presentation
925 Prs3d_Root::NewGroup (thePresentation);
927 // Right extension with text
928 DrawExtension (thePresentation, anExtensionSize,
933 aLabelString, aLabelWidth,
937 if (theMode == ComputeMode_All || theMode == ComputeMode_Line)
939 // add central dimension line
940 Prs3d_Root::NewGroup (thePresentation);
942 // add graphical primitives
943 Handle(Graphic3d_ArrayOfSegments) aPrimSegments = new Graphic3d_ArrayOfSegments (2);
944 aPrimSegments->AddVertex (aCenterLineBegin);
945 aPrimSegments->AddVertex (aCenterLineEnd);
946 Prs3d_Root::CurrentGroup (thePresentation)->SetPrimitivesAspect (aDimensionAspect->LineAspect()->Aspect());
947 Prs3d_Root::CurrentGroup (thePresentation)->AddPrimitiveArray (aPrimSegments);
949 // add selection primitives
950 SelectionGeometry::Curve& aSensitiveCurve = mySelectionGeom.NewCurve();
951 aSensitiveCurve.Append (aCenterLineBegin);
952 aSensitiveCurve.Append (aCenterLineEnd);
954 // add arrows to presentation
955 Prs3d_Root::NewGroup (thePresentation);
957 DrawArrow (thePresentation, aSecondArrowBegin, aSecondArrowDir);
960 DrawArrow (thePresentation, aFirstArrowBegin, aFirstArrowDir);
963 if (!isArrowsExternal || theIsOneSide)
968 // add extension lines for external arrows
969 Prs3d_Root::NewGroup (thePresentation);
971 DrawExtension (thePresentation, aDimensionAspect->ArrowTailSize(),
972 aFirstArrowEnd, aFirstExtensionDir,
973 THE_EMPTY_LABEL, 0.0, theMode, LabelPosition_None);
980 // add flyout lines to presentation
981 if (theMode == ComputeMode_All)
983 Prs3d_Root::NewGroup (thePresentation);
985 Handle(Graphic3d_ArrayOfSegments) aPrimSegments = new Graphic3d_ArrayOfSegments(4);
986 aPrimSegments->AddVertex (theFirstPoint);
987 aPrimSegments->AddVertex (aLineBegPoint);
989 aPrimSegments->AddVertex (theSecondPoint);
990 aPrimSegments->AddVertex (aLineEndPoint);
992 Prs3d_Root::CurrentGroup (thePresentation)->SetPrimitivesAspect (aDimensionAspect->LineAspect()->Aspect());
993 Prs3d_Root::CurrentGroup (thePresentation)->AddPrimitiveArray (aPrimSegments);
996 mySelectionGeom.IsComputed = Standard_True;
999 //=======================================================================
1000 //function : ComputeLinearFlyouts
1002 //=======================================================================
1003 void AIS_Dimension::ComputeLinearFlyouts (const Handle(SelectMgr_Selection)& theSelection,
1004 const Handle(SelectMgr_EntityOwner)& theOwner,
1005 const gp_Pnt& theFirstPoint,
1006 const gp_Pnt& theSecondPoint)
1008 // count flyout direction
1009 gp_Ax1 aPlaneNormal = GetPlane().Axis();
1010 gp_Dir aTargetPointsVector = gce_MakeDir (theFirstPoint, theSecondPoint);
1012 // count a flyout direction vector.
1013 gp_Dir aFlyoutVector = aPlaneNormal.Direction() ^ aTargetPointsVector;
1015 // create lines for layouts
1016 gp_Lin aLine1 (theFirstPoint, aFlyoutVector);
1017 gp_Lin aLine2 (theSecondPoint, aFlyoutVector);
1019 // get flyout end points
1020 gp_Pnt aFlyoutEnd1 = ElCLib::Value (ElCLib::Parameter (aLine1, theFirstPoint) + GetFlyout(), aLine1);
1021 gp_Pnt aFlyoutEnd2 = ElCLib::Value (ElCLib::Parameter (aLine2, theSecondPoint) + GetFlyout(), aLine2);
1023 // fill sensitive entity for flyouts
1024 Handle(Select3D_SensitiveGroup) aSensitiveEntity = new Select3D_SensitiveGroup (theOwner);
1025 aSensitiveEntity->Add (new Select3D_SensitiveSegment (theOwner, theFirstPoint, aFlyoutEnd1));
1026 aSensitiveEntity->Add (new Select3D_SensitiveSegment (theOwner, theSecondPoint, aFlyoutEnd2));
1027 theSelection->Add (aSensitiveEntity);
1030 //=======================================================================
1031 //function : CircleFromPlanarFace
1032 //purpose : if possible computes circle from planar face
1033 //=======================================================================
1034 Standard_Boolean AIS_Dimension::CircleFromPlanarFace (const TopoDS_Face& theFace,
1035 Handle(Geom_Curve)& theCurve,
1036 gp_Pnt& theFirstPoint,
1037 gp_Pnt& theLastPoint)
1039 TopExp_Explorer anIt (theFace, TopAbs_EDGE);
1040 for ( ; anIt.More(); anIt.Next())
1042 TopoDS_Edge aCurEdge = TopoDS::Edge (anIt.Current());
1043 if (AIS::ComputeGeometry (aCurEdge, theCurve, theFirstPoint, theLastPoint))
1045 if (theCurve->IsInstance (STANDARD_TYPE(Geom_Circle)))
1047 return Standard_True;
1051 return Standard_False;
1054 //=======================================================================
1055 //function : CircleFromEdge
1056 //purpose : if possible computes circle from edge
1057 //=======================================================================
1058 Standard_Boolean AIS_Dimension::CircleFromEdge (const TopoDS_Edge& theEdge,
1060 gp_Pnt& theFirstPoint,
1061 gp_Pnt& theLastPoint)
1063 BRepAdaptor_Curve anAdaptedCurve (theEdge);
1064 switch (anAdaptedCurve.GetType())
1066 case GeomAbs_Circle:
1068 theCircle = anAdaptedCurve.Circle();
1071 case GeomAbs_Ellipse:
1073 gp_Elips anEll = anAdaptedCurve.Ellipse();
1074 if ((anEll.MinorRadius() - anEll.MajorRadius()) >= Precision::Confusion())
1076 return Standard_False;
1078 theCircle = gp_Circ(anEll.Position(),anEll.MinorRadius());
1082 case GeomAbs_Hyperbola:
1083 case GeomAbs_Parabola:
1084 case GeomAbs_BezierCurve:
1085 case GeomAbs_BSplineCurve:
1086 case GeomAbs_OtherCurve:
1088 return Standard_False;
1091 theFirstPoint = anAdaptedCurve.Value (anAdaptedCurve.FirstParameter());
1092 theLastPoint = anAdaptedCurve.Value (anAdaptedCurve.LastParameter());
1093 return Standard_True;
1096 //=======================================================================
1097 //function : InitCircularDimension
1099 //=======================================================================
1100 Standard_Boolean AIS_Dimension::InitCircularDimension (const TopoDS_Shape& theShape,
1102 gp_Pnt& theMiddleArcPoint,
1103 Standard_Boolean& theIsClosed)
1106 Handle(Geom_Surface) aBasisSurf;
1107 AIS_KindOfSurface aSurfType = AIS_KOS_OtherSurface;
1108 gp_Pnt aFirstPoint, aLastPoint;
1109 Standard_Real anOffset = 0.0;
1110 Standard_Real aFirstParam = 0.0;
1111 Standard_Real aLastParam = 0.0;
1113 // Discover circular geometry
1114 switch (theShape.ShapeType())
1118 AIS::GetPlaneFromFace (TopoDS::Face (theShape), aPln, aBasisSurf, aSurfType, anOffset);
1120 if (aSurfType == AIS_KOS_Plane)
1122 Handle(Geom_Curve) aCurve;
1123 if (!CircleFromPlanarFace (TopoDS::Face (theShape), aCurve, aFirstPoint, aLastPoint))
1125 return Standard_False;
1128 theCircle = Handle(Geom_Circle)::DownCast (aCurve)->Circ();
1133 BRepAdaptor_Surface aSurf1 (TopoDS::Face (theShape));
1134 Standard_Real aFirstU = aSurf1.FirstUParameter();
1135 Standard_Real aLastU = aSurf1.LastUParameter();
1136 Standard_Real aFirstV = aSurf1.FirstVParameter();
1137 Standard_Real aLastV = aSurf1.LastVParameter();
1138 Standard_Real aMidU = (aFirstU + aLastU) * 0.5;
1139 Standard_Real aMidV = (aFirstV + aLastV) * 0.5;
1140 aSurf1.D0 (aMidU, aMidV, aCurPos);
1141 Handle (Adaptor3d_HCurve) aBasisCurve;
1142 Standard_Boolean isExpectedType = Standard_False;
1143 if (aSurfType == AIS_KOS_Cylinder)
1145 isExpectedType = Standard_True;
1149 if (aSurfType == AIS_KOS_Revolution)
1151 aBasisCurve = aSurf1.BasisCurve();
1152 if (aBasisCurve->GetType() == GeomAbs_Line)
1154 isExpectedType = Standard_True;
1157 else if (aSurfType == AIS_KOS_Extrusion)
1159 aBasisCurve = aSurf1.BasisCurve();
1160 if (aBasisCurve->GetType() == GeomAbs_Circle)
1162 isExpectedType = Standard_True;
1167 if (!isExpectedType)
1169 return Standard_False;
1172 Handle(Geom_Curve) aCurve = aBasisSurf->VIso(aMidV);
1173 if (aCurve->DynamicType() == STANDARD_TYPE (Geom_Circle))
1175 theCircle = Handle(Geom_Circle)::DownCast (aCurve)->Circ();
1177 else if (aCurve->DynamicType() == STANDARD_TYPE (Geom_TrimmedCurve))
1179 Handle(Geom_TrimmedCurve) aTrimmedCurve = Handle(Geom_TrimmedCurve)::DownCast (aCurve);
1180 aFirstU = aTrimmedCurve->FirstParameter();
1181 aLastU = aTrimmedCurve->LastParameter();
1182 if (aTrimmedCurve->BasisCurve()->DynamicType() == STANDARD_TYPE (Geom_Circle))
1184 theCircle = Handle(Geom_Circle)::DownCast(aTrimmedCurve->BasisCurve())->Circ();
1189 // Compute a circle from 3 points on "aCurve"
1191 aSurf1.D0 (aFirstU, aMidV, aP1);
1192 aSurf1.D0 (aLastU, aMidV, aP2);
1193 GC_MakeCircle aMkCirc (aP1, aCurPos, aP2);
1194 theCircle = aMkCirc.Value()->Circ();
1197 aFirstPoint = ElCLib::Value (aFirstU, theCircle);
1198 aLastPoint = ElCLib::Value (aLastU, theCircle);
1205 TopExp_Explorer anIt (theShape, TopAbs_EDGE);
1208 anEdge = TopoDS::Edge (anIt.Current());
1210 if (!AIS_Dimension::CircleFromEdge (anEdge, theCircle, aFirstPoint, aLastPoint))
1212 return Standard_False;
1218 TopoDS_Edge anEdge = TopoDS::Edge (theShape);
1219 if (!AIS_Dimension::CircleFromEdge (anEdge, theCircle, aFirstPoint, aLastPoint))
1221 return Standard_False;
1225 case TopAbs_COMPOUND:
1226 case TopAbs_COMPSOLID:
1232 return Standard_False;
1235 theIsClosed = aFirstPoint.IsEqual (aLastPoint, Precision::Confusion());
1237 gp_Pnt aCenter = theCircle.Location();
1239 if (theIsClosed) // Circle
1241 gp_Dir anXDir = theCircle.XAxis().Direction();
1242 theMiddleArcPoint = aCenter.Translated (gp_Vec (anXDir) * theCircle.Radius());
1246 aFirstParam = ElCLib::Parameter (theCircle, aFirstPoint);
1247 aLastParam = ElCLib::Parameter (theCircle, aLastPoint);
1248 if (aFirstParam > aLastParam)
1250 aFirstParam -= 2.0 * M_PI;
1253 Standard_Real aParCurPos = (aFirstParam + aLastParam) * 0.5;
1254 gp_Vec aVec = gp_Vec (aCenter, ElCLib::Value (aParCurPos, theCircle)).Normalized () * theCircle.Radius ();
1255 theMiddleArcPoint = aCenter.Translated (aVec);
1258 return Standard_True;
1261 //=======================================================================
1262 //function : ComputeSelection
1264 //=======================================================================
1265 void AIS_Dimension::ComputeSelection (const Handle(SelectMgr_Selection)& theSelection,
1266 const Standard_Integer theMode)
1268 if (!mySelectionGeom.IsComputed)
1273 AIS_DimensionSelectionMode aSelectionMode = (AIS_DimensionSelectionMode)theMode;
1275 // init appropriate entity owner
1276 Handle(SelectMgr_EntityOwner) aSensitiveOwner;
1278 switch (aSelectionMode)
1280 // neutral selection owner
1282 aSensitiveOwner = new SelectMgr_EntityOwner (this, THE_NEUTRAL_SEL_PRIORITY);
1285 // local selection owners
1288 aSensitiveOwner = new AIS_DimensionOwner (this, aSelectionMode, THE_LOCAL_SEL_PRIORITY);
1292 if (aSelectionMode == AIS_DSM_All || aSelectionMode == AIS_DSM_Line)
1294 // sensitives for dimension line segments
1295 Handle(Select3D_SensitiveGroup) aGroupOfSensitives = new Select3D_SensitiveGroup (aSensitiveOwner);
1297 SelectionGeometry::SeqOfCurves::Iterator aCurveIt (mySelectionGeom.DimensionLine);
1298 for (; aCurveIt.More(); aCurveIt.Next())
1300 const SelectionGeometry::HCurve& aCurveData = aCurveIt.Value();
1302 TColgp_Array1OfPnt aSensitivePnts (1, aCurveData->Length());
1303 for (Standard_Integer aPntIt = 1; aPntIt <= aCurveData->Length(); ++aPntIt)
1305 aSensitivePnts.ChangeValue (aPntIt) = aCurveData->Value (aPntIt);
1308 aGroupOfSensitives->Add (new Select3D_SensitiveCurve (aSensitiveOwner, aSensitivePnts));
1311 Quantity_Length anArrowLength = myDrawer->DimensionAspect()->ArrowAspect()->Length();
1312 Standard_Real anArrowAngle = myDrawer->DimensionAspect()->ArrowAspect()->Angle();
1314 // sensitives for arrows
1315 SelectionGeometry::SeqOfArrows::Iterator anArrowIt (mySelectionGeom.Arrows);
1316 for (; anArrowIt.More(); anArrowIt.Next())
1318 const SelectionGeometry::HArrow& anArrow = anArrowIt.Value();
1320 gp_Pnt aSidePnt1 (gp::Origin());
1321 gp_Pnt aSidePnt2 (gp::Origin());
1322 const gp_Dir& aPlane = GetPlane().Axis().Direction();
1323 const gp_Pnt& aPeak = anArrow->Position;
1324 const gp_Dir& aDir = anArrow->Direction;
1326 // compute points for arrow in plane
1327 PointsForArrow (aPeak, aDir, aPlane, anArrowLength, anArrowAngle, aSidePnt1, aSidePnt2);
1329 aGroupOfSensitives->Add (new Select3D_SensitiveTriangle (aSensitiveOwner, aPeak, aSidePnt1, aSidePnt2));
1331 if (!myDrawer->DimensionAspect()->IsArrows3d())
1336 // compute points for orthogonal sensitive plane
1337 gp_Dir anOrthoPlane = anArrow->Direction.Crossed (aPlane);
1339 PointsForArrow (aPeak, aDir, anOrthoPlane, anArrowLength, anArrowAngle, aSidePnt1, aSidePnt2);
1341 aGroupOfSensitives->Add (new Select3D_SensitiveTriangle (aSensitiveOwner, aPeak, aSidePnt1, aSidePnt2));
1344 theSelection->Add (aGroupOfSensitives);
1347 // sensitives for text element
1348 if (aSelectionMode == AIS_DSM_All || aSelectionMode == AIS_DSM_Text)
1350 Handle(Select3D_SensitiveEntity) aTextSensitive;
1352 gp_Ax2 aTextAxes (mySelectionGeom.TextPos,
1353 GetPlane().Axis().Direction(),
1354 mySelectionGeom.TextDir);
1356 if (myDrawer->DimensionAspect()->IsText3d())
1358 // sensitive planar rectangle for text
1359 Standard_Real aDx = mySelectionGeom.TextWidth * 0.5;
1360 Standard_Real aDy = mySelectionGeom.TextHeight * 0.5;
1362 gp_Trsf aLabelPlane;
1363 aLabelPlane.SetTransformation (aTextAxes, gp::XOY());
1365 TColgp_Array1OfPnt aRectanglePoints(1, 4);
1366 aRectanglePoints.ChangeValue(1) = gp_Pnt (-aDx, -aDy, 0.0).Transformed (aLabelPlane);
1367 aRectanglePoints.ChangeValue(2) = gp_Pnt (-aDx, aDy, 0.0).Transformed (aLabelPlane);
1368 aRectanglePoints.ChangeValue(3) = gp_Pnt ( aDx, aDy, 0.0).Transformed (aLabelPlane);
1369 aRectanglePoints.ChangeValue(4) = gp_Pnt ( aDx, -aDy, 0.0).Transformed (aLabelPlane);
1371 Poly_Array1OfTriangle aTriangles(1, 2);
1372 aTriangles.ChangeValue(1) = Poly_Triangle(1, 2, 3);
1373 aTriangles.ChangeValue(2) = Poly_Triangle(1, 3, 4);
1375 Handle(Poly_Triangulation) aRectanglePoly =
1376 new Poly_Triangulation(aRectanglePoints, aTriangles);
1379 new Select3D_SensitiveTriangulation (aSensitiveOwner, aRectanglePoly, TopLoc_Location(), Standard_True);
1383 gp_Circ aTextGeom (aTextAxes, mySelToleranceForText2d != 0.0
1384 ? mySelToleranceForText2d : 1.0);
1386 Handle(Geom_Circle) aSensGeom = new Geom_Circle (aTextGeom);
1388 aTextSensitive = new Select3D_SensitiveCircle (aSensitiveOwner, aSensGeom, Standard_True);
1391 theSelection->Add (aTextSensitive);
1394 // callback for flyout sensitive calculation
1395 if (aSelectionMode == AIS_DSM_All)
1397 ComputeFlyoutSelection (theSelection, aSensitiveOwner);
1401 //=======================================================================
1402 //function : PointsForArrow
1404 //=======================================================================
1405 void AIS_Dimension::PointsForArrow (const gp_Pnt& thePeakPnt,
1406 const gp_Dir& theDirection,
1407 const gp_Dir& thePlane,
1408 const Standard_Real theArrowLength,
1409 const Standard_Real theArrowAngle,
1410 gp_Pnt& theSidePnt1,
1411 gp_Pnt& theSidePnt2)
1413 gp_Lin anArrowLin (thePeakPnt, theDirection.Reversed());
1414 gp_Pnt anArrowEnd = ElCLib::Value (theArrowLength, anArrowLin);
1415 gp_Lin anEdgeLin (anArrowEnd, theDirection.Crossed (thePlane));
1417 Standard_Real anEdgeLength = Tan (theArrowAngle) * theArrowLength;
1419 theSidePnt1 = ElCLib::Value ( anEdgeLength, anEdgeLin);
1420 theSidePnt2 = ElCLib::Value (-anEdgeLength, anEdgeLin);
1423 //=======================================================================
1424 //function : GetTextPositionForLinear
1426 //=======================================================================
1427 gp_Pnt AIS_Dimension::GetTextPositionForLinear (const gp_Pnt& theFirstPoint,
1428 const gp_Pnt& theSecondPoint,
1429 const Standard_Boolean theIsOneSide) const
1433 return gp::Origin();
1436 gp_Pnt aTextPosition (gp::Origin());
1438 Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
1440 // Get label alignment and arrow orientation.
1441 Standard_Integer aLabelPosition = 0;
1442 Standard_Boolean isArrowsExternal = Standard_False;
1443 FitTextAlignmentForLinear (theFirstPoint, theSecondPoint, theIsOneSide,
1444 aDimensionAspect->TextHorizontalPosition(),
1445 aLabelPosition, isArrowsExternal);
1447 // Compute dimension line points.
1448 gp_Dir aPlaneNormal = GetPlane().Axis().Direction();
1449 gp_Vec aTargetPointsVec (theFirstPoint, theSecondPoint);
1451 // Compute flyout direction vector
1452 gp_Dir aFlyoutVector = aPlaneNormal ^ gp_Dir (aTargetPointsVec);
1454 // create lines for layouts
1455 gp_Lin aLine1 (theFirstPoint, aFlyoutVector);
1456 gp_Lin aLine2 (theSecondPoint, aFlyoutVector);
1457 // Get flyout end points
1458 gp_Pnt aLineBegPoint = ElCLib::Value (ElCLib::Parameter (aLine1, theFirstPoint) + GetFlyout(), aLine1);
1459 gp_Pnt aLineEndPoint = ElCLib::Value (ElCLib::Parameter (aLine2, theSecondPoint) + GetFlyout(), aLine2);
1461 // Get text position.
1462 switch (aLabelPosition & LabelPosition_HMask)
1464 case LabelPosition_Left:
1466 gp_Dir aTargetPointsDir = gce_MakeDir (theFirstPoint, theSecondPoint);
1467 Standard_Real anExtensionSize = aDimensionAspect->ExtensionSize();
1469 Standard_Real anOffset = isArrowsExternal
1470 ? anExtensionSize + aDimensionAspect->ArrowAspect()->Length()
1472 gp_Vec anExtensionVec = gp_Vec (aTargetPointsDir) * -anOffset;
1473 aTextPosition = aLineEndPoint.Translated (anExtensionVec);
1476 case LabelPosition_Right:
1478 gp_Dir aTargetPointsDir = gce_MakeDir (theFirstPoint, theSecondPoint);
1479 Standard_Real anExtensionSize = aDimensionAspect->ExtensionSize();
1481 Standard_Real anOffset = isArrowsExternal
1482 ? anExtensionSize + aDimensionAspect->ArrowAspect()->Length()
1484 gp_Vec anExtensionVec = gp_Vec (aTargetPointsDir) * anOffset;
1485 aTextPosition = aLineBegPoint.Translated (anExtensionVec);
1488 case LabelPosition_HCenter:
1490 aTextPosition = (aLineBegPoint.XYZ() + aLineEndPoint.XYZ()) * 0.5;
1495 return aTextPosition;
1498 //=======================================================================
1499 //function : AdjustParametersForLinear
1501 //=======================================================================
1502 Standard_Boolean AIS_Dimension::AdjustParametersForLinear (const gp_Pnt& theTextPos,
1503 const gp_Pnt& theFirstPoint,
1504 const gp_Pnt& theSecondPoint,
1505 Standard_Real& theExtensionSize,
1506 Prs3d_DimensionTextHorizontalPosition& theAlignment,
1507 Standard_Real& theFlyout,
1509 Standard_Boolean& theIsPlaneOld) const
1511 Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
1512 Standard_Real anArrowLength = aDimensionAspect->ArrowAspect()->Length();
1514 gp_Dir aTargetPointsDir = gce_MakeDir (theFirstPoint, theSecondPoint);
1515 gp_Vec aTargetPointsVec (theFirstPoint, theSecondPoint);
1517 // Don't set new plane if the text position lies on the attachment points line.
1518 gp_Lin aTargetPointsLin (theFirstPoint, aTargetPointsDir);
1519 if (!aTargetPointsLin.Contains (theTextPos, Precision::Confusion()))
1521 //Set new automatic plane.
1522 thePlane = gce_MakePln (theTextPos, theFirstPoint, theSecondPoint);
1523 theIsPlaneOld = Standard_False;
1526 // Compute flyout direction vector.
1527 gp_Dir aPlaneNormal = GetPlane().Axis().Direction();
1528 gp_Dir aPositiveFlyout = aPlaneNormal ^ aTargetPointsDir;
1530 // Additional check of collinearity of the plane normal and attachment points vector.
1531 if (aPlaneNormal.IsParallel (aTargetPointsDir, Precision::Angular()))
1533 return Standard_False;
1537 gp_Vec aFirstToTextVec (theFirstPoint, theTextPos);
1539 Standard_Real aCos = aFirstToTextVec.Normalized() * gp_Vec (aTargetPointsDir);
1541 gp_Pnt aTextPosProj = theFirstPoint.Translated
1542 (gp_Vec (aTargetPointsDir) * aFirstToTextVec.Magnitude() * aCos);
1544 // Compute flyout value and direction.
1545 gp_Vec aFlyoutVector = gp_Vec (aTextPosProj, theTextPos);
1548 if (aFlyoutVector.Magnitude() > Precision::Confusion())
1550 theFlyout = gp_Dir (aFlyoutVector).IsOpposite (aPositiveFlyout, Precision::Angular())
1551 ? -aFlyoutVector.Magnitude()
1552 : aFlyoutVector.Magnitude();
1555 // Compute attach points (through which main dimension line passes).
1556 gp_Pnt aFirstAttach = theFirstPoint.Translated (aFlyoutVector);
1557 gp_Pnt aSecondAttach = theSecondPoint.Translated (aFlyoutVector);
1559 // Set horizontal text alignment.
1562 theAlignment = Prs3d_DTHP_Left;
1564 Standard_Real aNewExtSize = theTextPos.Distance (aFirstAttach) - anArrowLength;
1565 theExtensionSize = aNewExtSize < 0.0 ? 0.0 : aNewExtSize;
1567 else if (aTextPosProj.Distance (theFirstPoint) > theFirstPoint.Distance (theSecondPoint))
1569 theAlignment = Prs3d_DTHP_Right;
1571 Standard_Real aNewExtSize = theTextPos.Distance (aSecondAttach) - anArrowLength;
1572 theExtensionSize = aNewExtSize < 0.0 ? 0.0 : aNewExtSize;
1576 theAlignment = Prs3d_DTHP_Center;
1578 return Standard_True;
1581 //=======================================================================
1582 //function : FitTextAlignmentForLinear
1584 //=======================================================================
1585 void AIS_Dimension::FitTextAlignmentForLinear (const gp_Pnt& theFirstPoint,
1586 const gp_Pnt& theSecondPoint,
1587 const Standard_Boolean theIsOneSide,
1588 const Prs3d_DimensionTextHorizontalPosition& theHorizontalTextPos,
1589 Standard_Integer& theLabelPosition,
1590 Standard_Boolean& theIsArrowsExternal) const
1592 theLabelPosition = LabelPosition_None;
1593 theIsArrowsExternal = Standard_False;
1595 // Compute dimension line points
1596 gp_Ax1 aPlaneNormal = GetPlane().Axis();
1597 gp_Dir aTargetPointsVector = gce_MakeDir (theFirstPoint, theSecondPoint);
1599 // compute flyout direction vector
1600 gp_Dir aFlyoutVector = aPlaneNormal.Direction() ^ aTargetPointsVector;
1602 // create lines for layouts
1603 gp_Lin aLine1 (theFirstPoint, aFlyoutVector);
1604 gp_Lin aLine2 (theSecondPoint, aFlyoutVector);
1606 // Get flyout end points
1607 gp_Pnt aLineBegPoint = ElCLib::Value (ElCLib::Parameter (aLine1, theFirstPoint) + GetFlyout(), aLine1);
1608 gp_Pnt aLineEndPoint = ElCLib::Value (ElCLib::Parameter (aLine2, theSecondPoint) + GetFlyout(), aLine2);
1610 Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
1612 // For extensions we need to know arrow size, text size and extension size: get it from aspect
1613 Quantity_Length anArrowLength = aDimensionAspect->ArrowAspect()->Length();
1615 // prepare label string and compute its geometrical width
1616 Standard_Real aLabelWidth;
1617 TCollection_ExtendedString aLabelString = GetValueString (aLabelWidth);
1619 // Add margins to cut dimension lines for 3d text
1620 if (aDimensionAspect->IsText3d())
1622 aLabelWidth += aDimensionAspect->TextAspect()->Height() * THE_3D_TEXT_MARGIN * 2.0;
1625 // Handle user-defined and automatic arrow placement
1626 switch (aDimensionAspect->ArrowOrientation())
1628 case Prs3d_DAO_External: theIsArrowsExternal = true; break;
1629 case Prs3d_DAO_Internal: theIsArrowsExternal = false; break;
1632 // Add margin to ensure a small tail between text and arrow
1633 Standard_Real anArrowMargin = aDimensionAspect->IsText3d()
1634 ? aDimensionAspect->TextAspect()->Height() * THE_3D_TEXT_MARGIN
1637 Standard_Real aDimensionWidth = aLineBegPoint.Distance (aLineEndPoint);
1638 Standard_Real anArrowsWidth = theIsOneSide
1639 ? anArrowLength + anArrowMargin
1640 : (anArrowLength + anArrowMargin) * 2.0;
1642 theIsArrowsExternal = aDimensionWidth < aLabelWidth + anArrowsWidth;
1647 // Handle user-defined and automatic text placement
1648 switch (theHorizontalTextPos)
1650 case Prs3d_DTHP_Left : theLabelPosition |= LabelPosition_Left; break;
1651 case Prs3d_DTHP_Right : theLabelPosition |= LabelPosition_Right; break;
1652 case Prs3d_DTHP_Center: theLabelPosition |= LabelPosition_HCenter; break;
1653 case Prs3d_DTHP_Fit:
1655 Standard_Real aDimensionWidth = aLineBegPoint.Distance (aLineEndPoint);
1656 Standard_Real anArrowsWidth = theIsOneSide ? anArrowLength : 2.0 * anArrowLength;
1657 Standard_Real aContentWidth = theIsArrowsExternal ? aLabelWidth : aLabelWidth + anArrowsWidth;
1659 theLabelPosition |= aDimensionWidth < aContentWidth ? LabelPosition_Left : LabelPosition_HCenter;
1664 // Handle vertical text placement options
1665 switch (aDimensionAspect->TextVerticalPosition())
1667 case Prs3d_DTVP_Above : theLabelPosition |= LabelPosition_Above; break;
1668 case Prs3d_DTVP_Below : theLabelPosition |= LabelPosition_Below; break;
1669 case Prs3d_DTVP_Center : theLabelPosition |= LabelPosition_VCenter; break;
1673 //=======================================================================
1674 //function : UnsetFixedTextPosition
1676 //=======================================================================
1677 void AIS_Dimension::UnsetFixedTextPosition()
1679 myIsTextPositionFixed = Standard_False;
1680 myFixedTextPosition = gp::Origin();