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),
103 myIsValueCustom (Standard_False),
104 myIsTextPositionFixed (Standard_False),
105 mySpecialSymbol (' '),
106 myDisplaySpecialSymbol (AIS_DSS_No),
107 myGeometryType (GeometryType_UndefShapes),
108 myIsPlaneCustom (Standard_False),
110 myIsGeometryValid (Standard_False),
111 myKindOfDimension (theType)
115 //=======================================================================
116 //function : SetCustomValue
118 //=======================================================================
119 void AIS_Dimension::SetCustomValue (const Standard_Real theValue)
121 if (myIsValueCustom && myCustomValue == theValue)
126 myIsValueCustom = Standard_True;
128 myCustomValue = theValue;
133 //=======================================================================
134 //function : GetPlane
136 //=======================================================================
137 const gp_Pln& AIS_Dimension::GetPlane() const
142 //=======================================================================
143 //function : SetUserPlane
145 //=======================================================================
146 void AIS_Dimension::SetCustomPlane (const gp_Pln& thePlane)
149 myIsPlaneCustom = Standard_True;
151 // Disable fixed (custom) text position
152 UnsetFixedTextPosition();
154 // Check validity if geometry has been set already.
161 //=======================================================================
162 //function : SetDimensionAspect
164 //=======================================================================
165 void AIS_Dimension::SetDimensionAspect (const Handle(Prs3d_DimensionAspect)& theDimensionAspect)
167 myDrawer->SetDimensionAspect (theDimensionAspect);
172 //=======================================================================
173 //function : SetDisplaySpecialSymbol
175 //=======================================================================
176 void AIS_Dimension::SetDisplaySpecialSymbol (const AIS_DisplaySpecialSymbol theDisplaySpecSymbol)
178 if (myDisplaySpecialSymbol == theDisplaySpecSymbol)
183 myDisplaySpecialSymbol = theDisplaySpecSymbol;
188 //=======================================================================
189 //function : SetSpecialSymbol
191 //=======================================================================
192 void AIS_Dimension::SetSpecialSymbol (const Standard_ExtCharacter theSpecialSymbol)
194 if (mySpecialSymbol == theSpecialSymbol)
199 mySpecialSymbol = theSpecialSymbol;
204 //=======================================================================
205 //function : SetSelToleranceForText2d
207 //=======================================================================
208 void AIS_Dimension::SetSelToleranceForText2d (const Standard_Real theTol)
210 if (mySelToleranceForText2d == theTol)
215 mySelToleranceForText2d = theTol;
220 //=======================================================================
221 //function : SetFlyout
223 //=======================================================================
224 void AIS_Dimension::SetFlyout (const Standard_Real theFlyout)
226 if (myFlyout == theFlyout)
231 myFlyout = theFlyout;
233 // Disable fixed text position
234 UnsetFixedTextPosition();
239 //=======================================================================
240 //function : GetDisplayUnits
242 //=======================================================================
243 const TCollection_AsciiString& AIS_Dimension::GetDisplayUnits() const
245 return THE_UNDEFINED_UNITS;
248 //=======================================================================
249 //function : GetModelUnits
251 //=======================================================================
252 const TCollection_AsciiString& AIS_Dimension::GetModelUnits() const
254 return THE_UNDEFINED_UNITS;
257 //=======================================================================
258 //function : ValueToDisplayUnits
260 //=======================================================================
261 Standard_Real AIS_Dimension::ValueToDisplayUnits() const
263 return UnitsAPI::AnyToAny (GetValue(),
264 GetModelUnits().ToCString(),
265 GetDisplayUnits().ToCString());
268 //=======================================================================
269 //function : GetValueString
271 //=======================================================================
272 TCollection_ExtendedString AIS_Dimension::GetValueString (Standard_Real& theWidth) const
274 // format value string using "sprintf"
275 TCollection_AsciiString aFormatStr = myDrawer->DimensionAspect()->ValueStringFormat();
277 char aFmtBuffer[256];
278 sprintf (aFmtBuffer, aFormatStr.ToCString(), ValueToDisplayUnits());
279 TCollection_ExtendedString aValueStr = TCollection_ExtendedString (aFmtBuffer);
281 // add units to values string
282 if (myDrawer->DimensionAspect()->IsUnitsDisplayed())
285 aValueStr += TCollection_ExtendedString (GetDisplayUnits());
288 switch (myDisplaySpecialSymbol)
290 case AIS_DSS_Before : aValueStr.Insert (1, mySpecialSymbol); break;
291 case AIS_DSS_After : aValueStr.Insert (aValueStr.Length() + 1, mySpecialSymbol); break;
292 case AIS_DSS_No : break;
295 // Get text style parameters
296 Quantity_Color aColor;
297 Standard_CString aFontName;
298 Standard_Real aFactor;
299 Standard_Real aSpace;
300 myDrawer->DimensionAspect()->TextAspect()->Aspect()->Values (aColor, aFontName, aFactor, aSpace);
301 Font_FontAspect aFontAspect = myDrawer->DimensionAspect()->TextAspect()->Aspect()->GetTextFontAspect();
302 Standard_Real aFontHeight = myDrawer->DimensionAspect()->TextAspect()->Height();
304 NCollection_Utf8String anUTFString = (Standard_Utf16Char* )aValueStr.ToExtString();
308 if (myDrawer->DimensionAspect()->IsText3d())
310 // text width produced by BRepFont
311 Font_BRepFont aFont (aFontName, aFontAspect, aFontHeight);
313 for (NCollection_Utf8Iter anIter = anUTFString.Iterator(); *anIter != 0; )
315 Standard_Utf32Char aCurrChar = *anIter;
316 Standard_Utf32Char aNextChar = *(++anIter);
317 theWidth += aFont.AdvanceX (aCurrChar, aNextChar);
322 // Text width for 1:1 scale 2D case
323 Handle(Font_FTFont) aFont = new Font_FTFont();
324 aFont->Init (aFontName, aFontAspect, (const unsigned int)aFontHeight, THE_2D_TEXT_RESOLUTION);
326 for (NCollection_Utf8Iter anIter = anUTFString.Iterator(); *anIter != 0; )
328 Standard_Utf32Char aCurrChar = *anIter;
329 Standard_Utf32Char aNextChar = *(++anIter);
330 theWidth += (Standard_Real) aFont->AdvanceX (aCurrChar, aNextChar);
337 //=======================================================================
338 //function : DrawArrow
340 //=======================================================================
341 void AIS_Dimension::DrawArrow (const Handle(Prs3d_Presentation)& thePresentation,
342 const gp_Pnt& theLocation,
343 const gp_Dir& theDirection)
345 Prs3d_Root::NewGroup (thePresentation);
347 Quantity_Length aLength = myDrawer->DimensionAspect()->ArrowAspect()->Length();
348 Standard_Real anAngle = myDrawer->DimensionAspect()->ArrowAspect()->Angle();
350 if (myDrawer->DimensionAspect()->IsArrows3d())
352 Prs3d_Arrow::Draw (thePresentation,
360 gp_Pnt aLeftPoint (gp::Origin());
361 gp_Pnt aRightPoint (gp::Origin());
362 const gp_Dir& aPlane = GetPlane().Axis().Direction();
364 PointsForArrow (theLocation, theDirection, aPlane, aLength, anAngle, aLeftPoint, aRightPoint);
366 Handle(Graphic3d_ArrayOfTriangles) anArrow = new Graphic3d_ArrayOfTriangles(3);
368 anArrow->AddVertex (aLeftPoint);
369 anArrow->AddVertex (theLocation);
370 anArrow->AddVertex (aRightPoint);
372 // Set aspect for arrow triangles
373 Quantity_Color aColor;
374 Aspect_TypeOfLine aTOL;
375 Standard_Real aWidth;
376 myDrawer->DimensionAspect()->ArrowAspect()->Aspect()->Values (aColor, aTOL, aWidth);
377 Graphic3d_MaterialAspect aShadeMat (Graphic3d_NOM_DEFAULT);
378 aShadeMat.SetReflectionModeOff (Graphic3d_TOR_AMBIENT);
379 aShadeMat.SetReflectionModeOff (Graphic3d_TOR_DIFFUSE);
380 aShadeMat.SetReflectionModeOff (Graphic3d_TOR_SPECULAR);
382 Handle(Prs3d_ShadingAspect) aShadingStyle = new Prs3d_ShadingAspect();
383 aShadingStyle->SetColor (aColor);
384 aShadingStyle->SetMaterial (aShadeMat);
386 Prs3d_Root::CurrentGroup (thePresentation)->SetPrimitivesAspect (aShadingStyle->Aspect());
387 Prs3d_Root::CurrentGroup (thePresentation)->AddPrimitiveArray (anArrow);
390 SelectionGeometry::Arrow& aSensitiveArrow = mySelectionGeom.NewArrow();
391 aSensitiveArrow.Position = theLocation;
392 aSensitiveArrow.Direction = theDirection;
395 //=======================================================================
396 //function : DrawText
398 //=======================================================================
399 void AIS_Dimension::DrawText (const Handle(Prs3d_Presentation)& thePresentation,
400 const gp_Pnt& theTextPos,
401 const gp_Dir& theTextDir,
402 const TCollection_ExtendedString& theText,
403 const Standard_Integer theLabelPosition)
405 if (myDrawer->DimensionAspect()->IsText3d())
407 // getting font parameters
408 Quantity_Color aColor;
409 Standard_CString aFontName;
410 Standard_Real anExpansionFactor;
411 Standard_Real aSpace;
412 myDrawer->DimensionAspect()->TextAspect()->Aspect()->Values (aColor, aFontName, anExpansionFactor, aSpace);
413 Font_FontAspect aFontAspect = myDrawer->DimensionAspect()->TextAspect()->Aspect()->GetTextFontAspect();
414 Standard_Real aFontHeight = myDrawer->DimensionAspect()->TextAspect()->Height();
416 // creating TopoDS_Shape for text
417 Font_BRepFont aFont (aFontName, aFontAspect, aFontHeight);
418 NCollection_Utf8String anUTFString = (Standard_Utf16Char* )theText.ToExtString();
420 Font_BRepTextBuilder aBuilder;
421 TopoDS_Shape aTextShape = aBuilder.Perform (aFont, anUTFString);
423 // compute text width with kerning
424 Standard_Real aTextWidth = 0.0;
425 Standard_Real aTextHeight = aFont.Ascender() + aFont.Descender();
427 for (NCollection_Utf8Iter anIter = anUTFString.Iterator(); *anIter != 0; )
429 Standard_Utf32Char aCurrChar = *anIter;
430 Standard_Utf32Char aNextChar = *(++anIter);
431 aTextWidth += aFont.AdvanceX (aCurrChar, aNextChar);
434 // formating text position in XOY plane
435 Standard_Integer aHLabelPos = theLabelPosition & LabelPosition_HMask;
436 Standard_Integer aVLabelPos = theLabelPosition & LabelPosition_VMask;
438 gp_Dir aTextDir (aHLabelPos == LabelPosition_Left ? -theTextDir : theTextDir);
440 // compute label offsets
441 Standard_Real aMarginSize = aFontHeight * THE_3D_TEXT_MARGIN;
442 Standard_Real aCenterHOffset = 0.0;
443 Standard_Real aCenterVOffset = 0.0;
446 case LabelPosition_HCenter : aCenterHOffset = 0.0; break;
447 case LabelPosition_Right : aCenterHOffset = aTextWidth / 2.0 + aMarginSize; break;
448 case LabelPosition_Left : aCenterHOffset = -aTextWidth / 2.0 - aMarginSize; break;
452 case LabelPosition_VCenter : aCenterVOffset = 0.0; break;
453 case LabelPosition_Above : aCenterVOffset = aTextHeight / 2.0 + aMarginSize; break;
454 case LabelPosition_Below : aCenterVOffset = -aTextHeight / 2.0 - aMarginSize; break;
457 // compute shape offset transformation
458 Standard_Real aShapeHOffset = aCenterHOffset - aTextWidth / 2.0;
459 Standard_Real aShapeVOffset = aCenterVOffset - aTextHeight / 2.0;
461 // center shape in its bounding box (suppress border spacing added by FT_Font)
463 BRepBndLib::AddClose (aTextShape, aShapeBnd);
465 Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
466 aShapeBnd.Get (aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
468 Standard_Real aXalign = aTextWidth * 0.5 - (aXmax + aXmin) * 0.5;
469 Standard_Real aYalign = aTextHeight * 0.5 - (aYmax + aYmin) * 0.5;
470 aShapeHOffset += aXalign;
471 aShapeVOffset += aYalign;
473 gp_Trsf anOffsetTrsf;
474 anOffsetTrsf.SetTranslation (gp::Origin(), gp_Pnt (aShapeHOffset, aShapeVOffset, 0.0));
475 aTextShape.Move (anOffsetTrsf);
477 // transform text to myWorkingPlane coordinate system
478 gp_Ax3 aTextCoordSystem (theTextPos, GetPlane().Axis().Direction(), aTextDir);
479 gp_Trsf aTextPlaneTrsf;
480 aTextPlaneTrsf.SetTransformation (aTextCoordSystem, gp_Ax3 (gp::XOY()));
481 aTextShape.Move (aTextPlaneTrsf);
483 // set text flipping anchors
484 gp_Trsf aCenterOffsetTrsf;
485 gp_Pnt aCenterOffset (aCenterHOffset, aCenterVOffset, 0.0);
486 aCenterOffsetTrsf.SetTranslation (gp::Origin(), aCenterOffset);
488 gp_Pnt aCenterOfLabel (gp::Origin());
489 aCenterOfLabel.Transform (aCenterOffsetTrsf);
490 aCenterOfLabel.Transform (aTextPlaneTrsf);
492 gp_Ax2 aFlippingAxes (aCenterOfLabel, GetPlane().Axis().Direction(), aTextDir);
493 Prs3d_Root::CurrentGroup (thePresentation)->SetFlippingOptions (Standard_True, aFlippingAxes);
496 if (myDrawer->DimensionAspect()->IsTextShaded())
498 // Setting text shading and color parameters
499 if (!myDrawer->HasOwnShadingAspect())
501 myDrawer->SetShadingAspect (new Prs3d_ShadingAspect());
504 Graphic3d_MaterialAspect aShadeMat (Graphic3d_NOM_DEFAULT);
505 aShadeMat.SetReflectionModeOff (Graphic3d_TOR_AMBIENT);
506 aShadeMat.SetReflectionModeOff (Graphic3d_TOR_DIFFUSE);
507 aShadeMat.SetReflectionModeOff (Graphic3d_TOR_SPECULAR);
508 myDrawer->ShadingAspect()->Aspect()->SetInteriorColor (aColor);
509 myDrawer->ShadingAspect()->Aspect()->SetBackInteriorColor (aColor);
510 myDrawer->ShadingAspect()->SetMaterial (aShadeMat);
513 StdPrs_ShadedShape::Add (thePresentation, aTextShape, myDrawer);
517 // Setting color for text
518 if (!myDrawer->HasOwnFreeBoundaryAspect())
520 myDrawer->SetFreeBoundaryAspect (new Prs3d_LineAspect (aColor, Aspect_TOL_SOLID, 1.0));
523 myDrawer->FreeBoundaryAspect()->Aspect()->SetColor (aColor);
526 StdPrs_WFShape::Add (thePresentation, aTextShape, myDrawer);
528 Prs3d_Root::CurrentGroup (thePresentation)->SetFlippingOptions (Standard_False, gp_Ax2());
530 mySelectionGeom.TextPos = aCenterOfLabel;
531 mySelectionGeom.TextDir = aTextDir;
532 mySelectionGeom.TextWidth = aTextWidth + aMarginSize * 2.0;
533 mySelectionGeom.TextHeight = aTextHeight;
538 // generate primitives for 2D text
539 myDrawer->DimensionAspect()->TextAspect()->Aspect()->SetDisplayType (Aspect_TODT_DIMENSION);
541 Prs3d_Text::Draw (thePresentation,
542 myDrawer->DimensionAspect()->TextAspect(),
546 mySelectionGeom.TextPos = theTextPos;
547 mySelectionGeom.TextDir = theTextDir;
548 mySelectionGeom.TextWidth = 0.0;
549 mySelectionGeom.TextHeight = 0.0;
552 //=======================================================================
553 //function : DrawExtension
555 //=======================================================================
556 void AIS_Dimension::DrawExtension (const Handle(Prs3d_Presentation)& thePresentation,
557 const Standard_Real theExtensionSize,
558 const gp_Pnt& theExtensionStart,
559 const gp_Dir& theExtensionDir,
560 const TCollection_ExtendedString& theLabelString,
561 const Standard_Real theLabelWidth,
562 const Standard_Integer theMode,
563 const Standard_Integer theLabelPosition)
565 // reference line for extension starting at its connection point
566 gp_Lin anExtensionLine (theExtensionStart, theExtensionDir);
568 Standard_Boolean hasLabel = theLabelString.Length() > 0;
569 if (hasLabel && (theMode == ComputeMode_All || theMode == ComputeMode_Text))
571 // compute text primitives; get its model width
572 gp_Pnt aTextPos = ElCLib::Value (theExtensionSize, anExtensionLine);
573 gp_Dir aTextDir = theExtensionDir;
575 DrawText (thePresentation,
582 if (theMode != ComputeMode_All && theMode != ComputeMode_Line)
587 Standard_Boolean isShortLine = !myDrawer->DimensionAspect()->IsText3d()
588 || theLabelPosition & LabelPosition_VCenter;
590 // compute graphical primitives and sensitives for extension line
591 gp_Pnt anExtStart = theExtensionStart;
592 gp_Pnt anExtEnd = !hasLabel || isShortLine
593 ? ElCLib::Value (theExtensionSize, anExtensionLine)
594 : ElCLib::Value (theExtensionSize + theLabelWidth, anExtensionLine);
596 // add graphical primitives
597 Handle(Graphic3d_ArrayOfSegments) anExtPrimitive = new Graphic3d_ArrayOfSegments (2);
598 anExtPrimitive->AddVertex (anExtStart);
599 anExtPrimitive->AddVertex (anExtEnd);
601 // add selection primitives
602 SelectionGeometry::Curve& aSensitiveCurve = mySelectionGeom.NewCurve();
603 aSensitiveCurve.Append (anExtStart);
604 aSensitiveCurve.Append (anExtEnd);
606 if (!myDrawer->DimensionAspect()->IsText3d() && theMode == ComputeMode_All)
608 Prs3d_Root::CurrentGroup (thePresentation)->SetStencilTestOptions (Standard_True);
610 Handle(Graphic3d_AspectLine3d) aDimensionLineStyle = myDrawer->DimensionAspect()->LineAspect()->Aspect();
611 Prs3d_Root::CurrentGroup (thePresentation)->SetPrimitivesAspect (aDimensionLineStyle);
612 Prs3d_Root::CurrentGroup (thePresentation)->AddPrimitiveArray (anExtPrimitive);
613 if (!myDrawer->DimensionAspect()->IsText3d() && theMode == ComputeMode_All)
615 Prs3d_Root::CurrentGroup (thePresentation)->SetStencilTestOptions (Standard_False);
619 //=======================================================================
620 //function : DrawLinearDimension
622 //=======================================================================
623 void AIS_Dimension::DrawLinearDimension (const Handle(Prs3d_Presentation)& thePresentation,
624 const Standard_Integer theMode,
625 const gp_Pnt& theFirstPoint,
626 const gp_Pnt& theSecondPoint,
627 const Standard_Boolean theIsOneSide)
629 // do not build any dimension for equal points
630 if (theFirstPoint.IsEqual (theSecondPoint, Precision::Confusion()))
632 Standard_ProgramError::Raise ("Can not build presentation for equal points.");
635 Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
637 // For extensions we need to know arrow size, text size and extension size: get it from aspect
638 Quantity_Length anArrowLength = aDimensionAspect->ArrowAspect()->Length();
639 Standard_Real anExtensionSize = aDimensionAspect->ExtensionSize();
640 // prepare label string and compute its geometrical width
641 Standard_Real aLabelWidth;
642 TCollection_ExtendedString aLabelString = GetValueString (aLabelWidth);
644 // add margins to cut dimension lines for 3d text
645 if (aDimensionAspect->IsText3d())
647 aLabelWidth += aDimensionAspect->TextAspect()->Height() * THE_3D_TEXT_MARGIN * 2.0;
650 // handle user-defined and automatic arrow placement
651 Standard_Boolean isArrowsExternal = Standard_False;
652 Standard_Integer aLabelPosition = LabelPosition_None;
654 Prs3d_DimensionTextHorizontalPosition aHorisontalTextPos = aDimensionAspect->TextHorizontalPosition();
655 if (IsTextPositionCustom())
657 if (!AdjustParametersForLinear (myFixedTextPosition, theFirstPoint, theSecondPoint,
658 anExtensionSize, aHorisontalTextPos, myFlyout, myPlane, myIsPlaneCustom))
660 Standard_ProgramError::Raise ("Can not adjust plane to the custom label position.");
664 FitTextAlignmentForLinear (theFirstPoint, theSecondPoint, theIsOneSide, aHorisontalTextPos,
665 aLabelPosition, isArrowsExternal);
667 // compute dimension line points
668 gp_Ax1 aPlaneNormal = GetPlane().Axis();
669 gp_Dir aTargetPointsVector = gce_MakeDir (theFirstPoint, theSecondPoint);
671 // compute flyout direction vector
672 gp_Dir aFlyoutVector = aPlaneNormal.Direction() ^ aTargetPointsVector;
674 // create lines for layouts
675 gp_Lin aLine1 (theFirstPoint, aFlyoutVector);
676 gp_Lin aLine2 (theSecondPoint, aFlyoutVector);
678 // Get flyout end points
679 gp_Pnt aLineBegPoint = ElCLib::Value (ElCLib::Parameter (aLine1, theFirstPoint) + GetFlyout(), aLine1);
680 gp_Pnt aLineEndPoint = ElCLib::Value (ElCLib::Parameter (aLine2, theSecondPoint) + GetFlyout(), aLine2);
682 gp_Lin aDimensionLine = gce_MakeLin (aLineBegPoint, aLineEndPoint);
684 // compute arrows positions and directions
685 gp_Dir aFirstArrowDir = aDimensionLine.Direction().Reversed();
686 gp_Dir aSecondArrowDir = aDimensionLine.Direction();
687 gp_Dir aFirstExtensionDir = aDimensionLine.Direction().Reversed();
688 gp_Dir aSecondExtensionDir = aDimensionLine.Direction();
690 gp_Pnt aFirstArrowBegin (0.0, 0.0, 0.0);
691 gp_Pnt aFirstArrowEnd (0.0, 0.0, 0.0);
692 gp_Pnt aSecondArrowBegin (0.0, 0.0, 0.0);
693 gp_Pnt aSecondArrowEnd (0.0, 0.0, 0.0);
695 if (isArrowsExternal)
697 aFirstArrowDir.Reverse();
698 aSecondArrowDir.Reverse();
701 aFirstArrowBegin = aLineBegPoint;
702 aSecondArrowBegin = aLineEndPoint;
703 aFirstArrowEnd = aLineBegPoint.Translated (-gp_Vec (aFirstArrowDir).Scaled (anArrowLength));
704 aSecondArrowEnd = aLineEndPoint.Translated (-gp_Vec (aSecondArrowDir).Scaled (anArrowLength));
706 gp_Pnt aCenterLineBegin = isArrowsExternal
707 ? aLineBegPoint : aFirstArrowEnd;
709 gp_Pnt aCenterLineEnd = isArrowsExternal || theIsOneSide
710 ? aLineEndPoint : aSecondArrowEnd;
713 switch (aLabelPosition & LabelPosition_HMask)
715 // ------------------------------------------------------------------------ //
717 // -------------------------------------------------------------------------//
718 case LabelPosition_HCenter:
720 // add label on dimension or extension line to presentation
721 Prs3d_Root::NewGroup (thePresentation);
723 gp_Pnt aTextPos = IsTextPositionCustom() ? myFixedTextPosition
724 : (aCenterLineBegin.XYZ() + aCenterLineEnd.XYZ()) * 0.5;
725 gp_Dir aTextDir = aDimensionLine.Direction();
727 // add text primitives
728 if (theMode == ComputeMode_All || theMode == ComputeMode_Text)
730 DrawText (thePresentation,
737 // add dimension line primitives
738 if (theMode == ComputeMode_All || theMode == ComputeMode_Line)
740 Standard_Boolean isLineBreak = aDimensionAspect->TextVerticalPosition() == Prs3d_DTVP_Center
741 && aDimensionAspect->IsText3d();
743 Handle(Graphic3d_ArrayOfSegments) aPrimSegments = new Graphic3d_ArrayOfSegments (isLineBreak ? 4 : 2);
745 // compute continuous or sectioned main line segments
748 Standard_Real aPTextPosition = ElCLib::Parameter (aDimensionLine, aTextPos);
749 gp_Pnt aSection1Beg = aCenterLineBegin;
750 gp_Pnt aSection1End = ElCLib::Value (aPTextPosition - (aLabelWidth * 0.5), aDimensionLine);
751 gp_Pnt aSection2Beg = ElCLib::Value (aPTextPosition + (aLabelWidth * 0.5), aDimensionLine);
752 gp_Pnt aSection2End = aCenterLineEnd;
754 aPrimSegments->AddVertex (aSection1Beg);
755 aPrimSegments->AddVertex (aSection1End);
756 aPrimSegments->AddVertex (aSection2Beg);
757 aPrimSegments->AddVertex (aSection2End);
759 SelectionGeometry::Curve& aLeftSensitiveCurve = mySelectionGeom.NewCurve();
760 SelectionGeometry::Curve& aRightSensitiveCurve = mySelectionGeom.NewCurve();
761 aLeftSensitiveCurve.Append (aSection1Beg);
762 aLeftSensitiveCurve.Append (aSection1End);
763 aRightSensitiveCurve.Append (aSection2Beg);
764 aRightSensitiveCurve.Append (aSection2End);
768 aPrimSegments->AddVertex (aCenterLineBegin);
769 aPrimSegments->AddVertex (aCenterLineEnd);
771 SelectionGeometry::Curve& aSensitiveCurve = mySelectionGeom.NewCurve();
772 aSensitiveCurve.Append (aCenterLineBegin);
773 aSensitiveCurve.Append (aCenterLineEnd);
776 // set text label justification
777 Graphic3d_VerticalTextAlignment aTextJustificaton = Graphic3d_VTA_BOTTOM;
778 switch (aLabelPosition & LabelPosition_VMask)
780 case LabelPosition_Above :
781 case LabelPosition_VCenter : aTextJustificaton = Graphic3d_VTA_BOTTOM; break;
782 case LabelPosition_Below : aTextJustificaton = Graphic3d_VTA_TOP; break;
784 aDimensionAspect->TextAspect()->SetVerticalJustification (aTextJustificaton);
786 // main dimension line, short extension
787 if (!aDimensionAspect->IsText3d() && theMode == ComputeMode_All)
789 Prs3d_Root::CurrentGroup (thePresentation)->SetStencilTestOptions (Standard_True);
791 Prs3d_Root::CurrentGroup (thePresentation)->SetPrimitivesAspect (aDimensionAspect->LineAspect()->Aspect());
792 Prs3d_Root::CurrentGroup (thePresentation)->AddPrimitiveArray (aPrimSegments);
793 if (!aDimensionAspect->IsText3d() && theMode == ComputeMode_All)
795 Prs3d_Root::CurrentGroup (thePresentation)->SetStencilTestOptions (Standard_False);
798 // add arrows to presentation
799 Prs3d_Root::NewGroup (thePresentation);
801 DrawArrow (thePresentation, aFirstArrowBegin, aFirstArrowDir);
804 DrawArrow (thePresentation, aSecondArrowBegin, aSecondArrowDir);
807 if (!isArrowsExternal)
812 // add arrow extension lines to presentation
813 Prs3d_Root::NewGroup (thePresentation);
815 DrawExtension (thePresentation, aDimensionAspect->ArrowTailSize(),
816 aFirstArrowEnd, aFirstExtensionDir,
817 THE_EMPTY_LABEL, 0.0, theMode, LabelPosition_None);
820 DrawExtension (thePresentation, aDimensionAspect->ArrowTailSize(),
821 aSecondArrowEnd, aSecondExtensionDir,
822 THE_EMPTY_LABEL, 0.0, theMode, LabelPosition_None);
828 // ------------------------------------------------------------------------ //
830 // -------------------------------------------------------------------------//
832 case LabelPosition_Left:
834 // add label on dimension or extension line to presentation
835 Prs3d_Root::NewGroup (thePresentation);
837 // Left extension with the text
838 DrawExtension (thePresentation, anExtensionSize,
848 // add dimension line primitives
849 if (theMode == ComputeMode_All || theMode == ComputeMode_Line)
851 // add central dimension line
852 Prs3d_Root::NewGroup (thePresentation);
854 // add graphical primitives
855 Handle(Graphic3d_ArrayOfSegments) aPrimSegments = new Graphic3d_ArrayOfSegments (2);
856 aPrimSegments->AddVertex (aCenterLineBegin);
857 aPrimSegments->AddVertex (aCenterLineEnd);
859 Prs3d_Root::CurrentGroup (thePresentation)->SetPrimitivesAspect (aDimensionAspect->LineAspect()->Aspect());
860 Prs3d_Root::CurrentGroup (thePresentation)->AddPrimitiveArray (aPrimSegments);
862 // add selection primitives
863 SelectionGeometry::Curve& aSensitiveCurve = mySelectionGeom.NewCurve();
864 aSensitiveCurve.Append (aCenterLineBegin);
865 aSensitiveCurve.Append (aCenterLineEnd);
867 // add arrows to presentation
868 Prs3d_Root::NewGroup (thePresentation);
870 DrawArrow (thePresentation, aFirstArrowBegin, aFirstArrowDir);
873 DrawArrow (thePresentation, aSecondArrowBegin, aSecondArrowDir);
876 if (!isArrowsExternal || theIsOneSide)
881 // add extension lines for external arrows
882 Prs3d_Root::NewGroup (thePresentation);
884 DrawExtension (thePresentation, aDimensionAspect->ArrowTailSize(),
885 aSecondArrowEnd, aSecondExtensionDir,
886 THE_EMPTY_LABEL, 0.0, theMode, LabelPosition_None);
891 // ------------------------------------------------------------------------ //
893 // -------------------------------------------------------------------------//
895 case LabelPosition_Right:
897 // add label on dimension or extension line to presentation
898 Prs3d_Root::NewGroup (thePresentation);
900 // Right extension with text
901 DrawExtension (thePresentation, anExtensionSize,
906 aLabelString, aLabelWidth,
910 if (theMode == ComputeMode_All || theMode == ComputeMode_Line)
912 // add central dimension line
913 Prs3d_Root::NewGroup (thePresentation);
915 // add graphical primitives
916 Handle(Graphic3d_ArrayOfSegments) aPrimSegments = new Graphic3d_ArrayOfSegments (2);
917 aPrimSegments->AddVertex (aCenterLineBegin);
918 aPrimSegments->AddVertex (aCenterLineEnd);
919 Prs3d_Root::CurrentGroup (thePresentation)->SetPrimitivesAspect (aDimensionAspect->LineAspect()->Aspect());
920 Prs3d_Root::CurrentGroup (thePresentation)->AddPrimitiveArray (aPrimSegments);
922 // add selection primitives
923 SelectionGeometry::Curve& aSensitiveCurve = mySelectionGeom.NewCurve();
924 aSensitiveCurve.Append (aCenterLineBegin);
925 aSensitiveCurve.Append (aCenterLineEnd);
927 // add arrows to presentation
928 Prs3d_Root::NewGroup (thePresentation);
930 DrawArrow (thePresentation, aSecondArrowBegin, aSecondArrowDir);
933 DrawArrow (thePresentation, aFirstArrowBegin, aFirstArrowDir);
936 if (!isArrowsExternal || theIsOneSide)
941 // add extension lines for external arrows
942 Prs3d_Root::NewGroup (thePresentation);
944 DrawExtension (thePresentation, aDimensionAspect->ArrowTailSize(),
945 aFirstArrowEnd, aFirstExtensionDir,
946 THE_EMPTY_LABEL, 0.0, theMode, LabelPosition_None);
953 // add flyout lines to presentation
954 if (theMode == ComputeMode_All)
956 Prs3d_Root::NewGroup (thePresentation);
958 Handle(Graphic3d_ArrayOfSegments) aPrimSegments = new Graphic3d_ArrayOfSegments(4);
959 aPrimSegments->AddVertex (theFirstPoint);
960 aPrimSegments->AddVertex (aLineBegPoint);
962 aPrimSegments->AddVertex (theSecondPoint);
963 aPrimSegments->AddVertex (aLineEndPoint);
965 Prs3d_Root::CurrentGroup (thePresentation)->SetPrimitivesAspect (aDimensionAspect->LineAspect()->Aspect());
966 Prs3d_Root::CurrentGroup (thePresentation)->AddPrimitiveArray (aPrimSegments);
969 mySelectionGeom.IsComputed = Standard_True;
972 //=======================================================================
973 //function : ComputeLinearFlyouts
975 //=======================================================================
976 void AIS_Dimension::ComputeLinearFlyouts (const Handle(SelectMgr_Selection)& theSelection,
977 const Handle(SelectMgr_EntityOwner)& theOwner,
978 const gp_Pnt& theFirstPoint,
979 const gp_Pnt& theSecondPoint)
981 // count flyout direction
982 gp_Ax1 aPlaneNormal = GetPlane().Axis();
983 gp_Dir aTargetPointsVector = gce_MakeDir (theFirstPoint, theSecondPoint);
985 // count a flyout direction vector.
986 gp_Dir aFlyoutVector = aPlaneNormal.Direction() ^ aTargetPointsVector;
988 // create lines for layouts
989 gp_Lin aLine1 (theFirstPoint, aFlyoutVector);
990 gp_Lin aLine2 (theSecondPoint, aFlyoutVector);
992 // get flyout end points
993 gp_Pnt aFlyoutEnd1 = ElCLib::Value (ElCLib::Parameter (aLine1, theFirstPoint) + GetFlyout(), aLine1);
994 gp_Pnt aFlyoutEnd2 = ElCLib::Value (ElCLib::Parameter (aLine2, theSecondPoint) + GetFlyout(), aLine2);
996 // fill sensitive entity for flyouts
997 Handle(Select3D_SensitiveGroup) aSensitiveEntity = new Select3D_SensitiveGroup (theOwner);
998 aSensitiveEntity->Add (new Select3D_SensitiveSegment (theOwner, theFirstPoint, aFlyoutEnd1));
999 aSensitiveEntity->Add (new Select3D_SensitiveSegment (theOwner, theSecondPoint, aFlyoutEnd2));
1000 theSelection->Add (aSensitiveEntity);
1003 //=======================================================================
1004 //function : CircleFromPlanarFace
1005 //purpose : if possible computes circle from planar face
1006 //=======================================================================
1007 Standard_Boolean AIS_Dimension::CircleFromPlanarFace (const TopoDS_Face& theFace,
1008 Handle(Geom_Curve)& theCurve,
1009 gp_Pnt& theFirstPoint,
1010 gp_Pnt& theLastPoint)
1012 TopExp_Explorer anIt (theFace, TopAbs_EDGE);
1013 for ( ; anIt.More(); anIt.Next())
1015 TopoDS_Edge aCurEdge = TopoDS::Edge (anIt.Current());
1016 if (AIS::ComputeGeometry (aCurEdge, theCurve, theFirstPoint, theLastPoint))
1018 if (theCurve->IsInstance (STANDARD_TYPE(Geom_Circle)))
1020 return Standard_True;
1024 return Standard_False;
1027 //=======================================================================
1028 //function : CircleFromEdge
1029 //purpose : if possible computes circle from edge
1030 //=======================================================================
1031 Standard_Boolean AIS_Dimension::CircleFromEdge (const TopoDS_Edge& theEdge,
1033 gp_Pnt& theFirstPoint,
1034 gp_Pnt& theLastPoint)
1036 BRepAdaptor_Curve anAdaptedCurve (theEdge);
1037 switch (anAdaptedCurve.GetType())
1039 case GeomAbs_Circle:
1041 theCircle = anAdaptedCurve.Circle();
1044 case GeomAbs_Ellipse:
1046 gp_Elips anEll = anAdaptedCurve.Ellipse();
1047 if ((anEll.MinorRadius() - anEll.MajorRadius()) >= Precision::Confusion())
1049 return Standard_False;
1051 theCircle = gp_Circ(anEll.Position(),anEll.MinorRadius());
1055 case GeomAbs_Hyperbola:
1056 case GeomAbs_Parabola:
1057 case GeomAbs_BezierCurve:
1058 case GeomAbs_BSplineCurve:
1059 case GeomAbs_OtherCurve:
1061 return Standard_False;
1064 theFirstPoint = anAdaptedCurve.Value (anAdaptedCurve.FirstParameter());
1065 theLastPoint = anAdaptedCurve.Value (anAdaptedCurve.LastParameter());
1066 return Standard_True;
1069 //=======================================================================
1070 //function : InitCircularDimension
1072 //=======================================================================
1073 Standard_Boolean AIS_Dimension::InitCircularDimension (const TopoDS_Shape& theShape,
1075 gp_Pnt& theMiddleArcPoint,
1076 Standard_Boolean& theIsClosed)
1079 Handle(Geom_Surface) aBasisSurf;
1080 AIS_KindOfSurface aSurfType = AIS_KOS_OtherSurface;
1081 gp_Pnt aFirstPoint, aLastPoint;
1082 Standard_Real anOffset = 0.0;
1083 Standard_Real aFirstParam = 0.0;
1084 Standard_Real aLastParam = 0.0;
1086 // Discover circular geometry
1087 switch (theShape.ShapeType())
1091 AIS::GetPlaneFromFace (TopoDS::Face (theShape), aPln, aBasisSurf, aSurfType, anOffset);
1093 if (aSurfType == AIS_KOS_Plane)
1095 Handle(Geom_Curve) aCurve;
1096 if (!CircleFromPlanarFace (TopoDS::Face (theShape), aCurve, aFirstPoint, aLastPoint))
1098 return Standard_False;
1101 theCircle = Handle(Geom_Circle)::DownCast (aCurve)->Circ();
1106 BRepAdaptor_Surface aSurf1 (TopoDS::Face (theShape));
1107 Standard_Real aFirstU = aSurf1.FirstUParameter();
1108 Standard_Real aLastU = aSurf1.LastUParameter();
1109 Standard_Real aFirstV = aSurf1.FirstVParameter();
1110 Standard_Real aLastV = aSurf1.LastVParameter();
1111 Standard_Real aMidU = (aFirstU + aLastU) * 0.5;
1112 Standard_Real aMidV = (aFirstV + aLastV) * 0.5;
1113 aSurf1.D0 (aMidU, aMidV, aCurPos);
1114 Handle (Adaptor3d_HCurve) aBasisCurve;
1115 Standard_Boolean isExpectedType = Standard_False;
1116 if (aSurfType == AIS_KOS_Cylinder)
1118 isExpectedType = Standard_True;
1122 if (aSurfType == AIS_KOS_Revolution)
1124 aBasisCurve = aSurf1.BasisCurve();
1125 if (aBasisCurve->GetType() == GeomAbs_Line)
1127 isExpectedType = Standard_True;
1130 else if (aSurfType == AIS_KOS_Extrusion)
1132 aBasisCurve = aSurf1.BasisCurve();
1133 if (aBasisCurve->GetType() == GeomAbs_Circle)
1135 isExpectedType = Standard_True;
1140 if (!isExpectedType)
1142 return Standard_False;
1145 Handle(Geom_Curve) aCurve = aBasisSurf->VIso(aMidV);
1146 if (aCurve->DynamicType() == STANDARD_TYPE (Geom_Circle))
1148 theCircle = Handle(Geom_Circle)::DownCast (aCurve)->Circ();
1150 else if (aCurve->DynamicType() == STANDARD_TYPE (Geom_TrimmedCurve))
1152 Handle(Geom_TrimmedCurve) aTrimmedCurve = Handle(Geom_TrimmedCurve)::DownCast (aCurve);
1153 aFirstU = aTrimmedCurve->FirstParameter();
1154 aLastU = aTrimmedCurve->LastParameter();
1155 if (aTrimmedCurve->BasisCurve()->DynamicType() == STANDARD_TYPE (Geom_Circle))
1157 theCircle = Handle(Geom_Circle)::DownCast(aTrimmedCurve->BasisCurve())->Circ();
1162 // Compute a circle from 3 points on "aCurve"
1164 aSurf1.D0 (aFirstU, aMidV, aP1);
1165 aSurf1.D0 (aLastU, aMidV, aP2);
1166 GC_MakeCircle aMkCirc (aP1, aCurPos, aP2);
1167 theCircle = aMkCirc.Value()->Circ();
1170 aFirstPoint = ElCLib::Value (aFirstU, theCircle);
1171 aLastPoint = ElCLib::Value (aLastU, theCircle);
1178 TopExp_Explorer anIt (theShape, TopAbs_EDGE);
1181 anEdge = TopoDS::Edge (anIt.Current());
1183 if (!AIS_Dimension::CircleFromEdge (anEdge, theCircle, aFirstPoint, aLastPoint))
1185 return Standard_False;
1191 TopoDS_Edge anEdge = TopoDS::Edge (theShape);
1192 if (!AIS_Dimension::CircleFromEdge (anEdge, theCircle, aFirstPoint, aLastPoint))
1194 return Standard_False;
1198 case TopAbs_COMPOUND:
1199 case TopAbs_COMPSOLID:
1205 return Standard_False;
1208 theIsClosed = aFirstPoint.IsEqual (aLastPoint, Precision::Confusion());
1210 gp_Pnt aCenter = theCircle.Location();
1212 if (theIsClosed) // Circle
1214 gp_Dir anXDir = theCircle.XAxis().Direction();
1215 theMiddleArcPoint = aCenter.Translated (gp_Vec (anXDir) * theCircle.Radius());
1219 aFirstParam = ElCLib::Parameter (theCircle, aFirstPoint);
1220 aLastParam = ElCLib::Parameter (theCircle, aLastPoint);
1221 if (aFirstParam > aLastParam)
1223 aFirstParam -= 2.0 * M_PI;
1226 Standard_Real aParCurPos = (aFirstParam + aLastParam) * 0.5;
1227 gp_Vec aVec = gp_Vec (aCenter, ElCLib::Value (aParCurPos, theCircle)).Normalized () * theCircle.Radius ();
1228 theMiddleArcPoint = aCenter.Translated (aVec);
1231 return Standard_True;
1234 //=======================================================================
1235 //function : ComputeSelection
1237 //=======================================================================
1238 void AIS_Dimension::ComputeSelection (const Handle(SelectMgr_Selection)& theSelection,
1239 const Standard_Integer theMode)
1241 if (!mySelectionGeom.IsComputed)
1246 AIS_DimensionSelectionMode aSelectionMode = (AIS_DimensionSelectionMode)theMode;
1248 // init appropriate entity owner
1249 Handle(SelectMgr_EntityOwner) aSensitiveOwner;
1251 switch (aSelectionMode)
1253 // neutral selection owner
1255 aSensitiveOwner = new SelectMgr_EntityOwner (this, THE_NEUTRAL_SEL_PRIORITY);
1258 // local selection owners
1261 aSensitiveOwner = new AIS_DimensionOwner (this, aSelectionMode, THE_LOCAL_SEL_PRIORITY);
1265 if (aSelectionMode == AIS_DSM_All || aSelectionMode == AIS_DSM_Line)
1267 // sensitives for dimension line segments
1268 Handle(Select3D_SensitiveGroup) aGroupOfSensitives = new Select3D_SensitiveGroup (aSensitiveOwner);
1270 SelectionGeometry::SeqOfCurves::Iterator aCurveIt (mySelectionGeom.DimensionLine);
1271 for (; aCurveIt.More(); aCurveIt.Next())
1273 const SelectionGeometry::HCurve& aCurveData = aCurveIt.Value();
1275 TColgp_Array1OfPnt aSensitivePnts (1, aCurveData->Length());
1276 for (Standard_Integer aPntIt = 1; aPntIt <= aCurveData->Length(); ++aPntIt)
1278 aSensitivePnts.ChangeValue (aPntIt) = aCurveData->Value (aPntIt);
1281 aGroupOfSensitives->Add (new Select3D_SensitiveCurve (aSensitiveOwner, aSensitivePnts));
1284 Quantity_Length anArrowLength = myDrawer->DimensionAspect()->ArrowAspect()->Length();
1285 Standard_Real anArrowAngle = myDrawer->DimensionAspect()->ArrowAspect()->Angle();
1287 // sensitives for arrows
1288 SelectionGeometry::SeqOfArrows::Iterator anArrowIt (mySelectionGeom.Arrows);
1289 for (; anArrowIt.More(); anArrowIt.Next())
1291 const SelectionGeometry::HArrow& anArrow = anArrowIt.Value();
1293 gp_Pnt aSidePnt1 (gp::Origin());
1294 gp_Pnt aSidePnt2 (gp::Origin());
1295 const gp_Dir& aPlane = GetPlane().Axis().Direction();
1296 const gp_Pnt& aPeak = anArrow->Position;
1297 const gp_Dir& aDir = anArrow->Direction;
1299 // compute points for arrow in plane
1300 PointsForArrow (aPeak, aDir, aPlane, anArrowLength, anArrowAngle, aSidePnt1, aSidePnt2);
1302 aGroupOfSensitives->Add (new Select3D_SensitiveTriangle (aSensitiveOwner, aPeak, aSidePnt1, aSidePnt2));
1304 if (!myDrawer->DimensionAspect()->IsArrows3d())
1309 // compute points for orthogonal sensitive plane
1310 gp_Dir anOrthoPlane = anArrow->Direction.Crossed (aPlane);
1312 PointsForArrow (aPeak, aDir, anOrthoPlane, anArrowLength, anArrowAngle, aSidePnt1, aSidePnt2);
1314 aGroupOfSensitives->Add (new Select3D_SensitiveTriangle (aSensitiveOwner, aPeak, aSidePnt1, aSidePnt2));
1317 theSelection->Add (aGroupOfSensitives);
1320 // sensitives for text element
1321 if (aSelectionMode == AIS_DSM_All || aSelectionMode == AIS_DSM_Text)
1323 Handle(Select3D_SensitiveEntity) aTextSensitive;
1325 gp_Ax2 aTextAxes (mySelectionGeom.TextPos,
1326 GetPlane().Axis().Direction(),
1327 mySelectionGeom.TextDir);
1329 if (myDrawer->DimensionAspect()->IsText3d())
1331 // sensitive planar rectangle for text
1332 Standard_Real aDx = mySelectionGeom.TextWidth * 0.5;
1333 Standard_Real aDy = mySelectionGeom.TextHeight * 0.5;
1335 gp_Trsf aLabelPlane;
1336 aLabelPlane.SetTransformation (aTextAxes, gp::XOY());
1338 TColgp_Array1OfPnt aRectanglePoints(1, 4);
1339 aRectanglePoints.ChangeValue(1) = gp_Pnt (-aDx, -aDy, 0.0).Transformed (aLabelPlane);
1340 aRectanglePoints.ChangeValue(2) = gp_Pnt (-aDx, aDy, 0.0).Transformed (aLabelPlane);
1341 aRectanglePoints.ChangeValue(3) = gp_Pnt ( aDx, aDy, 0.0).Transformed (aLabelPlane);
1342 aRectanglePoints.ChangeValue(4) = gp_Pnt ( aDx, -aDy, 0.0).Transformed (aLabelPlane);
1344 Poly_Array1OfTriangle aTriangles(1, 2);
1345 aTriangles.ChangeValue(1) = Poly_Triangle(1, 2, 3);
1346 aTriangles.ChangeValue(2) = Poly_Triangle(1, 3, 4);
1348 Handle(Poly_Triangulation) aRectanglePoly =
1349 new Poly_Triangulation(aRectanglePoints, aTriangles);
1352 new Select3D_SensitiveTriangulation (aSensitiveOwner, aRectanglePoly, TopLoc_Location(), Standard_True);
1356 gp_Circ aTextGeom (aTextAxes, mySelToleranceForText2d != 0.0
1357 ? mySelToleranceForText2d : 1.0);
1359 Handle(Geom_Circle) aSensGeom = new Geom_Circle (aTextGeom);
1361 aTextSensitive = new Select3D_SensitiveCircle (aSensitiveOwner, aSensGeom, Standard_True);
1364 theSelection->Add (aTextSensitive);
1367 // callback for flyout sensitive calculation
1368 if (aSelectionMode == AIS_DSM_All)
1370 ComputeFlyoutSelection (theSelection, aSensitiveOwner);
1374 //=======================================================================
1375 //function : PointsForArrow
1377 //=======================================================================
1378 void AIS_Dimension::PointsForArrow (const gp_Pnt& thePeakPnt,
1379 const gp_Dir& theDirection,
1380 const gp_Dir& thePlane,
1381 const Standard_Real theArrowLength,
1382 const Standard_Real theArrowAngle,
1383 gp_Pnt& theSidePnt1,
1384 gp_Pnt& theSidePnt2)
1386 gp_Lin anArrowLin (thePeakPnt, theDirection.Reversed());
1387 gp_Pnt anArrowEnd = ElCLib::Value (theArrowLength, anArrowLin);
1388 gp_Lin anEdgeLin (anArrowEnd, theDirection.Crossed (thePlane));
1390 Standard_Real anEdgeLength = Tan (theArrowAngle) * theArrowLength;
1392 theSidePnt1 = ElCLib::Value ( anEdgeLength, anEdgeLin);
1393 theSidePnt2 = ElCLib::Value (-anEdgeLength, anEdgeLin);
1396 //=======================================================================
1397 //function : GetTextPositionForLinear
1399 //=======================================================================
1400 gp_Pnt AIS_Dimension::GetTextPositionForLinear (const gp_Pnt& theFirstPoint,
1401 const gp_Pnt& theSecondPoint,
1402 const Standard_Boolean theIsOneSide) const
1406 return gp::Origin();
1409 gp_Pnt aTextPosition (gp::Origin());
1411 Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
1413 // Get label alignment and arrow orientation.
1414 Standard_Integer aLabelPosition = 0;
1415 Standard_Boolean isArrowsExternal = Standard_False;
1416 FitTextAlignmentForLinear (theFirstPoint, theSecondPoint, theIsOneSide,
1417 aDimensionAspect->TextHorizontalPosition(),
1418 aLabelPosition, isArrowsExternal);
1420 // Compute dimension line points.
1421 gp_Dir aPlaneNormal = GetPlane().Axis().Direction();
1422 gp_Vec aTargetPointsVec (theFirstPoint, theSecondPoint);
1424 // Compute flyout direction vector
1425 gp_Dir aFlyoutVector = aPlaneNormal ^ gp_Dir (aTargetPointsVec);
1427 // create lines for layouts
1428 gp_Lin aLine1 (theFirstPoint, aFlyoutVector);
1429 gp_Lin aLine2 (theSecondPoint, aFlyoutVector);
1430 // Get flyout end points
1431 gp_Pnt aLineBegPoint = ElCLib::Value (ElCLib::Parameter (aLine1, theFirstPoint) + GetFlyout(), aLine1);
1432 gp_Pnt aLineEndPoint = ElCLib::Value (ElCLib::Parameter (aLine2, theSecondPoint) + GetFlyout(), aLine2);
1434 // Get text position.
1435 switch (aLabelPosition & LabelPosition_HMask)
1437 case LabelPosition_Left:
1439 gp_Dir aTargetPointsDir = gce_MakeDir (theFirstPoint, theSecondPoint);
1440 Standard_Real anExtensionSize = aDimensionAspect->ExtensionSize();
1442 Standard_Real anOffset = isArrowsExternal
1443 ? anExtensionSize + aDimensionAspect->ArrowAspect()->Length()
1445 gp_Vec anExtensionVec = gp_Vec (aTargetPointsDir) * -anOffset;
1446 aTextPosition = aLineEndPoint.Translated (anExtensionVec);
1449 case LabelPosition_Right:
1451 gp_Dir aTargetPointsDir = gce_MakeDir (theFirstPoint, theSecondPoint);
1452 Standard_Real anExtensionSize = aDimensionAspect->ExtensionSize();
1454 Standard_Real anOffset = isArrowsExternal
1455 ? anExtensionSize + aDimensionAspect->ArrowAspect()->Length()
1457 gp_Vec anExtensionVec = gp_Vec (aTargetPointsDir) * anOffset;
1458 aTextPosition = aLineBegPoint.Translated (anExtensionVec);
1461 case LabelPosition_HCenter:
1463 aTextPosition = (aLineBegPoint.XYZ() + aLineEndPoint.XYZ()) * 0.5;
1468 return aTextPosition;
1471 //=======================================================================
1472 //function : AdjustParametersForLinear
1474 //=======================================================================
1475 Standard_Boolean AIS_Dimension::AdjustParametersForLinear (const gp_Pnt& theTextPos,
1476 const gp_Pnt& theFirstPoint,
1477 const gp_Pnt& theSecondPoint,
1478 Standard_Real& theExtensionSize,
1479 Prs3d_DimensionTextHorizontalPosition& theAlignment,
1480 Standard_Real& theFlyout,
1482 Standard_Boolean& theIsPlaneOld) const
1484 Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
1485 Standard_Real anArrowLength = aDimensionAspect->ArrowAspect()->Length();
1487 gp_Dir aTargetPointsDir = gce_MakeDir (theFirstPoint, theSecondPoint);
1488 gp_Vec aTargetPointsVec (theFirstPoint, theSecondPoint);
1490 // Don't set new plane if the text position lies on the attachment points line.
1491 gp_Lin aTargetPointsLin (theFirstPoint, aTargetPointsDir);
1492 if (!aTargetPointsLin.Contains (theTextPos, Precision::Confusion()))
1494 //Set new automatic plane.
1495 thePlane = gce_MakePln (theTextPos, theFirstPoint, theSecondPoint);
1496 theIsPlaneOld = Standard_False;
1499 // Compute flyout direction vector.
1500 gp_Dir aPlaneNormal = GetPlane().Axis().Direction();
1501 gp_Dir aPositiveFlyout = aPlaneNormal ^ aTargetPointsDir;
1503 // Additional check of collinearity of the plane normal and attachment points vector.
1504 if (aPlaneNormal.IsParallel (aTargetPointsDir, Precision::Angular()))
1506 return Standard_False;
1510 gp_Vec aFirstToTextVec (theFirstPoint, theTextPos);
1512 Standard_Real aCos = aFirstToTextVec.Normalized() * gp_Vec (aTargetPointsDir);
1514 gp_Pnt aTextPosProj = theFirstPoint.Translated
1515 (gp_Vec (aTargetPointsDir) * aFirstToTextVec.Magnitude() * aCos);
1517 // Compute flyout value and direction.
1518 gp_Vec aFlyoutVector = gp_Vec (aTextPosProj, theTextPos);
1521 if (aFlyoutVector.Magnitude() > Precision::Confusion())
1523 theFlyout = gp_Dir (aFlyoutVector).IsOpposite (aPositiveFlyout, Precision::Angular())
1524 ? -aFlyoutVector.Magnitude()
1525 : aFlyoutVector.Magnitude();
1528 // Compute attach points (through which main dimension line passes).
1529 gp_Pnt aFirstAttach = theFirstPoint.Translated (aFlyoutVector);
1530 gp_Pnt aSecondAttach = theSecondPoint.Translated (aFlyoutVector);
1532 // Set horizontal text alignment.
1535 theAlignment = Prs3d_DTHP_Left;
1537 Standard_Real aNewExtSize = theTextPos.Distance (aFirstAttach) - anArrowLength;
1538 theExtensionSize = aNewExtSize < 0.0 ? 0.0 : aNewExtSize;
1540 else if (aTextPosProj.Distance (theFirstPoint) > theFirstPoint.Distance (theSecondPoint))
1542 theAlignment = Prs3d_DTHP_Right;
1544 Standard_Real aNewExtSize = theTextPos.Distance (aSecondAttach) - anArrowLength;
1545 theExtensionSize = aNewExtSize < 0.0 ? 0.0 : aNewExtSize;
1549 theAlignment = Prs3d_DTHP_Center;
1551 return Standard_True;
1554 //=======================================================================
1555 //function : FitTextAlignmentForLinear
1557 //=======================================================================
1558 void AIS_Dimension::FitTextAlignmentForLinear (const gp_Pnt& theFirstPoint,
1559 const gp_Pnt& theSecondPoint,
1560 const Standard_Boolean theIsOneSide,
1561 const Prs3d_DimensionTextHorizontalPosition& theHorizontalTextPos,
1562 Standard_Integer& theLabelPosition,
1563 Standard_Boolean& theIsArrowsExternal) const
1565 theLabelPosition = LabelPosition_None;
1566 theIsArrowsExternal = Standard_False;
1568 // Compute dimension line points
1569 gp_Ax1 aPlaneNormal = GetPlane().Axis();
1570 gp_Dir aTargetPointsVector = gce_MakeDir (theFirstPoint, theSecondPoint);
1572 // compute flyout direction vector
1573 gp_Dir aFlyoutVector = aPlaneNormal.Direction() ^ aTargetPointsVector;
1575 // create lines for layouts
1576 gp_Lin aLine1 (theFirstPoint, aFlyoutVector);
1577 gp_Lin aLine2 (theSecondPoint, aFlyoutVector);
1579 // Get flyout end points
1580 gp_Pnt aLineBegPoint = ElCLib::Value (ElCLib::Parameter (aLine1, theFirstPoint) + GetFlyout(), aLine1);
1581 gp_Pnt aLineEndPoint = ElCLib::Value (ElCLib::Parameter (aLine2, theSecondPoint) + GetFlyout(), aLine2);
1583 Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
1585 // For extensions we need to know arrow size, text size and extension size: get it from aspect
1586 Quantity_Length anArrowLength = aDimensionAspect->ArrowAspect()->Length();
1588 // prepare label string and compute its geometrical width
1589 Standard_Real aLabelWidth;
1590 TCollection_ExtendedString aLabelString = GetValueString (aLabelWidth);
1592 // Add margins to cut dimension lines for 3d text
1593 if (aDimensionAspect->IsText3d())
1595 aLabelWidth += aDimensionAspect->TextAspect()->Height() * THE_3D_TEXT_MARGIN * 2.0;
1598 // Handle user-defined and automatic arrow placement
1599 switch (aDimensionAspect->ArrowOrientation())
1601 case Prs3d_DAO_External: theIsArrowsExternal = true; break;
1602 case Prs3d_DAO_Internal: theIsArrowsExternal = false; break;
1605 // Add margin to ensure a small tail between text and arrow
1606 Standard_Real anArrowMargin = aDimensionAspect->IsText3d()
1607 ? aDimensionAspect->TextAspect()->Height() * THE_3D_TEXT_MARGIN
1610 Standard_Real aDimensionWidth = aLineBegPoint.Distance (aLineEndPoint);
1611 Standard_Real anArrowsWidth = theIsOneSide
1612 ? anArrowLength + anArrowMargin
1613 : (anArrowLength + anArrowMargin) * 2.0;
1615 theIsArrowsExternal = aDimensionWidth < aLabelWidth + anArrowsWidth;
1620 // Handle user-defined and automatic text placement
1621 switch (theHorizontalTextPos)
1623 case Prs3d_DTHP_Left : theLabelPosition |= LabelPosition_Left; break;
1624 case Prs3d_DTHP_Right : theLabelPosition |= LabelPosition_Right; break;
1625 case Prs3d_DTHP_Center: theLabelPosition |= LabelPosition_HCenter; break;
1626 case Prs3d_DTHP_Fit:
1628 Standard_Real aDimensionWidth = aLineBegPoint.Distance (aLineEndPoint);
1629 Standard_Real anArrowsWidth = theIsOneSide ? anArrowLength : 2.0 * anArrowLength;
1630 Standard_Real aContentWidth = theIsArrowsExternal ? aLabelWidth : aLabelWidth + anArrowsWidth;
1632 theLabelPosition |= aDimensionWidth < aContentWidth ? LabelPosition_Left : LabelPosition_HCenter;
1637 // Handle vertical text placement options
1638 switch (aDimensionAspect->TextVerticalPosition())
1640 case Prs3d_DTVP_Above : theLabelPosition |= LabelPosition_Above; break;
1641 case Prs3d_DTVP_Below : theLabelPosition |= LabelPosition_Below; break;
1642 case Prs3d_DTVP_Center : theLabelPosition |= LabelPosition_VCenter; break;
1646 //=======================================================================
1647 //function : UnsetFixedTextPosition
1649 //=======================================================================
1650 void AIS_Dimension::UnsetFixedTextPosition()
1652 myIsTextPositionFixed = Standard_False;
1653 myFixedTextPosition = gp::Origin();