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
339 if (aFont.FindAndInit (aTextAspect->Aspect()->Font(), aTextAspect->Aspect()->GetTextFontAspect(), aTextAspect->Height(), Font_StrictLevel_Any))
341 for (NCollection_Utf8Iter anIter = anUTFString.Iterator(); *anIter != 0; )
343 Standard_Utf32Char aCurrChar = *anIter;
344 Standard_Utf32Char aNextChar = *(++anIter);
345 theWidth += aFont.AdvanceX (aCurrChar, aNextChar);
351 // Text width for 1:1 scale 2D case
352 Font_FTFontParams aFontParams;
353 aFontParams.PointSize = (unsigned int )aTextAspect->Height();
354 aFontParams.Resolution = THE_2D_TEXT_RESOLUTION;
355 if (Handle(Font_FTFont) aFont = Font_FTFont::FindAndCreate (aTextAspect->Aspect()->Font(), aTextAspect->Aspect()->GetTextFontAspect(), aFontParams, Font_StrictLevel_Any))
357 for (NCollection_Utf8Iter anIter = anUTFString.Iterator(); *anIter != 0; )
359 Standard_Utf32Char aCurrChar = *anIter;
360 Standard_Utf32Char aNextChar = *(++anIter);
361 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 Standard_Real 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_PolygonOffset aPolOffset;
407 aPolOffset.Mode = Aspect_POM_Off;
408 aPolOffset.Factor = 0.0f;
409 aPolOffset.Units = 0.0f;
410 Handle(Graphic3d_AspectFillArea3d) aShadingStyle = new Graphic3d_AspectFillArea3d();
411 aShadingStyle->SetInteriorStyle (Aspect_IS_SOLID);
412 aShadingStyle->SetColor (myDrawer->DimensionAspect()->ArrowAspect()->Aspect()->Color());
413 aShadingStyle->SetShadingModel (Graphic3d_TOSM_UNLIT);
414 aShadingStyle->SetPolygonOffset (aPolOffset);
416 aGroup->SetPrimitivesAspect (aShadingStyle);
417 aGroup->AddPrimitiveArray (anArrow);
420 SelectionGeometry::Arrow& aSensitiveArrow = mySelectionGeom.NewArrow();
421 aSensitiveArrow.Position = theLocation;
422 aSensitiveArrow.Direction = theDirection;
425 //=======================================================================
426 //function : drawText
428 //=======================================================================
429 void AIS_Dimension::drawText (const Handle(Prs3d_Presentation)& thePresentation,
430 const gp_Pnt& theTextPos,
431 const gp_Dir& theTextDir,
432 const TCollection_ExtendedString& theText,
433 const Standard_Integer theLabelPosition)
435 Handle(Graphic3d_Group) aGroup = thePresentation->NewGroup();
436 if (myDrawer->DimensionAspect()->IsText3d())
438 // getting font parameters
439 Handle(Prs3d_TextAspect) aTextAspect = myDrawer->DimensionAspect()->TextAspect();
440 Quantity_Color aColor = aTextAspect->Aspect()->Color();
441 Font_FontAspect aFontAspect = aTextAspect->Aspect()->GetTextFontAspect();
442 Standard_Real aFontHeight = aTextAspect->Height();
444 // creating TopoDS_Shape for text
445 Font_BRepFont aFont (aTextAspect->Aspect()->Font().ToCString(),
446 aFontAspect, aFontHeight);
447 NCollection_Utf8String anUTFString (theText.ToExtString());
449 Font_BRepTextBuilder aBuilder;
450 TopoDS_Shape aTextShape = aBuilder.Perform (aFont, anUTFString);
452 // compute text width with kerning
453 Standard_Real aTextWidth = 0.0;
454 Standard_Real aTextHeight = aFont.Ascender() + aFont.Descender();
456 for (NCollection_Utf8Iter anIter = anUTFString.Iterator(); *anIter != 0; )
458 Standard_Utf32Char aCurrChar = *anIter;
459 Standard_Utf32Char aNextChar = *(++anIter);
460 aTextWidth += aFont.AdvanceX (aCurrChar, aNextChar);
463 // formating text position in XOY plane
464 Standard_Integer aHLabelPos = theLabelPosition & LabelPosition_HMask;
465 Standard_Integer aVLabelPos = theLabelPosition & LabelPosition_VMask;
467 gp_Dir aTextDir (aHLabelPos == LabelPosition_Left ? -theTextDir : theTextDir);
469 // compute label offsets
470 Standard_Real aMarginSize = aFontHeight * THE_3D_TEXT_MARGIN;
471 Standard_Real aCenterHOffset = 0.0;
472 Standard_Real aCenterVOffset = 0.0;
475 case LabelPosition_HCenter : aCenterHOffset = 0.0; break;
476 case LabelPosition_Right : aCenterHOffset = aTextWidth / 2.0 + aMarginSize; break;
477 case LabelPosition_Left : aCenterHOffset = -aTextWidth / 2.0 - aMarginSize; break;
481 case LabelPosition_VCenter : aCenterVOffset = 0.0; break;
482 case LabelPosition_Above : aCenterVOffset = aTextHeight / 2.0 + aMarginSize; break;
483 case LabelPosition_Below : aCenterVOffset = -aTextHeight / 2.0 - aMarginSize; break;
486 // compute shape offset transformation
487 Standard_Real aShapeHOffset = aCenterHOffset - aTextWidth / 2.0;
488 Standard_Real aShapeVOffset = aCenterVOffset - aTextHeight / 2.0;
490 // center shape in its bounding box (suppress border spacing added by FT_Font)
492 BRepBndLib::AddClose (aTextShape, aShapeBnd);
494 Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
495 aShapeBnd.Get (aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
497 Standard_Real aXalign = aTextWidth * 0.5 - (aXmax + aXmin) * 0.5;
498 Standard_Real aYalign = aTextHeight * 0.5 - (aYmax + aYmin) * 0.5;
499 aShapeHOffset += aXalign;
500 aShapeVOffset += aYalign;
502 gp_Trsf anOffsetTrsf;
503 anOffsetTrsf.SetTranslation (gp::Origin(), gp_Pnt (aShapeHOffset, aShapeVOffset, 0.0));
504 aTextShape.Move (anOffsetTrsf);
506 // transform text to myWorkingPlane coordinate system
507 gp_Ax3 aTextCoordSystem (theTextPos, GetPlane().Axis().Direction(), aTextDir);
508 gp_Trsf aTextPlaneTrsf;
509 aTextPlaneTrsf.SetTransformation (aTextCoordSystem, gp_Ax3 (gp::XOY()));
510 aTextShape.Move (aTextPlaneTrsf);
512 // set text flipping anchors
513 gp_Trsf aCenterOffsetTrsf;
514 gp_Pnt aCenterOffset (aCenterHOffset, aCenterVOffset, 0.0);
515 aCenterOffsetTrsf.SetTranslation (gp::Origin(), aCenterOffset);
517 gp_Pnt aCenterOfLabel (gp::Origin());
518 aCenterOfLabel.Transform (aCenterOffsetTrsf);
519 aCenterOfLabel.Transform (aTextPlaneTrsf);
521 gp_Ax2 aFlippingAxes (aCenterOfLabel, GetPlane().Axis().Direction(), aTextDir);
522 aGroup->SetFlippingOptions (Standard_True, aFlippingAxes);
525 if (myDrawer->DimensionAspect()->IsTextShaded())
527 // Setting text shading and color parameters
528 if (!myDrawer->HasOwnShadingAspect())
530 myDrawer->SetShadingAspect (new Prs3d_ShadingAspect());
533 Graphic3d_MaterialAspect aShadeMat (Graphic3d_NOM_DEFAULT);
534 aShadeMat.SetAmbientColor (Quantity_NOC_BLACK);
535 aShadeMat.SetDiffuseColor (Quantity_NOC_BLACK);
536 aShadeMat.SetSpecularColor(Quantity_NOC_BLACK);
537 myDrawer->ShadingAspect()->Aspect()->SetInteriorColor (aColor);
538 myDrawer->ShadingAspect()->Aspect()->SetBackInteriorColor (aColor);
539 myDrawer->ShadingAspect()->SetMaterial (aShadeMat);
542 StdPrs_ShadedShape::Add (thePresentation, aTextShape, myDrawer);
546 // Setting color for text
547 if (!myDrawer->HasOwnFreeBoundaryAspect())
549 myDrawer->SetFreeBoundaryAspect (new Prs3d_LineAspect (aColor, Aspect_TOL_SOLID, 1.0));
551 myDrawer->FreeBoundaryAspect()->Aspect()->SetColor (aColor);
554 if (Handle(Graphic3d_ArrayOfPrimitives) anEdges = StdPrs_WFShape::AddAllEdges (aTextShape, myDrawer))
556 aGroup->SetGroupPrimitivesAspect (myDrawer->FreeBoundaryAspect()->Aspect());
557 aGroup->AddPrimitiveArray (anEdges);
560 Prs3d_Root::CurrentGroup (thePresentation)->SetFlippingOptions (Standard_False, gp_Ax2());
562 mySelectionGeom.TextPos = aCenterOfLabel;
563 mySelectionGeom.TextDir = aTextDir;
564 mySelectionGeom.TextWidth = aTextWidth + aMarginSize * 2.0;
565 mySelectionGeom.TextHeight = aTextHeight;
570 // generate primitives for 2D text
571 myDrawer->DimensionAspect()->TextAspect()->Aspect()->SetDisplayType (Aspect_TODT_DIMENSION);
573 Prs3d_Text::Draw (aGroup,
574 myDrawer->DimensionAspect()->TextAspect(),
578 mySelectionGeom.TextPos = theTextPos;
579 mySelectionGeom.TextDir = theTextDir;
580 mySelectionGeom.TextWidth = 0.0;
581 mySelectionGeom.TextHeight = 0.0;
584 //=======================================================================
585 //function : DrawExtension
587 //=======================================================================
588 void AIS_Dimension::DrawExtension (const Handle(Prs3d_Presentation)& thePresentation,
589 const Standard_Real theExtensionSize,
590 const gp_Pnt& theExtensionStart,
591 const gp_Dir& theExtensionDir,
592 const TCollection_ExtendedString& theLabelString,
593 const Standard_Real theLabelWidth,
594 const Standard_Integer theMode,
595 const Standard_Integer theLabelPosition)
597 // reference line for extension starting at its connection point
598 gp_Lin anExtensionLine (theExtensionStart, theExtensionDir);
600 Standard_Boolean hasLabel = theLabelString.Length() > 0;
601 if (hasLabel && (theMode == ComputeMode_All || theMode == ComputeMode_Text))
603 // compute text primitives; get its model width
604 gp_Pnt aTextPos = ElCLib::Value (theExtensionSize, anExtensionLine);
605 gp_Dir aTextDir = theExtensionDir;
607 Handle(Graphic3d_Group) aGroup = thePresentation->NewGroup();
608 drawText (thePresentation,
615 if (theMode != ComputeMode_All && theMode != ComputeMode_Line)
620 Standard_Boolean isShortLine = !myDrawer->DimensionAspect()->IsText3d()
621 || theLabelPosition & LabelPosition_VCenter;
623 // compute graphical primitives and sensitives for extension line
624 gp_Pnt anExtStart = theExtensionStart;
625 gp_Pnt anExtEnd = !hasLabel || isShortLine
626 ? ElCLib::Value (theExtensionSize, anExtensionLine)
627 : ElCLib::Value (theExtensionSize + theLabelWidth, anExtensionLine);
629 // add graphical primitives
630 Handle(Graphic3d_ArrayOfSegments) anExtPrimitive = new Graphic3d_ArrayOfSegments (2);
631 anExtPrimitive->AddVertex (anExtStart);
632 anExtPrimitive->AddVertex (anExtEnd);
634 // add selection primitives
635 SelectionGeometry::Curve& aSensitiveCurve = mySelectionGeom.NewCurve();
636 aSensitiveCurve.Append (anExtStart);
637 aSensitiveCurve.Append (anExtEnd);
639 Handle(Graphic3d_Group) aGroup = thePresentation->NewGroup();
640 if (!myDrawer->DimensionAspect()->IsText3d() && theMode == ComputeMode_All)
642 aGroup->SetStencilTestOptions (Standard_True);
644 Handle(Graphic3d_AspectLine3d) aDimensionLineStyle = myDrawer->DimensionAspect()->LineAspect()->Aspect();
645 aGroup->SetPrimitivesAspect (aDimensionLineStyle);
646 aGroup->AddPrimitiveArray (anExtPrimitive);
647 if (!myDrawer->DimensionAspect()->IsText3d() && theMode == ComputeMode_All)
649 aGroup->SetStencilTestOptions (Standard_False);
653 //=======================================================================
654 //function : DrawLinearDimension
656 //=======================================================================
657 void AIS_Dimension::DrawLinearDimension (const Handle(Prs3d_Presentation)& thePresentation,
658 const Standard_Integer theMode,
659 const gp_Pnt& theFirstPoint,
660 const gp_Pnt& theSecondPoint,
661 const Standard_Boolean theIsOneSide)
663 // do not build any dimension for equal points
664 if (theFirstPoint.IsEqual (theSecondPoint, Precision::Confusion()))
666 throw Standard_ProgramError("Can not build presentation for equal points.");
669 Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
671 // For extensions we need to know arrow size, text size and extension size: get it from aspect
672 Standard_Real anArrowLength = aDimensionAspect->ArrowAspect()->Length();
673 Standard_Real anExtensionSize = aDimensionAspect->ExtensionSize();
674 // prepare label string and compute its geometrical width
675 Standard_Real aLabelWidth;
676 TCollection_ExtendedString aLabelString = GetValueString (aLabelWidth);
678 // add margins to cut dimension lines for 3d text
679 if (aDimensionAspect->IsText3d())
681 aLabelWidth += aDimensionAspect->TextAspect()->Height() * THE_3D_TEXT_MARGIN * 2.0;
684 // handle user-defined and automatic arrow placement
685 Standard_Boolean isArrowsExternal = Standard_False;
686 Standard_Integer aLabelPosition = LabelPosition_None;
688 Prs3d_DimensionTextHorizontalPosition aHorisontalTextPos = aDimensionAspect->TextHorizontalPosition();
689 if (IsTextPositionCustom())
691 if (!AdjustParametersForLinear (myFixedTextPosition, theFirstPoint, theSecondPoint,
692 anExtensionSize, aHorisontalTextPos, myFlyout, myPlane, myIsPlaneCustom))
694 throw Standard_ProgramError("Can not adjust plane to the custom label position.");
698 FitTextAlignmentForLinear (theFirstPoint, theSecondPoint, theIsOneSide, aHorisontalTextPos,
699 aLabelPosition, isArrowsExternal);
701 // compute dimension line points
702 gp_Pnt aLineBegPoint, aLineEndPoint;
703 ComputeFlyoutLinePoints (theFirstPoint, theSecondPoint, aLineBegPoint, aLineEndPoint);
704 gp_Lin aDimensionLine = gce_MakeLin (aLineBegPoint, aLineEndPoint);
706 // compute arrows positions and directions
707 gp_Dir aFirstArrowDir = aDimensionLine.Direction().Reversed();
708 gp_Dir aSecondArrowDir = aDimensionLine.Direction();
709 gp_Dir aFirstExtensionDir = aDimensionLine.Direction().Reversed();
710 gp_Dir aSecondExtensionDir = aDimensionLine.Direction();
712 gp_Pnt aFirstArrowBegin (0.0, 0.0, 0.0);
713 gp_Pnt aFirstArrowEnd (0.0, 0.0, 0.0);
714 gp_Pnt aSecondArrowBegin (0.0, 0.0, 0.0);
715 gp_Pnt aSecondArrowEnd (0.0, 0.0, 0.0);
717 if (isArrowsExternal)
719 aFirstArrowDir.Reverse();
720 aSecondArrowDir.Reverse();
723 aFirstArrowBegin = aLineBegPoint;
724 aSecondArrowBegin = aLineEndPoint;
725 aFirstArrowEnd = aLineBegPoint.Translated (-gp_Vec (aFirstArrowDir).Scaled (anArrowLength));
726 aSecondArrowEnd = aLineEndPoint.Translated (-gp_Vec (aSecondArrowDir).Scaled (anArrowLength));
728 gp_Pnt aCenterLineBegin = isArrowsExternal
729 ? aLineBegPoint : aFirstArrowEnd;
731 gp_Pnt aCenterLineEnd = isArrowsExternal || theIsOneSide
732 ? aLineEndPoint : aSecondArrowEnd;
735 switch (aLabelPosition & LabelPosition_HMask)
737 // ------------------------------------------------------------------------ //
739 // -------------------------------------------------------------------------//
740 case LabelPosition_HCenter:
742 // add label on dimension or extension line to presentation
743 gp_Pnt aTextPos = IsTextPositionCustom() ? myFixedTextPosition
744 : (aCenterLineBegin.XYZ() + aCenterLineEnd.XYZ()) * 0.5;
745 gp_Dir aTextDir = aDimensionLine.Direction();
747 // add text primitives
748 if (theMode == ComputeMode_All || theMode == ComputeMode_Text)
750 thePresentation->NewGroup();
751 drawText (thePresentation,
758 // add dimension line primitives
759 if (theMode == ComputeMode_All || theMode == ComputeMode_Line)
761 Standard_Boolean isLineBreak = aDimensionAspect->TextVerticalPosition() == Prs3d_DTVP_Center
762 && aDimensionAspect->IsText3d();
764 Handle(Graphic3d_ArrayOfSegments) aPrimSegments = new Graphic3d_ArrayOfSegments (isLineBreak ? 4 : 2);
766 // compute continuous or sectioned main line segments
769 Standard_Real aPTextPosition = ElCLib::Parameter (aDimensionLine, aTextPos);
770 gp_Pnt aSection1Beg = aCenterLineBegin;
771 gp_Pnt aSection1End = ElCLib::Value (aPTextPosition - (aLabelWidth * 0.5), aDimensionLine);
772 gp_Pnt aSection2Beg = ElCLib::Value (aPTextPosition + (aLabelWidth * 0.5), aDimensionLine);
773 gp_Pnt aSection2End = aCenterLineEnd;
775 aPrimSegments->AddVertex (aSection1Beg);
776 aPrimSegments->AddVertex (aSection1End);
777 aPrimSegments->AddVertex (aSection2Beg);
778 aPrimSegments->AddVertex (aSection2End);
780 SelectionGeometry::Curve& aLeftSensitiveCurve = mySelectionGeom.NewCurve();
781 SelectionGeometry::Curve& aRightSensitiveCurve = mySelectionGeom.NewCurve();
782 aLeftSensitiveCurve.Append (aSection1Beg);
783 aLeftSensitiveCurve.Append (aSection1End);
784 aRightSensitiveCurve.Append (aSection2Beg);
785 aRightSensitiveCurve.Append (aSection2End);
789 aPrimSegments->AddVertex (aCenterLineBegin);
790 aPrimSegments->AddVertex (aCenterLineEnd);
792 SelectionGeometry::Curve& aSensitiveCurve = mySelectionGeom.NewCurve();
793 aSensitiveCurve.Append (aCenterLineBegin);
794 aSensitiveCurve.Append (aCenterLineEnd);
797 // set text label justification
798 Graphic3d_VerticalTextAlignment aTextJustificaton = Graphic3d_VTA_BOTTOM;
799 switch (aLabelPosition & LabelPosition_VMask)
801 case LabelPosition_Above :
802 case LabelPosition_VCenter : aTextJustificaton = Graphic3d_VTA_BOTTOM; break;
803 case LabelPosition_Below : aTextJustificaton = Graphic3d_VTA_TOP; break;
805 aDimensionAspect->TextAspect()->SetVerticalJustification (aTextJustificaton);
807 // main dimension line, short extension
809 Handle(Graphic3d_Group) aGroup = thePresentation->NewGroup();
810 if (!aDimensionAspect->IsText3d() && theMode == ComputeMode_All)
812 aGroup->SetStencilTestOptions (Standard_True);
814 aGroup->SetPrimitivesAspect (aDimensionAspect->LineAspect()->Aspect());
815 aGroup->AddPrimitiveArray (aPrimSegments);
816 if (!aDimensionAspect->IsText3d() && theMode == ComputeMode_All)
818 aGroup->SetStencilTestOptions (Standard_False);
822 // add arrows to presentation
824 Handle(Graphic3d_Group) aGroup = thePresentation->NewGroup();
825 DrawArrow (thePresentation, aFirstArrowBegin, aFirstArrowDir);
828 DrawArrow (thePresentation, aSecondArrowBegin, aSecondArrowDir);
832 if (!isArrowsExternal)
837 // add arrow extension lines to presentation
839 DrawExtension (thePresentation, aDimensionAspect->ArrowTailSize(),
840 aFirstArrowEnd, aFirstExtensionDir,
841 THE_EMPTY_LABEL, 0.0, theMode, LabelPosition_None);
844 DrawExtension (thePresentation, aDimensionAspect->ArrowTailSize(),
845 aSecondArrowEnd, aSecondExtensionDir,
846 THE_EMPTY_LABEL, 0.0, theMode, LabelPosition_None);
852 // ------------------------------------------------------------------------ //
854 // -------------------------------------------------------------------------//
856 case LabelPosition_Left:
858 // add label on dimension or extension line to presentation
860 // Left extension with the text
861 DrawExtension (thePresentation, anExtensionSize,
872 // add dimension line primitives
873 if (theMode == ComputeMode_All || theMode == ComputeMode_Line)
875 // add central dimension line
877 Handle(Graphic3d_Group) aGroup = thePresentation->NewGroup();
879 // add graphical primitives
880 Handle(Graphic3d_ArrayOfSegments) aPrimSegments = new Graphic3d_ArrayOfSegments (2);
881 aPrimSegments->AddVertex (aCenterLineBegin);
882 aPrimSegments->AddVertex (aCenterLineEnd);
884 aGroup->SetPrimitivesAspect (aDimensionAspect->LineAspect()->Aspect());
885 aGroup->AddPrimitiveArray (aPrimSegments);
887 // add selection primitives
888 SelectionGeometry::Curve& aSensitiveCurve = mySelectionGeom.NewCurve();
889 aSensitiveCurve.Append (aCenterLineBegin);
890 aSensitiveCurve.Append (aCenterLineEnd);
893 // add arrows to presentation
895 Handle(Graphic3d_Group) aGroup = thePresentation->NewGroup();
896 DrawArrow (thePresentation, aFirstArrowBegin, aFirstArrowDir);
899 DrawArrow (thePresentation, aSecondArrowBegin, aSecondArrowDir);
903 if (!isArrowsExternal || theIsOneSide)
908 // add extension lines for external arrows
910 DrawExtension (thePresentation, aDimensionAspect->ArrowTailSize(),
911 aSecondArrowEnd, aSecondExtensionDir,
912 THE_EMPTY_LABEL, 0.0, theMode, LabelPosition_None);
918 // ------------------------------------------------------------------------ //
920 // -------------------------------------------------------------------------//
922 case LabelPosition_Right:
924 // add label on dimension or extension line to presentation
926 // Right extension with text
927 DrawExtension (thePresentation, anExtensionSize,
932 aLabelString, aLabelWidth,
936 if (theMode == ComputeMode_All || theMode == ComputeMode_Line)
938 // add central dimension line
940 Handle(Graphic3d_Group) aGroup = thePresentation->NewGroup();
942 // add graphical primitives
943 Handle(Graphic3d_ArrayOfSegments) aPrimSegments = new Graphic3d_ArrayOfSegments (2);
944 aPrimSegments->AddVertex (aCenterLineBegin);
945 aPrimSegments->AddVertex (aCenterLineEnd);
946 aGroup->SetGroupPrimitivesAspect (aDimensionAspect->LineAspect()->Aspect());
947 aGroup->AddPrimitiveArray (aPrimSegments);
949 // add selection primitives
950 SelectionGeometry::Curve& aSensitiveCurve = mySelectionGeom.NewCurve();
951 aSensitiveCurve.Append (aCenterLineBegin);
952 aSensitiveCurve.Append (aCenterLineEnd);
955 // add arrows to presentation
957 thePresentation->NewGroup();
958 DrawArrow (thePresentation, aSecondArrowBegin, aSecondArrowDir);
961 DrawArrow (thePresentation, aFirstArrowBegin, aFirstArrowDir);
965 if (!isArrowsExternal || theIsOneSide)
970 // add extension lines for external arrows
972 DrawExtension (thePresentation, aDimensionAspect->ArrowTailSize(),
973 aFirstArrowEnd, aFirstExtensionDir,
974 THE_EMPTY_LABEL, 0.0, theMode, LabelPosition_None);
982 // add flyout lines to presentation
983 if (theMode == ComputeMode_All)
985 Handle(Graphic3d_Group) aGroup = thePresentation->NewGroup();
987 Handle(Graphic3d_ArrayOfSegments) aPrimSegments = new Graphic3d_ArrayOfSegments(4);
988 aPrimSegments->AddVertex (theFirstPoint);
989 aPrimSegments->AddVertex (aLineBegPoint);
991 aPrimSegments->AddVertex (theSecondPoint);
992 aPrimSegments->AddVertex (aLineEndPoint);
994 aGroup->SetGroupPrimitivesAspect (aDimensionAspect->LineAspect()->Aspect());
995 aGroup->AddPrimitiveArray (aPrimSegments);
998 mySelectionGeom.IsComputed = Standard_True;
1001 //=======================================================================
1002 //function : ComputeFlyoutLinePoints
1004 //=======================================================================
1005 void AIS_Dimension::ComputeFlyoutLinePoints (const gp_Pnt& theFirstPoint, const gp_Pnt& theSecondPoint,
1006 gp_Pnt& theLineBegPoint, gp_Pnt& theLineEndPoint)
1008 // compute dimension line points
1009 gp_Ax1 aPlaneNormal = GetPlane().Axis();
1010 // compute flyout direction vector
1011 gp_Dir aTargetPointsVector = gce_MakeDir (theFirstPoint, theSecondPoint);
1012 gp_Dir aFlyoutVector = aPlaneNormal.Direction() ^ aTargetPointsVector;
1013 // create lines for layouts
1014 gp_Lin aLine1 (theFirstPoint, aFlyoutVector);
1015 gp_Lin aLine2 (theSecondPoint, aFlyoutVector);
1017 // Get flyout end points
1018 theLineBegPoint = ElCLib::Value (ElCLib::Parameter (aLine1, theFirstPoint) + GetFlyout(), aLine1);
1019 theLineEndPoint = ElCLib::Value (ElCLib::Parameter (aLine2, theSecondPoint) + GetFlyout(), aLine2);
1022 //=======================================================================
1023 //function : ComputeLinearFlyouts
1025 //=======================================================================
1026 void AIS_Dimension::ComputeLinearFlyouts (const Handle(SelectMgr_Selection)& theSelection,
1027 const Handle(SelectMgr_EntityOwner)& theOwner,
1028 const gp_Pnt& theFirstPoint,
1029 const gp_Pnt& theSecondPoint)
1031 // count flyout direction
1032 gp_Ax1 aPlaneNormal = GetPlane().Axis();
1033 gp_Dir aTargetPointsVector = gce_MakeDir (theFirstPoint, theSecondPoint);
1035 // count a flyout direction vector.
1036 gp_Dir aFlyoutVector = aPlaneNormal.Direction() ^ aTargetPointsVector;
1038 // create lines for layouts
1039 gp_Lin aLine1 (theFirstPoint, aFlyoutVector);
1040 gp_Lin aLine2 (theSecondPoint, aFlyoutVector);
1042 // get flyout end points
1043 gp_Pnt aFlyoutEnd1 = ElCLib::Value (ElCLib::Parameter (aLine1, theFirstPoint) + GetFlyout(), aLine1);
1044 gp_Pnt aFlyoutEnd2 = ElCLib::Value (ElCLib::Parameter (aLine2, theSecondPoint) + GetFlyout(), aLine2);
1046 // fill sensitive entity for flyouts
1047 Handle(Select3D_SensitiveGroup) aSensitiveEntity = new Select3D_SensitiveGroup (theOwner);
1048 aSensitiveEntity->Add (new Select3D_SensitiveSegment (theOwner, theFirstPoint, aFlyoutEnd1));
1049 aSensitiveEntity->Add (new Select3D_SensitiveSegment (theOwner, theSecondPoint, aFlyoutEnd2));
1050 theSelection->Add (aSensitiveEntity);
1053 //=======================================================================
1054 //function : CircleFromPlanarFace
1055 //purpose : if possible computes circle from planar face
1056 //=======================================================================
1057 Standard_Boolean AIS_Dimension::CircleFromPlanarFace (const TopoDS_Face& theFace,
1058 Handle(Geom_Curve)& theCurve,
1059 gp_Pnt& theFirstPoint,
1060 gp_Pnt& theLastPoint)
1062 TopExp_Explorer anIt (theFace, TopAbs_EDGE);
1063 for ( ; anIt.More(); anIt.Next())
1065 TopoDS_Edge aCurEdge = TopoDS::Edge (anIt.Current());
1066 if (AIS::ComputeGeometry (aCurEdge, theCurve, theFirstPoint, theLastPoint))
1068 if (theCurve->IsInstance (STANDARD_TYPE(Geom_Circle)))
1070 return Standard_True;
1074 return Standard_False;
1077 //=======================================================================
1078 //function : CircleFromEdge
1079 //purpose : if possible computes circle from edge
1080 //=======================================================================
1081 Standard_Boolean AIS_Dimension::CircleFromEdge (const TopoDS_Edge& theEdge,
1083 gp_Pnt& theFirstPoint,
1084 gp_Pnt& theLastPoint)
1086 BRepAdaptor_Curve anAdaptedCurve (theEdge);
1087 switch (anAdaptedCurve.GetType())
1089 case GeomAbs_Circle:
1091 theCircle = anAdaptedCurve.Circle();
1094 case GeomAbs_Ellipse:
1096 gp_Elips anEll = anAdaptedCurve.Ellipse();
1097 if ((anEll.MinorRadius() - anEll.MajorRadius()) >= Precision::Confusion())
1099 return Standard_False;
1101 theCircle = gp_Circ(anEll.Position(),anEll.MinorRadius());
1105 case GeomAbs_Hyperbola:
1106 case GeomAbs_Parabola:
1107 case GeomAbs_BezierCurve:
1108 case GeomAbs_BSplineCurve:
1109 case GeomAbs_OtherCurve:
1111 return Standard_False;
1114 theFirstPoint = anAdaptedCurve.Value (anAdaptedCurve.FirstParameter());
1115 theLastPoint = anAdaptedCurve.Value (anAdaptedCurve.LastParameter());
1116 return Standard_True;
1119 //=======================================================================
1120 //function : InitCircularDimension
1122 //=======================================================================
1123 Standard_Boolean AIS_Dimension::InitCircularDimension (const TopoDS_Shape& theShape,
1125 gp_Pnt& theMiddleArcPoint,
1126 Standard_Boolean& theIsClosed)
1129 Handle(Geom_Surface) aBasisSurf;
1130 AIS_KindOfSurface aSurfType = AIS_KOS_OtherSurface;
1131 gp_Pnt aFirstPoint, aLastPoint;
1132 Standard_Real anOffset = 0.0;
1133 Standard_Real aFirstParam = 0.0;
1134 Standard_Real aLastParam = 0.0;
1136 // Discover circular geometry
1137 switch (theShape.ShapeType())
1141 AIS::GetPlaneFromFace (TopoDS::Face (theShape), aPln, aBasisSurf, aSurfType, anOffset);
1143 if (aSurfType == AIS_KOS_Plane)
1145 Handle(Geom_Curve) aCurve;
1146 if (!CircleFromPlanarFace (TopoDS::Face (theShape), aCurve, aFirstPoint, aLastPoint))
1148 return Standard_False;
1151 theCircle = Handle(Geom_Circle)::DownCast (aCurve)->Circ();
1156 BRepAdaptor_Surface aSurf1 (TopoDS::Face (theShape));
1157 Standard_Real aFirstU = aSurf1.FirstUParameter();
1158 Standard_Real aLastU = aSurf1.LastUParameter();
1159 Standard_Real aFirstV = aSurf1.FirstVParameter();
1160 Standard_Real aLastV = aSurf1.LastVParameter();
1161 Standard_Real aMidU = (aFirstU + aLastU) * 0.5;
1162 Standard_Real aMidV = (aFirstV + aLastV) * 0.5;
1163 aSurf1.D0 (aMidU, aMidV, aCurPos);
1164 Handle (Adaptor3d_HCurve) aBasisCurve;
1165 Standard_Boolean isExpectedType = Standard_False;
1166 if (aSurfType == AIS_KOS_Cylinder)
1168 isExpectedType = Standard_True;
1172 if (aSurfType == AIS_KOS_Revolution)
1174 aBasisCurve = aSurf1.BasisCurve();
1175 if (aBasisCurve->GetType() == GeomAbs_Line)
1177 isExpectedType = Standard_True;
1180 else if (aSurfType == AIS_KOS_Extrusion)
1182 aBasisCurve = aSurf1.BasisCurve();
1183 if (aBasisCurve->GetType() == GeomAbs_Circle)
1185 isExpectedType = Standard_True;
1190 if (!isExpectedType)
1192 return Standard_False;
1195 Handle(Geom_Curve) aCurve = aBasisSurf->VIso(aMidV);
1196 if (aCurve->DynamicType() == STANDARD_TYPE (Geom_Circle))
1198 theCircle = Handle(Geom_Circle)::DownCast (aCurve)->Circ();
1200 else if (aCurve->DynamicType() == STANDARD_TYPE (Geom_TrimmedCurve))
1202 Handle(Geom_TrimmedCurve) aTrimmedCurve = Handle(Geom_TrimmedCurve)::DownCast (aCurve);
1203 aFirstU = aTrimmedCurve->FirstParameter();
1204 aLastU = aTrimmedCurve->LastParameter();
1205 if (aTrimmedCurve->BasisCurve()->DynamicType() == STANDARD_TYPE (Geom_Circle))
1207 theCircle = Handle(Geom_Circle)::DownCast(aTrimmedCurve->BasisCurve())->Circ();
1212 // Compute a circle from 3 points on "aCurve"
1214 aSurf1.D0 (aFirstU, aMidV, aP1);
1215 aSurf1.D0 (aLastU, aMidV, aP2);
1216 GC_MakeCircle aMkCirc (aP1, aCurPos, aP2);
1217 theCircle = aMkCirc.Value()->Circ();
1220 aFirstPoint = ElCLib::Value (aFirstU, theCircle);
1221 aLastPoint = ElCLib::Value (aLastU, theCircle);
1228 TopExp_Explorer anIt (theShape, TopAbs_EDGE);
1231 anEdge = TopoDS::Edge (anIt.Current());
1233 if (!AIS_Dimension::CircleFromEdge (anEdge, theCircle, aFirstPoint, aLastPoint))
1235 return Standard_False;
1241 TopoDS_Edge anEdge = TopoDS::Edge (theShape);
1242 if (!AIS_Dimension::CircleFromEdge (anEdge, theCircle, aFirstPoint, aLastPoint))
1244 return Standard_False;
1248 case TopAbs_COMPOUND:
1249 case TopAbs_COMPSOLID:
1255 return Standard_False;
1258 theIsClosed = aFirstPoint.IsEqual (aLastPoint, Precision::Confusion());
1260 gp_Pnt aCenter = theCircle.Location();
1262 if (theIsClosed) // Circle
1264 gp_Dir anXDir = theCircle.XAxis().Direction();
1265 theMiddleArcPoint = aCenter.Translated (gp_Vec (anXDir) * theCircle.Radius());
1269 aFirstParam = ElCLib::Parameter (theCircle, aFirstPoint);
1270 aLastParam = ElCLib::Parameter (theCircle, aLastPoint);
1271 if (aFirstParam > aLastParam)
1273 aFirstParam -= 2.0 * M_PI;
1276 Standard_Real aParCurPos = (aFirstParam + aLastParam) * 0.5;
1277 gp_Vec aVec = gp_Vec (aCenter, ElCLib::Value (aParCurPos, theCircle)).Normalized () * theCircle.Radius ();
1278 theMiddleArcPoint = aCenter.Translated (aVec);
1281 return Standard_True;
1284 //=======================================================================
1285 //function : ComputeSelection
1287 //=======================================================================
1288 void AIS_Dimension::ComputeSelection (const Handle(SelectMgr_Selection)& theSelection,
1289 const Standard_Integer theMode)
1291 if (!mySelectionGeom.IsComputed)
1296 AIS_DimensionSelectionMode aSelectionMode = (AIS_DimensionSelectionMode)theMode;
1298 // init appropriate entity owner
1299 Handle(SelectMgr_EntityOwner) aSensitiveOwner;
1301 switch (aSelectionMode)
1303 // neutral selection owner
1305 aSensitiveOwner = new SelectMgr_EntityOwner (this, THE_NEUTRAL_SEL_PRIORITY);
1308 // local selection owners
1311 aSensitiveOwner = new AIS_DimensionOwner (this, aSelectionMode, THE_LOCAL_SEL_PRIORITY);
1315 if (aSelectionMode == AIS_DSM_All || aSelectionMode == AIS_DSM_Line)
1317 // sensitives for dimension line segments
1318 Handle(Select3D_SensitiveGroup) aGroupOfSensitives = new Select3D_SensitiveGroup (aSensitiveOwner);
1320 SelectionGeometry::SeqOfCurves::Iterator aCurveIt (mySelectionGeom.DimensionLine);
1321 for (; aCurveIt.More(); aCurveIt.Next())
1323 const SelectionGeometry::HCurve& aCurveData = aCurveIt.Value();
1325 TColgp_Array1OfPnt aSensitivePnts (1, aCurveData->Length());
1326 for (Standard_Integer aPntIt = 1; aPntIt <= aCurveData->Length(); ++aPntIt)
1328 aSensitivePnts.ChangeValue (aPntIt) = aCurveData->Value (aPntIt);
1331 aGroupOfSensitives->Add (new Select3D_SensitiveCurve (aSensitiveOwner, aSensitivePnts));
1334 Standard_Real anArrowLength = myDrawer->DimensionAspect()->ArrowAspect()->Length();
1335 Standard_Real anArrowAngle = myDrawer->DimensionAspect()->ArrowAspect()->Angle();
1337 // sensitives for arrows
1338 SelectionGeometry::SeqOfArrows::Iterator anArrowIt (mySelectionGeom.Arrows);
1339 for (; anArrowIt.More(); anArrowIt.Next())
1341 const SelectionGeometry::HArrow& anArrow = anArrowIt.Value();
1343 gp_Pnt aSidePnt1 (gp::Origin());
1344 gp_Pnt aSidePnt2 (gp::Origin());
1345 const gp_Dir& aPlane = GetPlane().Axis().Direction();
1346 const gp_Pnt& aPeak = anArrow->Position;
1347 const gp_Dir& aDir = anArrow->Direction;
1349 // compute points for arrow in plane
1350 PointsForArrow (aPeak, aDir, aPlane, anArrowLength, anArrowAngle, aSidePnt1, aSidePnt2);
1352 aGroupOfSensitives->Add (new Select3D_SensitiveTriangle (aSensitiveOwner, aPeak, aSidePnt1, aSidePnt2));
1354 if (!myDrawer->DimensionAspect()->IsArrows3d())
1359 // compute points for orthogonal sensitive plane
1360 gp_Dir anOrthoPlane = anArrow->Direction.Crossed (aPlane);
1362 PointsForArrow (aPeak, aDir, anOrthoPlane, anArrowLength, anArrowAngle, aSidePnt1, aSidePnt2);
1364 aGroupOfSensitives->Add (new Select3D_SensitiveTriangle (aSensitiveOwner, aPeak, aSidePnt1, aSidePnt2));
1367 theSelection->Add (aGroupOfSensitives);
1370 // sensitives for text element
1371 if (aSelectionMode == AIS_DSM_All || aSelectionMode == AIS_DSM_Text)
1373 Handle(Select3D_SensitiveEntity) aTextSensitive;
1375 gp_Ax2 aTextAxes (mySelectionGeom.TextPos,
1376 GetPlane().Axis().Direction(),
1377 mySelectionGeom.TextDir);
1379 if (myDrawer->DimensionAspect()->IsText3d())
1381 // sensitive planar rectangle for text
1382 Standard_Real aDx = mySelectionGeom.TextWidth * 0.5;
1383 Standard_Real aDy = mySelectionGeom.TextHeight * 0.5;
1385 gp_Trsf aLabelPlane;
1386 aLabelPlane.SetTransformation (aTextAxes, gp::XOY());
1388 TColgp_Array1OfPnt aRectanglePoints(1, 4);
1389 aRectanglePoints.ChangeValue(1) = gp_Pnt (-aDx, -aDy, 0.0).Transformed (aLabelPlane);
1390 aRectanglePoints.ChangeValue(2) = gp_Pnt (-aDx, aDy, 0.0).Transformed (aLabelPlane);
1391 aRectanglePoints.ChangeValue(3) = gp_Pnt ( aDx, aDy, 0.0).Transformed (aLabelPlane);
1392 aRectanglePoints.ChangeValue(4) = gp_Pnt ( aDx, -aDy, 0.0).Transformed (aLabelPlane);
1394 Poly_Array1OfTriangle aTriangles(1, 2);
1395 aTriangles.ChangeValue(1) = Poly_Triangle(1, 2, 3);
1396 aTriangles.ChangeValue(2) = Poly_Triangle(1, 3, 4);
1398 Handle(Poly_Triangulation) aRectanglePoly =
1399 new Poly_Triangulation(aRectanglePoints, aTriangles);
1402 new Select3D_SensitiveTriangulation (aSensitiveOwner, aRectanglePoly, TopLoc_Location(), Standard_True);
1406 gp_Circ aTextGeom (aTextAxes, mySelToleranceForText2d != 0.0
1407 ? mySelToleranceForText2d : 1.0);
1409 Handle(Geom_Circle) aSensGeom = new Geom_Circle (aTextGeom);
1411 aTextSensitive = new Select3D_SensitiveCircle (aSensitiveOwner, aSensGeom, Standard_True);
1414 theSelection->Add (aTextSensitive);
1417 // callback for flyout sensitive calculation
1418 if (aSelectionMode == AIS_DSM_All)
1420 ComputeFlyoutSelection (theSelection, aSensitiveOwner);
1424 //=======================================================================
1425 //function : PointsForArrow
1427 //=======================================================================
1428 void AIS_Dimension::PointsForArrow (const gp_Pnt& thePeakPnt,
1429 const gp_Dir& theDirection,
1430 const gp_Dir& thePlane,
1431 const Standard_Real theArrowLength,
1432 const Standard_Real theArrowAngle,
1433 gp_Pnt& theSidePnt1,
1434 gp_Pnt& theSidePnt2)
1436 gp_Lin anArrowLin (thePeakPnt, theDirection.Reversed());
1437 gp_Pnt anArrowEnd = ElCLib::Value (theArrowLength, anArrowLin);
1438 gp_Lin anEdgeLin (anArrowEnd, theDirection.Crossed (thePlane));
1440 Standard_Real anEdgeLength = Tan (theArrowAngle) * theArrowLength;
1442 theSidePnt1 = ElCLib::Value ( anEdgeLength, anEdgeLin);
1443 theSidePnt2 = ElCLib::Value (-anEdgeLength, anEdgeLin);
1446 //=======================================================================
1447 //function : GetTextPositionForLinear
1449 //=======================================================================
1450 gp_Pnt AIS_Dimension::GetTextPositionForLinear (const gp_Pnt& theFirstPoint,
1451 const gp_Pnt& theSecondPoint,
1452 const Standard_Boolean theIsOneSide) const
1456 return gp::Origin();
1459 gp_Pnt aTextPosition (gp::Origin());
1461 Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
1463 // Get label alignment and arrow orientation.
1464 Standard_Integer aLabelPosition = 0;
1465 Standard_Boolean isArrowsExternal = Standard_False;
1466 FitTextAlignmentForLinear (theFirstPoint, theSecondPoint, theIsOneSide,
1467 aDimensionAspect->TextHorizontalPosition(),
1468 aLabelPosition, isArrowsExternal);
1470 // Compute dimension line points.
1471 gp_Dir aPlaneNormal = GetPlane().Axis().Direction();
1472 gp_Vec aTargetPointsVec (theFirstPoint, theSecondPoint);
1474 // Compute flyout direction vector
1475 gp_Dir aFlyoutVector = aPlaneNormal ^ gp_Dir (aTargetPointsVec);
1477 // create lines for layouts
1478 gp_Lin aLine1 (theFirstPoint, aFlyoutVector);
1479 gp_Lin aLine2 (theSecondPoint, aFlyoutVector);
1480 // Get flyout end points
1481 gp_Pnt aLineBegPoint = ElCLib::Value (ElCLib::Parameter (aLine1, theFirstPoint) + GetFlyout(), aLine1);
1482 gp_Pnt aLineEndPoint = ElCLib::Value (ElCLib::Parameter (aLine2, theSecondPoint) + GetFlyout(), aLine2);
1484 // Get text position.
1485 switch (aLabelPosition & LabelPosition_HMask)
1487 case LabelPosition_Left:
1489 gp_Dir aTargetPointsDir = gce_MakeDir (theFirstPoint, theSecondPoint);
1490 Standard_Real anExtensionSize = aDimensionAspect->ExtensionSize();
1492 Standard_Real anOffset = isArrowsExternal
1493 ? anExtensionSize + aDimensionAspect->ArrowAspect()->Length()
1495 gp_Vec anExtensionVec = gp_Vec (aTargetPointsDir) * -anOffset;
1496 aTextPosition = aLineEndPoint.Translated (anExtensionVec);
1499 case LabelPosition_Right:
1501 gp_Dir aTargetPointsDir = gce_MakeDir (theFirstPoint, theSecondPoint);
1502 Standard_Real anExtensionSize = aDimensionAspect->ExtensionSize();
1504 Standard_Real anOffset = isArrowsExternal
1505 ? anExtensionSize + aDimensionAspect->ArrowAspect()->Length()
1507 gp_Vec anExtensionVec = gp_Vec (aTargetPointsDir) * anOffset;
1508 aTextPosition = aLineBegPoint.Translated (anExtensionVec);
1511 case LabelPosition_HCenter:
1513 aTextPosition = (aLineBegPoint.XYZ() + aLineEndPoint.XYZ()) * 0.5;
1518 return aTextPosition;
1521 //=======================================================================
1522 //function : AdjustParametersForLinear
1524 //=======================================================================
1525 Standard_Boolean AIS_Dimension::AdjustParametersForLinear (const gp_Pnt& theTextPos,
1526 const gp_Pnt& theFirstPoint,
1527 const gp_Pnt& theSecondPoint,
1528 Standard_Real& theExtensionSize,
1529 Prs3d_DimensionTextHorizontalPosition& theAlignment,
1530 Standard_Real& theFlyout,
1532 Standard_Boolean& theIsPlaneOld) const
1534 Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
1535 Standard_Real anArrowLength = aDimensionAspect->ArrowAspect()->Length();
1537 gp_Dir aTargetPointsDir = gce_MakeDir (theFirstPoint, theSecondPoint);
1538 gp_Vec aTargetPointsVec (theFirstPoint, theSecondPoint);
1540 // Don't set new plane if the text position lies on the attachment points line.
1541 gp_Lin aTargetPointsLin (theFirstPoint, aTargetPointsDir);
1542 if (!aTargetPointsLin.Contains (theTextPos, Precision::Confusion()))
1544 //Set new automatic plane.
1545 thePlane = gce_MakePln (theTextPos, theFirstPoint, theSecondPoint);
1546 theIsPlaneOld = Standard_False;
1549 // Compute flyout direction vector.
1550 gp_Dir aPlaneNormal = GetPlane().Axis().Direction();
1551 gp_Dir aPositiveFlyout = aPlaneNormal ^ aTargetPointsDir;
1553 // Additional check of collinearity of the plane normal and attachment points vector.
1554 if (aPlaneNormal.IsParallel (aTargetPointsDir, Precision::Angular()))
1556 return Standard_False;
1560 gp_Vec aFirstToTextVec (theFirstPoint, theTextPos);
1562 Standard_Real aCos = aFirstToTextVec.Normalized() * gp_Vec (aTargetPointsDir);
1564 gp_Pnt aTextPosProj = theFirstPoint.Translated
1565 (gp_Vec (aTargetPointsDir) * aFirstToTextVec.Magnitude() * aCos);
1567 // Compute flyout value and direction.
1568 gp_Vec aFlyoutVector = gp_Vec (aTextPosProj, theTextPos);
1571 if (aFlyoutVector.Magnitude() > Precision::Confusion())
1573 theFlyout = gp_Dir (aFlyoutVector).IsOpposite (aPositiveFlyout, Precision::Angular())
1574 ? -aFlyoutVector.Magnitude()
1575 : aFlyoutVector.Magnitude();
1578 // Compute attach points (through which main dimension line passes).
1579 gp_Pnt aFirstAttach = theFirstPoint.Translated (aFlyoutVector);
1580 gp_Pnt aSecondAttach = theSecondPoint.Translated (aFlyoutVector);
1582 // Set horizontal text alignment.
1585 theAlignment = Prs3d_DTHP_Left;
1587 Standard_Real aNewExtSize = theTextPos.Distance (aFirstAttach) - anArrowLength;
1588 theExtensionSize = aNewExtSize < 0.0 ? 0.0 : aNewExtSize;
1590 else if (aTextPosProj.Distance (theFirstPoint) > theFirstPoint.Distance (theSecondPoint))
1592 theAlignment = Prs3d_DTHP_Right;
1594 Standard_Real aNewExtSize = theTextPos.Distance (aSecondAttach) - anArrowLength;
1595 theExtensionSize = aNewExtSize < 0.0 ? 0.0 : aNewExtSize;
1599 theAlignment = Prs3d_DTHP_Center;
1601 return Standard_True;
1604 //=======================================================================
1605 //function : FitTextAlignmentForLinear
1607 //=======================================================================
1608 void AIS_Dimension::FitTextAlignmentForLinear (const gp_Pnt& theFirstPoint,
1609 const gp_Pnt& theSecondPoint,
1610 const Standard_Boolean theIsOneSide,
1611 const Prs3d_DimensionTextHorizontalPosition& theHorizontalTextPos,
1612 Standard_Integer& theLabelPosition,
1613 Standard_Boolean& theIsArrowsExternal) const
1615 theLabelPosition = LabelPosition_None;
1616 theIsArrowsExternal = Standard_False;
1618 // Compute dimension line points
1619 gp_Ax1 aPlaneNormal = GetPlane().Axis();
1620 gp_Dir aTargetPointsVector = gce_MakeDir (theFirstPoint, theSecondPoint);
1622 // compute flyout direction vector
1623 gp_Dir aFlyoutVector = aPlaneNormal.Direction() ^ aTargetPointsVector;
1625 // create lines for layouts
1626 gp_Lin aLine1 (theFirstPoint, aFlyoutVector);
1627 gp_Lin aLine2 (theSecondPoint, aFlyoutVector);
1629 // Get flyout end points
1630 gp_Pnt aLineBegPoint = ElCLib::Value (ElCLib::Parameter (aLine1, theFirstPoint) + GetFlyout(), aLine1);
1631 gp_Pnt aLineEndPoint = ElCLib::Value (ElCLib::Parameter (aLine2, theSecondPoint) + GetFlyout(), aLine2);
1633 Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
1635 // For extensions we need to know arrow size, text size and extension size: get it from aspect
1636 Standard_Real anArrowLength = aDimensionAspect->ArrowAspect()->Length();
1638 // prepare label string and compute its geometrical width
1639 Standard_Real aLabelWidth;
1640 TCollection_ExtendedString aLabelString = GetValueString (aLabelWidth);
1642 // Add margins to cut dimension lines for 3d text
1643 if (aDimensionAspect->IsText3d())
1645 aLabelWidth += aDimensionAspect->TextAspect()->Height() * THE_3D_TEXT_MARGIN * 2.0;
1648 // Handle user-defined and automatic arrow placement
1649 switch (aDimensionAspect->ArrowOrientation())
1651 case Prs3d_DAO_External: theIsArrowsExternal = true; break;
1652 case Prs3d_DAO_Internal: theIsArrowsExternal = false; break;
1655 // Add margin to ensure a small tail between text and arrow
1656 Standard_Real anArrowMargin = aDimensionAspect->IsText3d()
1657 ? aDimensionAspect->TextAspect()->Height() * THE_3D_TEXT_MARGIN
1660 Standard_Real aDimensionWidth = aLineBegPoint.Distance (aLineEndPoint);
1661 Standard_Real anArrowsWidth = theIsOneSide
1662 ? anArrowLength + anArrowMargin
1663 : (anArrowLength + anArrowMargin) * 2.0;
1665 theIsArrowsExternal = aDimensionWidth < aLabelWidth + anArrowsWidth;
1670 // Handle user-defined and automatic text placement
1671 switch (theHorizontalTextPos)
1673 case Prs3d_DTHP_Left : theLabelPosition |= LabelPosition_Left; break;
1674 case Prs3d_DTHP_Right : theLabelPosition |= LabelPosition_Right; break;
1675 case Prs3d_DTHP_Center: theLabelPosition |= LabelPosition_HCenter; break;
1676 case Prs3d_DTHP_Fit:
1678 Standard_Real aDimensionWidth = aLineBegPoint.Distance (aLineEndPoint);
1679 Standard_Real anArrowsWidth = theIsOneSide ? anArrowLength : 2.0 * anArrowLength;
1680 Standard_Real aContentWidth = theIsArrowsExternal ? aLabelWidth : aLabelWidth + anArrowsWidth;
1682 theLabelPosition |= aDimensionWidth < aContentWidth ? LabelPosition_Left : LabelPosition_HCenter;
1687 // Handle vertical text placement options
1688 switch (aDimensionAspect->TextVerticalPosition())
1690 case Prs3d_DTVP_Above : theLabelPosition |= LabelPosition_Above; break;
1691 case Prs3d_DTVP_Below : theLabelPosition |= LabelPosition_Below; break;
1692 case Prs3d_DTVP_Center : theLabelPosition |= LabelPosition_VCenter; break;
1696 //=======================================================================
1697 //function : UnsetFixedTextPosition
1699 //=======================================================================
1700 void AIS_Dimension::UnsetFixedTextPosition()
1702 myIsTextPositionFixed = Standard_False;
1703 myFixedTextPosition = gp::Origin();