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 <PrsDim_Dimension.hxx>
19 #include <PrsDim_DimensionOwner.hxx>
20 #include <AIS_InteractiveContext.hxx>
21 #include <BRepAdaptor_Curve.hxx>
22 #include <BRepAdaptor_Surface.hxx>
23 #include <BRepBndLib.hxx>
24 #include <Bnd_Box.hxx>
26 #include <Font_BRepTextBuilder.hxx>
27 #include <GC_MakeCircle.hxx>
28 #include <Geom_Line.hxx>
29 #include <Geom_TrimmedCurve.hxx>
30 #include <gce_MakeDir.hxx>
31 #include <gce_MakeLin.hxx>
32 #include <gce_MakePln.hxx>
33 #include <Graphic3d_AspectLine3d.hxx>
34 #include <Graphic3d_AspectFillArea3d.hxx>
35 #include <Graphic3d_AspectText3d.hxx>
36 #include <Graphic3d_Group.hxx>
37 #include <Prs3d_Arrow.hxx>
38 #include <Prs3d_ArrowAspect.hxx>
39 #include <Prs3d_Drawer.hxx>
40 #include <Prs3d_LineAspect.hxx>
41 #include <Prs3d_Presentation.hxx>
42 #include <Prs3d_ShadingAspect.hxx>
43 #include <Prs3d_Text.hxx>
44 #include <SelectMgr_EntityOwner.hxx>
45 #include <SelectMgr_Selection.hxx>
46 #include <Select3D_SensitiveCircle.hxx>
47 #include <Select3D_SensitiveGroup.hxx>
48 #include <Select3D_SensitiveCurve.hxx>
49 #include <Select3D_SensitiveSegment.hxx>
50 #include <Select3D_SensitiveTriangle.hxx>
51 #include <Select3D_SensitiveTriangulation.hxx>
52 #include <Poly_Array1OfTriangle.hxx>
53 #include <Poly_Triangulation.hxx>
54 #include <Standard_ProgramError.hxx>
55 #include <StdPrs_ShadedShape.hxx>
56 #include <StdPrs_WFShape.hxx>
57 #include <TCollection_AsciiString.hxx>
58 #include <TCollection_ExtendedString.hxx>
59 #include <TopExp_Explorer.hxx>
61 #include <TopoDS_Edge.hxx>
62 #include <V3d_Viewer.hxx>
63 #include <Units_UnitsDictionary.hxx>
64 #include <UnitsAPI.hxx>
66 IMPLEMENT_STANDARD_RTTIEXT(PrsDim_Dimension, AIS_InteractiveObject)
70 // default text strings
71 static const TCollection_ExtendedString THE_EMPTY_LABEL;
72 static const TCollection_AsciiString THE_UNDEFINED_UNITS;
74 // default text margin and resolution
75 static const Standard_Real THE_3D_TEXT_MARGIN = 0.1;
77 // default selection priorities
78 static const Standard_Integer THE_NEUTRAL_SEL_PRIORITY = 5;
79 static const Standard_Integer THE_LOCAL_SEL_PRIORITY = 6;
82 //=======================================================================
83 //function : Constructor
85 //=======================================================================
86 PrsDim_Dimension::PrsDim_Dimension (const PrsDim_KindOfDimension theType)
87 : AIS_InteractiveObject (),
88 mySelToleranceForText2d(0.0),
89 myValueType (ValueType_Computed),
91 myCustomStringValue (),
92 myIsTextPositionFixed (Standard_False),
93 mySpecialSymbol (' '),
94 myDisplaySpecialSymbol (PrsDim_DisplaySpecialSymbol_No),
95 myGeometryType (GeometryType_UndefShapes),
96 myIsPlaneCustom (Standard_False),
98 myIsGeometryValid (Standard_False),
99 myKindOfDimension (theType)
103 //=======================================================================
104 //function : SetCustomValue
106 //=======================================================================
107 void PrsDim_Dimension::SetCustomValue (const Standard_Real theValue)
109 if (myValueType == ValueType_CustomReal && myCustomValue == theValue)
114 myValueType = ValueType_CustomReal;
115 myCustomValue = theValue;
120 //=======================================================================
121 //function : SetCustomValue
123 //=======================================================================
124 void PrsDim_Dimension::SetCustomValue (const TCollection_ExtendedString& theValue)
126 if (myValueType == ValueType_CustomText && myCustomStringValue == theValue)
131 myValueType = ValueType_CustomText;
132 myCustomStringValue = theValue;
137 //=======================================================================
138 //function : SetUserPlane
140 //=======================================================================
141 void PrsDim_Dimension::SetCustomPlane (const gp_Pln& thePlane)
144 myIsPlaneCustom = Standard_True;
146 // Disable fixed (custom) text position
147 UnsetFixedTextPosition();
149 // Check validity if geometry has been set already.
156 //=======================================================================
157 //function : SetDimensionAspect
159 //=======================================================================
160 void PrsDim_Dimension::SetDimensionAspect (const Handle(Prs3d_DimensionAspect)& theDimensionAspect)
162 myDrawer->SetDimensionAspect (theDimensionAspect);
167 //=======================================================================
168 //function : SetDisplaySpecialSymbol
170 //=======================================================================
171 void PrsDim_Dimension::SetDisplaySpecialSymbol (const PrsDim_DisplaySpecialSymbol theDisplaySpecSymbol)
173 if (myDisplaySpecialSymbol == theDisplaySpecSymbol)
178 myDisplaySpecialSymbol = theDisplaySpecSymbol;
183 //=======================================================================
184 //function : SetSpecialSymbol
186 //=======================================================================
187 void PrsDim_Dimension::SetSpecialSymbol (const Standard_ExtCharacter theSpecialSymbol)
189 if (mySpecialSymbol == theSpecialSymbol)
194 mySpecialSymbol = theSpecialSymbol;
199 //=======================================================================
200 //function : SetSelToleranceForText2d
202 //=======================================================================
203 void PrsDim_Dimension::SetSelToleranceForText2d (const Standard_Real theTol)
205 if (mySelToleranceForText2d == theTol)
210 mySelToleranceForText2d = theTol;
215 //=======================================================================
216 //function : SetFlyout
218 //=======================================================================
219 void PrsDim_Dimension::SetFlyout (const Standard_Real theFlyout)
221 if (myFlyout == theFlyout)
226 myFlyout = theFlyout;
228 // Disable fixed text position
229 UnsetFixedTextPosition();
234 //=======================================================================
235 //function : GetDisplayUnits
237 //=======================================================================
238 const TCollection_AsciiString& PrsDim_Dimension::GetDisplayUnits() const
240 return THE_UNDEFINED_UNITS;
243 //=======================================================================
244 //function : GetModelUnits
246 //=======================================================================
247 const TCollection_AsciiString& PrsDim_Dimension::GetModelUnits() const
249 return THE_UNDEFINED_UNITS;
252 //=======================================================================
253 //function : ValueToDisplayUnits
255 //=======================================================================
256 Standard_Real PrsDim_Dimension::ValueToDisplayUnits() const
258 return UnitsAPI::AnyToAny (GetValue(),
259 GetModelUnits().ToCString(),
260 GetDisplayUnits().ToCString());
263 //=======================================================================
264 //function : GetValueString
266 //=======================================================================
267 TCollection_ExtendedString PrsDim_Dimension::GetValueString (Standard_Real& theWidth) const
269 TCollection_ExtendedString aValueStr;
270 if (myValueType == ValueType_CustomText)
272 aValueStr = myCustomStringValue;
276 // format value string using "sprintf"
277 TCollection_AsciiString aFormatStr = myDrawer->DimensionAspect()->ValueStringFormat();
279 char aFmtBuffer[256];
280 sprintf (aFmtBuffer, aFormatStr.ToCString(), ValueToDisplayUnits());
281 aValueStr = TCollection_ExtendedString (aFmtBuffer);
284 // add units to values string
285 if (myDrawer->DimensionAspect()->IsUnitsDisplayed())
288 aValueStr += TCollection_ExtendedString (GetDisplayUnits());
291 switch (myDisplaySpecialSymbol)
293 case PrsDim_DisplaySpecialSymbol_Before: aValueStr.Insert (1, mySpecialSymbol); break;
294 case PrsDim_DisplaySpecialSymbol_After: aValueStr.Insert (aValueStr.Length() + 1, mySpecialSymbol); break;
295 case PrsDim_DisplaySpecialSymbol_No: break;
298 // Get text style parameters
299 Handle(Prs3d_TextAspect) aTextAspect = myDrawer->DimensionAspect()->TextAspect();
300 NCollection_Utf8String anUTFString (aValueStr.ToExtString());
304 if (myDrawer->DimensionAspect()->IsText3d())
306 // text width produced by BRepFont
308 if (aFont.FindAndInit (aTextAspect->Aspect()->Font(), aTextAspect->Aspect()->GetTextFontAspect(), aTextAspect->Height(), Font_StrictLevel_Any))
310 for (NCollection_Utf8Iter anIter = anUTFString.Iterator(); *anIter != 0; )
312 Standard_Utf32Char aCurrChar = *anIter;
313 Standard_Utf32Char aNextChar = *(++anIter);
314 theWidth += aFont.AdvanceX (aCurrChar, aNextChar);
320 // Text width for 1:1 scale 2D case
321 Font_FTFontParams aFontParams;
322 const Graphic3d_RenderingParams& aRendParams = GetContext()->CurrentViewer()->DefaultRenderingParams();
323 aFontParams.PointSize = (unsigned int )aTextAspect->Height();
324 aFontParams.Resolution = aRendParams.Resolution;
325 aFontParams.FontHinting = aRendParams.FontHinting;
326 if (Handle(Font_FTFont) aFont = Font_FTFont::FindAndCreate (aTextAspect->Aspect()->Font(),
327 aTextAspect->Aspect()->GetTextFontAspect(),
329 Font_StrictLevel_Any))
331 for (NCollection_Utf8Iter anIter = anUTFString.Iterator(); *anIter != 0; )
333 Standard_Utf32Char aCurrChar = *anIter;
334 Standard_Utf32Char aNextChar = *(++anIter);
335 theWidth += (Standard_Real) aFont->AdvanceX (aCurrChar, aNextChar);
343 //=======================================================================
344 //function : DrawArrow
346 //=======================================================================
347 void PrsDim_Dimension::DrawArrow (const Handle(Prs3d_Presentation)& thePresentation,
348 const gp_Pnt& theLocation,
349 const gp_Dir& theDirection)
351 Handle(Graphic3d_Group) aGroup = thePresentation->NewGroup();
353 Standard_Real aLength = myDrawer->DimensionAspect()->ArrowAspect()->Length();
354 Standard_Real anAngle = myDrawer->DimensionAspect()->ArrowAspect()->Angle();
355 Standard_Boolean isZoomable = myDrawer->DimensionAspect()->ArrowAspect()->IsZoomable();
357 if (myDrawer->DimensionAspect()->IsArrows3d())
359 Prs3d_Arrow::Draw (aGroup,
364 aGroup->SetGroupPrimitivesAspect (myDrawer->DimensionAspect()->ArrowAspect()->Aspect());
368 gp_Pnt aLocation = isZoomable ? theLocation : gp::Origin();
369 gp_Pnt aLeftPoint (gp::Origin());
370 gp_Pnt aRightPoint (gp::Origin());
371 const gp_Dir& aPlane = GetPlane().Axis().Direction();
373 PointsForArrow (aLocation, theDirection, aPlane, aLength, anAngle, aLeftPoint, aRightPoint);
375 Handle(Graphic3d_ArrayOfTriangles) anArrow = new Graphic3d_ArrayOfTriangles(3);
377 anArrow->AddVertex (aLeftPoint);
378 anArrow->AddVertex (aLocation);
379 anArrow->AddVertex (aRightPoint);
381 // Set aspect for arrow triangles
382 Graphic3d_PolygonOffset aPolOffset;
383 aPolOffset.Mode = Aspect_POM_Off;
384 aPolOffset.Factor = 0.0f;
385 aPolOffset.Units = 0.0f;
386 Handle(Graphic3d_AspectFillArea3d) aShadingStyle = new Graphic3d_AspectFillArea3d();
387 aShadingStyle->SetInteriorStyle (Aspect_IS_SOLID);
388 aShadingStyle->SetColor (myDrawer->DimensionAspect()->ArrowAspect()->Aspect()->Color());
389 aShadingStyle->SetShadingModel (Graphic3d_TypeOfShadingModel_Unlit);
390 aShadingStyle->SetPolygonOffset (aPolOffset);
392 aGroup->SetPrimitivesAspect (aShadingStyle);
393 aGroup->AddPrimitiveArray (anArrow);
396 aGroup->SetTransformPersistence (new Graphic3d_TransformPers (Graphic3d_TMF_ZoomPers, theLocation));
400 SelectionGeometry::Arrow& aSensitiveArrow = mySelectionGeom.NewArrow();
401 aSensitiveArrow.Position = theLocation;
402 aSensitiveArrow.Direction = theDirection;
405 //=======================================================================
406 //function : drawText
408 //=======================================================================
409 void PrsDim_Dimension::drawText (const Handle(Prs3d_Presentation)& thePresentation,
410 const gp_Pnt& theTextPos,
411 const gp_Dir& theTextDir,
412 const TCollection_ExtendedString& theText,
413 const Standard_Integer theLabelPosition)
415 Handle(Graphic3d_Group) aGroup = thePresentation->NewGroup();
416 if (myDrawer->DimensionAspect()->IsText3d())
418 // getting font parameters
419 Handle(Prs3d_TextAspect) aTextAspect = myDrawer->DimensionAspect()->TextAspect();
420 Quantity_Color aColor = aTextAspect->Aspect()->Color();
421 Font_FontAspect aFontAspect = aTextAspect->Aspect()->GetTextFontAspect();
422 Standard_Real aFontHeight = aTextAspect->Height();
424 // creating TopoDS_Shape for text
425 Font_BRepFont aFont (aTextAspect->Aspect()->Font().ToCString(),
426 aFontAspect, aFontHeight);
427 NCollection_Utf8String anUTFString (theText.ToExtString());
429 Font_BRepTextBuilder aBuilder;
430 TopoDS_Shape aTextShape = aBuilder.Perform (aFont, anUTFString);
432 // compute text width with kerning
433 Standard_Real aTextWidth = 0.0;
434 Standard_Real aTextHeight = aFont.Ascender() + aFont.Descender();
436 for (NCollection_Utf8Iter anIter = anUTFString.Iterator(); *anIter != 0; )
438 Standard_Utf32Char aCurrChar = *anIter;
439 Standard_Utf32Char aNextChar = *(++anIter);
440 aTextWidth += aFont.AdvanceX (aCurrChar, aNextChar);
443 // formating text position in XOY plane
444 Standard_Integer aHLabelPos = theLabelPosition & LabelPosition_HMask;
445 Standard_Integer aVLabelPos = theLabelPosition & LabelPosition_VMask;
447 gp_Dir aTextDir (aHLabelPos == LabelPosition_Left ? -theTextDir : theTextDir);
449 // compute label offsets
450 Standard_Real aMarginSize = aFontHeight * THE_3D_TEXT_MARGIN;
451 Standard_Real aCenterHOffset = 0.0;
452 Standard_Real aCenterVOffset = 0.0;
455 case LabelPosition_HCenter : aCenterHOffset = 0.0; break;
456 case LabelPosition_Right : aCenterHOffset = aTextWidth / 2.0 + aMarginSize; break;
457 case LabelPosition_Left : aCenterHOffset = -aTextWidth / 2.0 - aMarginSize; break;
461 case LabelPosition_VCenter : aCenterVOffset = 0.0; break;
462 case LabelPosition_Above : aCenterVOffset = aTextHeight / 2.0 + aMarginSize; break;
463 case LabelPosition_Below : aCenterVOffset = -aTextHeight / 2.0 - aMarginSize; break;
466 // compute shape offset transformation
467 Standard_Real aShapeHOffset = aCenterHOffset - aTextWidth / 2.0;
468 Standard_Real aShapeVOffset = aCenterVOffset - aTextHeight / 2.0;
470 // center shape in its bounding box (suppress border spacing added by FT_Font)
472 BRepBndLib::AddClose (aTextShape, aShapeBnd);
474 Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
475 aShapeBnd.Get (aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
477 Standard_Real aXalign = aTextWidth * 0.5 - (aXmax + aXmin) * 0.5;
478 Standard_Real aYalign = aTextHeight * 0.5 - (aYmax + aYmin) * 0.5;
479 aShapeHOffset += aXalign;
480 aShapeVOffset += aYalign;
482 gp_Trsf anOffsetTrsf;
483 anOffsetTrsf.SetTranslation (gp::Origin(), gp_Pnt (aShapeHOffset, aShapeVOffset, 0.0));
484 aTextShape.Move (anOffsetTrsf);
486 // transform text to myWorkingPlane coordinate system
487 gp_Ax3 aTextCoordSystem (theTextPos, GetPlane().Axis().Direction(), aTextDir);
488 gp_Trsf aTextPlaneTrsf;
489 aTextPlaneTrsf.SetTransformation (aTextCoordSystem, gp_Ax3 (gp::XOY()));
490 aTextShape.Move (aTextPlaneTrsf);
492 // set text flipping anchors
493 gp_Trsf aCenterOffsetTrsf;
494 gp_Pnt aCenterOffset (aCenterHOffset, aCenterVOffset, 0.0);
495 aCenterOffsetTrsf.SetTranslation (gp::Origin(), aCenterOffset);
497 gp_Pnt aCenterOfLabel (gp::Origin());
498 aCenterOfLabel.Transform (aCenterOffsetTrsf);
499 aCenterOfLabel.Transform (aTextPlaneTrsf);
501 gp_Ax2 aFlippingAxes (aCenterOfLabel, GetPlane().Axis().Direction(), aTextDir);
502 aGroup->SetFlippingOptions (Standard_True, aFlippingAxes);
505 if (myDrawer->DimensionAspect()->IsTextShaded())
507 // Setting text shading and color parameters
508 if (!myDrawer->HasOwnShadingAspect())
510 myDrawer->SetShadingAspect (new Prs3d_ShadingAspect());
513 Graphic3d_MaterialAspect aShadeMat (Graphic3d_NameOfMaterial_DEFAULT);
514 aShadeMat.SetAmbientColor (Quantity_NOC_BLACK);
515 aShadeMat.SetDiffuseColor (Quantity_NOC_BLACK);
516 aShadeMat.SetSpecularColor(Quantity_NOC_BLACK);
517 myDrawer->ShadingAspect()->Aspect()->SetInteriorColor (aColor);
518 myDrawer->ShadingAspect()->Aspect()->SetBackInteriorColor (aColor);
519 myDrawer->ShadingAspect()->SetMaterial (aShadeMat);
522 StdPrs_ShadedShape::Add (thePresentation, aTextShape, myDrawer);
526 // Setting color for text
527 if (!myDrawer->HasOwnFreeBoundaryAspect())
529 myDrawer->SetFreeBoundaryAspect (new Prs3d_LineAspect (aColor, Aspect_TOL_SOLID, 1.0));
531 myDrawer->FreeBoundaryAspect()->Aspect()->SetColor (aColor);
534 if (Handle(Graphic3d_ArrayOfPrimitives) anEdges = StdPrs_WFShape::AddAllEdges (aTextShape, myDrawer))
536 aGroup->SetGroupPrimitivesAspect (myDrawer->FreeBoundaryAspect()->Aspect());
537 aGroup->AddPrimitiveArray (anEdges);
540 thePresentation->CurrentGroup()->SetFlippingOptions (Standard_False, gp_Ax2());
542 mySelectionGeom.TextPos = aCenterOfLabel;
543 mySelectionGeom.TextDir = aTextDir;
544 mySelectionGeom.TextWidth = aTextWidth + aMarginSize * 2.0;
545 mySelectionGeom.TextHeight = aTextHeight;
550 // generate primitives for 2D text
551 myDrawer->DimensionAspect()->TextAspect()->Aspect()->SetDisplayType (Aspect_TODT_DIMENSION);
553 Prs3d_Text::Draw (aGroup,
554 myDrawer->DimensionAspect()->TextAspect(),
558 mySelectionGeom.TextPos = theTextPos;
559 mySelectionGeom.TextDir = theTextDir;
560 mySelectionGeom.TextWidth = 0.0;
561 mySelectionGeom.TextHeight = 0.0;
564 //=======================================================================
565 //function : DrawExtension
567 //=======================================================================
568 void PrsDim_Dimension::DrawExtension (const Handle(Prs3d_Presentation)& thePresentation,
569 const Standard_Real theExtensionSize,
570 const gp_Pnt& theExtensionStart,
571 const gp_Dir& theExtensionDir,
572 const TCollection_ExtendedString& theLabelString,
573 const Standard_Real theLabelWidth,
574 const Standard_Integer theMode,
575 const Standard_Integer theLabelPosition)
577 // reference line for extension starting at its connection point
578 gp_Lin anExtensionLine (theExtensionStart, theExtensionDir);
580 Standard_Boolean hasLabel = theLabelString.Length() > 0;
581 if (hasLabel && (theMode == ComputeMode_All || theMode == ComputeMode_Text))
583 // compute text primitives; get its model width
584 gp_Pnt aTextPos = ElCLib::Value (theExtensionSize, anExtensionLine);
585 gp_Dir aTextDir = theExtensionDir;
587 Handle(Graphic3d_Group) aGroup = thePresentation->NewGroup();
588 drawText (thePresentation,
595 if (theMode != ComputeMode_All && theMode != ComputeMode_Line)
600 Standard_Boolean isShortLine = !myDrawer->DimensionAspect()->IsText3d()
601 || theLabelPosition & LabelPosition_VCenter;
603 // compute graphical primitives and sensitives for extension line
604 gp_Pnt anExtStart = theExtensionStart;
605 gp_Pnt anExtEnd = !hasLabel || isShortLine
606 ? ElCLib::Value (theExtensionSize, anExtensionLine)
607 : ElCLib::Value (theExtensionSize + theLabelWidth, anExtensionLine);
609 // add graphical primitives
610 Handle(Graphic3d_ArrayOfSegments) anExtPrimitive = new Graphic3d_ArrayOfSegments (2);
611 anExtPrimitive->AddVertex (anExtStart);
612 anExtPrimitive->AddVertex (anExtEnd);
614 // add selection primitives
615 SelectionGeometry::Curve& aSensitiveCurve = mySelectionGeom.NewCurve();
616 aSensitiveCurve.Append (anExtStart);
617 aSensitiveCurve.Append (anExtEnd);
619 Handle(Graphic3d_Group) aGroup = thePresentation->NewGroup();
620 if (!myDrawer->DimensionAspect()->IsText3d() && theMode == ComputeMode_All)
622 aGroup->SetStencilTestOptions (Standard_True);
624 Handle(Graphic3d_AspectLine3d) aDimensionLineStyle = myDrawer->DimensionAspect()->LineAspect()->Aspect();
625 aGroup->SetPrimitivesAspect (aDimensionLineStyle);
626 aGroup->AddPrimitiveArray (anExtPrimitive);
627 if (!myDrawer->DimensionAspect()->IsText3d() && theMode == ComputeMode_All)
629 aGroup->SetStencilTestOptions (Standard_False);
633 //=======================================================================
634 //function : DrawLinearDimension
636 //=======================================================================
637 void PrsDim_Dimension::DrawLinearDimension (const Handle(Prs3d_Presentation)& thePresentation,
638 const Standard_Integer theMode,
639 const gp_Pnt& theFirstPoint,
640 const gp_Pnt& theSecondPoint,
641 const Standard_Boolean theIsOneSide)
643 // do not build any dimension for equal points
644 if (theFirstPoint.IsEqual (theSecondPoint, Precision::Confusion()))
646 throw Standard_ProgramError("Can not build presentation for equal points.");
649 Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
651 // For extensions we need to know arrow size, text size and extension size: get it from aspect
652 Standard_Real anArrowLength = aDimensionAspect->ArrowAspect()->Length();
653 Standard_Real anExtensionSize = aDimensionAspect->ExtensionSize();
654 // prepare label string and compute its geometrical width
655 Standard_Real aLabelWidth;
656 TCollection_ExtendedString aLabelString = GetValueString (aLabelWidth);
658 // add margins to cut dimension lines for 3d text
659 if (aDimensionAspect->IsText3d())
661 aLabelWidth += aDimensionAspect->TextAspect()->Height() * THE_3D_TEXT_MARGIN * 2.0;
664 // handle user-defined and automatic arrow placement
665 Standard_Boolean isArrowsExternal = Standard_False;
666 Standard_Integer aLabelPosition = LabelPosition_None;
668 Prs3d_DimensionTextHorizontalPosition aHorisontalTextPos = aDimensionAspect->TextHorizontalPosition();
669 if (IsTextPositionCustom())
671 if (!AdjustParametersForLinear (myFixedTextPosition, theFirstPoint, theSecondPoint,
672 anExtensionSize, aHorisontalTextPos, myFlyout, myPlane, myIsPlaneCustom))
674 throw Standard_ProgramError("Can not adjust plane to the custom label position.");
678 FitTextAlignmentForLinear (theFirstPoint, theSecondPoint, theIsOneSide, aHorisontalTextPos,
679 aLabelPosition, isArrowsExternal);
681 // compute dimension line points
682 gp_Pnt aLineBegPoint, aLineEndPoint;
683 ComputeFlyoutLinePoints (theFirstPoint, theSecondPoint, aLineBegPoint, aLineEndPoint);
684 gp_Lin aDimensionLine = gce_MakeLin (aLineBegPoint, aLineEndPoint);
686 // compute arrows positions and directions
687 gp_Dir aFirstArrowDir = aDimensionLine.Direction().Reversed();
688 gp_Dir aSecondArrowDir = aDimensionLine.Direction();
689 gp_Dir aFirstExtensionDir = aDimensionLine.Direction().Reversed();
690 gp_Dir aSecondExtensionDir = aDimensionLine.Direction();
692 gp_Pnt aFirstArrowBegin (0.0, 0.0, 0.0);
693 gp_Pnt aFirstArrowEnd (0.0, 0.0, 0.0);
694 gp_Pnt aSecondArrowBegin (0.0, 0.0, 0.0);
695 gp_Pnt aSecondArrowEnd (0.0, 0.0, 0.0);
697 if (isArrowsExternal)
699 aFirstArrowDir.Reverse();
700 aSecondArrowDir.Reverse();
703 aFirstArrowBegin = aLineBegPoint;
704 aSecondArrowBegin = aLineEndPoint;
705 aFirstArrowEnd = aLineBegPoint;
706 aSecondArrowEnd = aLineEndPoint;
708 if (aDimensionAspect->ArrowAspect()->IsZoomable())
710 aFirstArrowEnd.Translate (-gp_Vec (aFirstArrowDir).Scaled (anArrowLength));
711 aSecondArrowEnd.Translate (-gp_Vec (aSecondArrowDir).Scaled (anArrowLength));
714 gp_Pnt aCenterLineBegin = isArrowsExternal
715 ? aLineBegPoint : aFirstArrowEnd;
717 gp_Pnt aCenterLineEnd = isArrowsExternal || theIsOneSide
718 ? aLineEndPoint : aSecondArrowEnd;
721 switch (aLabelPosition & LabelPosition_HMask)
723 // ------------------------------------------------------------------------ //
725 // -------------------------------------------------------------------------//
726 case LabelPosition_HCenter:
728 // add label on dimension or extension line to presentation
729 gp_Pnt aTextPos = IsTextPositionCustom() ? myFixedTextPosition
730 : (aCenterLineBegin.XYZ() + aCenterLineEnd.XYZ()) * 0.5;
731 gp_Dir aTextDir = aDimensionLine.Direction();
733 // add text primitives
734 if (theMode == ComputeMode_All || theMode == ComputeMode_Text)
736 thePresentation->NewGroup();
737 drawText (thePresentation,
744 // add dimension line primitives
745 if (theMode == ComputeMode_All || theMode == ComputeMode_Line)
747 Standard_Boolean isLineBreak = aDimensionAspect->TextVerticalPosition() == Prs3d_DTVP_Center
748 && aDimensionAspect->IsText3d();
750 Handle(Graphic3d_ArrayOfSegments) aPrimSegments = new Graphic3d_ArrayOfSegments (isLineBreak ? 4 : 2);
752 // compute continuous or sectioned main line segments
755 Standard_Real aPTextPosition = ElCLib::Parameter (aDimensionLine, aTextPos);
756 gp_Pnt aSection1Beg = aCenterLineBegin;
757 gp_Pnt aSection1End = ElCLib::Value (aPTextPosition - (aLabelWidth * 0.5), aDimensionLine);
758 gp_Pnt aSection2Beg = ElCLib::Value (aPTextPosition + (aLabelWidth * 0.5), aDimensionLine);
759 gp_Pnt aSection2End = aCenterLineEnd;
761 aPrimSegments->AddVertex (aSection1Beg);
762 aPrimSegments->AddVertex (aSection1End);
763 aPrimSegments->AddVertex (aSection2Beg);
764 aPrimSegments->AddVertex (aSection2End);
766 SelectionGeometry::Curve& aLeftSensitiveCurve = mySelectionGeom.NewCurve();
767 SelectionGeometry::Curve& aRightSensitiveCurve = mySelectionGeom.NewCurve();
768 aLeftSensitiveCurve.Append (aSection1Beg);
769 aLeftSensitiveCurve.Append (aSection1End);
770 aRightSensitiveCurve.Append (aSection2Beg);
771 aRightSensitiveCurve.Append (aSection2End);
775 aPrimSegments->AddVertex (aCenterLineBegin);
776 aPrimSegments->AddVertex (aCenterLineEnd);
778 SelectionGeometry::Curve& aSensitiveCurve = mySelectionGeom.NewCurve();
779 aSensitiveCurve.Append (aCenterLineBegin);
780 aSensitiveCurve.Append (aCenterLineEnd);
783 // set text label justification
784 Graphic3d_VerticalTextAlignment aTextJustificaton = Graphic3d_VTA_BOTTOM;
785 switch (aLabelPosition & LabelPosition_VMask)
787 case LabelPosition_Above :
788 case LabelPosition_VCenter : aTextJustificaton = Graphic3d_VTA_BOTTOM; break;
789 case LabelPosition_Below : aTextJustificaton = Graphic3d_VTA_TOP; break;
791 aDimensionAspect->TextAspect()->SetVerticalJustification (aTextJustificaton);
793 // main dimension line, short extension
795 Handle(Graphic3d_Group) aGroup = thePresentation->NewGroup();
796 if (!aDimensionAspect->IsText3d() && theMode == ComputeMode_All)
798 aGroup->SetStencilTestOptions (Standard_True);
800 aGroup->SetPrimitivesAspect (aDimensionAspect->LineAspect()->Aspect());
801 aGroup->AddPrimitiveArray (aPrimSegments);
802 if (!aDimensionAspect->IsText3d() && theMode == ComputeMode_All)
804 aGroup->SetStencilTestOptions (Standard_False);
808 // add arrows to presentation
810 Handle(Graphic3d_Group) aGroup = thePresentation->NewGroup();
811 DrawArrow (thePresentation, aFirstArrowBegin, aFirstArrowDir);
814 DrawArrow (thePresentation, aSecondArrowBegin, aSecondArrowDir);
818 if (!isArrowsExternal)
823 // add arrow extension lines to presentation
825 DrawExtension (thePresentation, aDimensionAspect->ArrowTailSize(),
826 aFirstArrowEnd, aFirstExtensionDir,
827 THE_EMPTY_LABEL, 0.0, theMode, LabelPosition_None);
830 DrawExtension (thePresentation, aDimensionAspect->ArrowTailSize(),
831 aSecondArrowEnd, aSecondExtensionDir,
832 THE_EMPTY_LABEL, 0.0, theMode, LabelPosition_None);
838 // ------------------------------------------------------------------------ //
840 // -------------------------------------------------------------------------//
842 case LabelPosition_Left:
844 // add label on dimension or extension line to presentation
846 // Left extension with the text
847 DrawExtension (thePresentation, anExtensionSize,
858 // add dimension line primitives
859 if (theMode == ComputeMode_All || theMode == ComputeMode_Line)
861 // add central dimension line
863 Handle(Graphic3d_Group) aGroup = thePresentation->NewGroup();
865 // add graphical primitives
866 Handle(Graphic3d_ArrayOfSegments) aPrimSegments = new Graphic3d_ArrayOfSegments (2);
867 aPrimSegments->AddVertex (aCenterLineBegin);
868 aPrimSegments->AddVertex (aCenterLineEnd);
870 aGroup->SetPrimitivesAspect (aDimensionAspect->LineAspect()->Aspect());
871 aGroup->AddPrimitiveArray (aPrimSegments);
873 // add selection primitives
874 SelectionGeometry::Curve& aSensitiveCurve = mySelectionGeom.NewCurve();
875 aSensitiveCurve.Append (aCenterLineBegin);
876 aSensitiveCurve.Append (aCenterLineEnd);
879 // add arrows to presentation
881 Handle(Graphic3d_Group) aGroup = thePresentation->NewGroup();
882 DrawArrow (thePresentation, aFirstArrowBegin, aFirstArrowDir);
885 DrawArrow (thePresentation, aSecondArrowBegin, aSecondArrowDir);
889 if (!isArrowsExternal || theIsOneSide)
894 // add extension lines for external arrows
896 DrawExtension (thePresentation, aDimensionAspect->ArrowTailSize(),
897 aSecondArrowEnd, aSecondExtensionDir,
898 THE_EMPTY_LABEL, 0.0, theMode, LabelPosition_None);
904 // ------------------------------------------------------------------------ //
906 // -------------------------------------------------------------------------//
908 case LabelPosition_Right:
910 // add label on dimension or extension line to presentation
912 // Right extension with text
913 DrawExtension (thePresentation, anExtensionSize,
918 aLabelString, aLabelWidth,
922 if (theMode == ComputeMode_All || theMode == ComputeMode_Line)
924 // add central dimension line
926 Handle(Graphic3d_Group) aGroup = thePresentation->NewGroup();
928 // add graphical primitives
929 Handle(Graphic3d_ArrayOfSegments) aPrimSegments = new Graphic3d_ArrayOfSegments (2);
930 aPrimSegments->AddVertex (aCenterLineBegin);
931 aPrimSegments->AddVertex (aCenterLineEnd);
932 aGroup->SetGroupPrimitivesAspect (aDimensionAspect->LineAspect()->Aspect());
933 aGroup->AddPrimitiveArray (aPrimSegments);
935 // add selection primitives
936 SelectionGeometry::Curve& aSensitiveCurve = mySelectionGeom.NewCurve();
937 aSensitiveCurve.Append (aCenterLineBegin);
938 aSensitiveCurve.Append (aCenterLineEnd);
941 // add arrows to presentation
943 thePresentation->NewGroup();
944 DrawArrow (thePresentation, aSecondArrowBegin, aSecondArrowDir);
947 DrawArrow (thePresentation, aFirstArrowBegin, aFirstArrowDir);
951 if (!isArrowsExternal || theIsOneSide)
956 // add extension lines for external arrows
958 DrawExtension (thePresentation, aDimensionAspect->ArrowTailSize(),
959 aFirstArrowEnd, aFirstExtensionDir,
960 THE_EMPTY_LABEL, 0.0, theMode, LabelPosition_None);
968 // add flyout lines to presentation
969 if (theMode == ComputeMode_All)
971 Handle(Graphic3d_Group) aGroup = thePresentation->NewGroup();
973 Handle(Graphic3d_ArrayOfSegments) aPrimSegments = new Graphic3d_ArrayOfSegments(4);
974 aPrimSegments->AddVertex (theFirstPoint);
975 aPrimSegments->AddVertex (aLineBegPoint);
977 aPrimSegments->AddVertex (theSecondPoint);
978 aPrimSegments->AddVertex (aLineEndPoint);
980 aGroup->SetGroupPrimitivesAspect (aDimensionAspect->LineAspect()->Aspect());
981 aGroup->AddPrimitiveArray (aPrimSegments);
984 mySelectionGeom.IsComputed = Standard_True;
987 //=======================================================================
988 //function : ComputeFlyoutLinePoints
990 //=======================================================================
991 void PrsDim_Dimension::ComputeFlyoutLinePoints (const gp_Pnt& theFirstPoint, const gp_Pnt& theSecondPoint,
992 gp_Pnt& theLineBegPoint, gp_Pnt& theLineEndPoint)
994 // compute dimension line points
995 gp_Ax1 aPlaneNormal = GetPlane().Axis();
996 // compute flyout direction vector
997 gp_Dir aTargetPointsVector = gce_MakeDir (theFirstPoint, theSecondPoint);
998 gp_Dir aFlyoutVector = aPlaneNormal.Direction() ^ aTargetPointsVector;
999 // create lines for layouts
1000 gp_Lin aLine1 (theFirstPoint, aFlyoutVector);
1001 gp_Lin aLine2 (theSecondPoint, aFlyoutVector);
1003 // Get flyout end points
1004 theLineBegPoint = ElCLib::Value (ElCLib::Parameter (aLine1, theFirstPoint) + GetFlyout(), aLine1);
1005 theLineEndPoint = ElCLib::Value (ElCLib::Parameter (aLine2, theSecondPoint) + GetFlyout(), aLine2);
1008 //=======================================================================
1009 //function : ComputeLinearFlyouts
1011 //=======================================================================
1012 void PrsDim_Dimension::ComputeLinearFlyouts (const Handle(SelectMgr_Selection)& theSelection,
1013 const Handle(SelectMgr_EntityOwner)& theOwner,
1014 const gp_Pnt& theFirstPoint,
1015 const gp_Pnt& theSecondPoint)
1017 // count flyout direction
1018 gp_Ax1 aPlaneNormal = GetPlane().Axis();
1019 gp_Dir aTargetPointsVector = gce_MakeDir (theFirstPoint, theSecondPoint);
1021 // count a flyout direction vector.
1022 gp_Dir aFlyoutVector = aPlaneNormal.Direction() ^ aTargetPointsVector;
1024 // create lines for layouts
1025 gp_Lin aLine1 (theFirstPoint, aFlyoutVector);
1026 gp_Lin aLine2 (theSecondPoint, aFlyoutVector);
1028 // get flyout end points
1029 gp_Pnt aFlyoutEnd1 = ElCLib::Value (ElCLib::Parameter (aLine1, theFirstPoint) + GetFlyout(), aLine1);
1030 gp_Pnt aFlyoutEnd2 = ElCLib::Value (ElCLib::Parameter (aLine2, theSecondPoint) + GetFlyout(), aLine2);
1032 // fill sensitive entity for flyouts
1033 Handle(Select3D_SensitiveGroup) aSensitiveEntity = new Select3D_SensitiveGroup (theOwner);
1034 aSensitiveEntity->Add (new Select3D_SensitiveSegment (theOwner, theFirstPoint, aFlyoutEnd1));
1035 aSensitiveEntity->Add (new Select3D_SensitiveSegment (theOwner, theSecondPoint, aFlyoutEnd2));
1036 theSelection->Add (aSensitiveEntity);
1039 //=======================================================================
1040 //function : CircleFromPlanarFace
1041 //purpose : if possible computes circle from planar face
1042 //=======================================================================
1043 Standard_Boolean PrsDim_Dimension::CircleFromPlanarFace (const TopoDS_Face& theFace,
1044 Handle(Geom_Curve)& theCurve,
1045 gp_Pnt& theFirstPoint,
1046 gp_Pnt& theLastPoint)
1048 TopExp_Explorer anIt (theFace, TopAbs_EDGE);
1049 for ( ; anIt.More(); anIt.Next())
1051 TopoDS_Edge aCurEdge = TopoDS::Edge (anIt.Current());
1052 if (PrsDim::ComputeGeometry (aCurEdge, theCurve, theFirstPoint, theLastPoint))
1054 if (theCurve->IsInstance (STANDARD_TYPE(Geom_Circle)))
1056 return Standard_True;
1060 return Standard_False;
1063 //=======================================================================
1064 //function : CircleFromEdge
1065 //purpose : if possible computes circle from edge
1066 //=======================================================================
1067 Standard_Boolean PrsDim_Dimension::CircleFromEdge (const TopoDS_Edge& theEdge,
1069 gp_Pnt& theFirstPoint,
1070 gp_Pnt& theLastPoint)
1072 BRepAdaptor_Curve anAdaptedCurve (theEdge);
1073 switch (anAdaptedCurve.GetType())
1075 case GeomAbs_Circle:
1077 theCircle = anAdaptedCurve.Circle();
1080 case GeomAbs_Ellipse:
1082 gp_Elips anEll = anAdaptedCurve.Ellipse();
1083 if ((anEll.MinorRadius() - anEll.MajorRadius()) >= Precision::Confusion())
1085 return Standard_False;
1087 theCircle = gp_Circ(anEll.Position(),anEll.MinorRadius());
1091 case GeomAbs_Hyperbola:
1092 case GeomAbs_Parabola:
1093 case GeomAbs_BezierCurve:
1094 case GeomAbs_BSplineCurve:
1095 case GeomAbs_OtherCurve:
1097 return Standard_False;
1100 theFirstPoint = anAdaptedCurve.Value (anAdaptedCurve.FirstParameter());
1101 theLastPoint = anAdaptedCurve.Value (anAdaptedCurve.LastParameter());
1102 return Standard_True;
1105 //=======================================================================
1106 //function : InitCircularDimension
1108 //=======================================================================
1109 Standard_Boolean PrsDim_Dimension::InitCircularDimension (const TopoDS_Shape& theShape,
1111 gp_Pnt& theMiddleArcPoint,
1112 Standard_Boolean& theIsClosed)
1115 Handle(Geom_Surface) aBasisSurf;
1116 PrsDim_KindOfSurface aSurfType = PrsDim_KOS_OtherSurface;
1117 gp_Pnt aFirstPoint, aLastPoint;
1118 Standard_Real anOffset = 0.0;
1119 Standard_Real aFirstParam = 0.0;
1120 Standard_Real aLastParam = 0.0;
1122 // Discover circular geometry
1123 switch (theShape.ShapeType())
1127 PrsDim::GetPlaneFromFace (TopoDS::Face (theShape), aPln, aBasisSurf, aSurfType, anOffset);
1129 if (aSurfType == PrsDim_KOS_Plane)
1131 Handle(Geom_Curve) aCurve;
1132 if (!CircleFromPlanarFace (TopoDS::Face (theShape), aCurve, aFirstPoint, aLastPoint))
1134 return Standard_False;
1137 theCircle = Handle(Geom_Circle)::DownCast (aCurve)->Circ();
1142 BRepAdaptor_Surface aSurf1 (TopoDS::Face (theShape));
1143 Standard_Real aFirstU = aSurf1.FirstUParameter();
1144 Standard_Real aLastU = aSurf1.LastUParameter();
1145 Standard_Real aFirstV = aSurf1.FirstVParameter();
1146 Standard_Real aLastV = aSurf1.LastVParameter();
1147 Standard_Real aMidU = (aFirstU + aLastU) * 0.5;
1148 Standard_Real aMidV = (aFirstV + aLastV) * 0.5;
1149 aSurf1.D0 (aMidU, aMidV, aCurPos);
1150 Handle (Adaptor3d_Curve) aBasisCurve;
1151 Standard_Boolean isExpectedType = Standard_False;
1152 if (aSurfType == PrsDim_KOS_Cylinder)
1154 isExpectedType = Standard_True;
1158 if (aSurfType == PrsDim_KOS_Revolution)
1160 aBasisCurve = aSurf1.BasisCurve();
1161 if (aBasisCurve->GetType() == GeomAbs_Line)
1163 isExpectedType = Standard_True;
1166 else if (aSurfType == PrsDim_KOS_Extrusion)
1168 aBasisCurve = aSurf1.BasisCurve();
1169 if (aBasisCurve->GetType() == GeomAbs_Circle)
1171 isExpectedType = Standard_True;
1176 if (!isExpectedType)
1178 return Standard_False;
1181 Handle(Geom_Curve) aCurve = aBasisSurf->VIso(aMidV);
1182 if (aCurve->DynamicType() == STANDARD_TYPE (Geom_Circle))
1184 theCircle = Handle(Geom_Circle)::DownCast (aCurve)->Circ();
1186 else if (aCurve->DynamicType() == STANDARD_TYPE (Geom_TrimmedCurve))
1188 Handle(Geom_TrimmedCurve) aTrimmedCurve = Handle(Geom_TrimmedCurve)::DownCast (aCurve);
1189 aFirstU = aTrimmedCurve->FirstParameter();
1190 aLastU = aTrimmedCurve->LastParameter();
1191 if (aTrimmedCurve->BasisCurve()->DynamicType() == STANDARD_TYPE (Geom_Circle))
1193 theCircle = Handle(Geom_Circle)::DownCast(aTrimmedCurve->BasisCurve())->Circ();
1198 // Compute a circle from 3 points on "aCurve"
1200 aSurf1.D0 (aFirstU, aMidV, aP1);
1201 aSurf1.D0 (aLastU, aMidV, aP2);
1202 GC_MakeCircle aMkCirc (aP1, aCurPos, aP2);
1203 theCircle = aMkCirc.Value()->Circ();
1206 aFirstPoint = ElCLib::Value (aFirstU, theCircle);
1207 aLastPoint = ElCLib::Value (aLastU, theCircle);
1214 TopExp_Explorer anIt (theShape, TopAbs_EDGE);
1217 anEdge = TopoDS::Edge (anIt.Current());
1219 if (!PrsDim_Dimension::CircleFromEdge (anEdge, theCircle, aFirstPoint, aLastPoint))
1221 return Standard_False;
1227 TopoDS_Edge anEdge = TopoDS::Edge (theShape);
1228 if (!PrsDim_Dimension::CircleFromEdge (anEdge, theCircle, aFirstPoint, aLastPoint))
1230 return Standard_False;
1234 case TopAbs_COMPOUND:
1235 case TopAbs_COMPSOLID:
1241 return Standard_False;
1244 theIsClosed = aFirstPoint.IsEqual (aLastPoint, Precision::Confusion());
1246 gp_Pnt aCenter = theCircle.Location();
1248 if (theIsClosed) // Circle
1250 gp_Dir anXDir = theCircle.XAxis().Direction();
1251 theMiddleArcPoint = aCenter.Translated (gp_Vec (anXDir) * theCircle.Radius());
1255 aFirstParam = ElCLib::Parameter (theCircle, aFirstPoint);
1256 aLastParam = ElCLib::Parameter (theCircle, aLastPoint);
1257 if (aFirstParam > aLastParam)
1259 aFirstParam -= 2.0 * M_PI;
1262 Standard_Real aParCurPos = (aFirstParam + aLastParam) * 0.5;
1263 gp_Vec aVec = gp_Vec (aCenter, ElCLib::Value (aParCurPos, theCircle)).Normalized () * theCircle.Radius ();
1264 theMiddleArcPoint = aCenter.Translated (aVec);
1267 return Standard_True;
1270 //=======================================================================
1271 //function : ComputeSelection
1273 //=======================================================================
1274 void PrsDim_Dimension::ComputeSelection (const Handle(SelectMgr_Selection)& theSelection,
1275 const Standard_Integer theMode)
1277 if (!mySelectionGeom.IsComputed)
1282 PrsDim_DimensionSelectionMode aSelectionMode = (PrsDim_DimensionSelectionMode)theMode;
1284 // init appropriate entity owner
1285 Handle(SelectMgr_EntityOwner) aSensitiveOwner;
1287 switch (aSelectionMode)
1289 // neutral selection owner
1290 case PrsDim_DimensionSelectionMode_All:
1291 aSensitiveOwner = new SelectMgr_EntityOwner (this, THE_NEUTRAL_SEL_PRIORITY);
1294 // local selection owners
1295 case PrsDim_DimensionSelectionMode_Line:
1296 case PrsDim_DimensionSelectionMode_Text:
1297 aSensitiveOwner = new PrsDim_DimensionOwner (this, aSelectionMode, THE_LOCAL_SEL_PRIORITY);
1301 if (aSelectionMode == PrsDim_DimensionSelectionMode_All || aSelectionMode == PrsDim_DimensionSelectionMode_Line)
1303 // sensitives for dimension line segments
1304 Handle(Select3D_SensitiveGroup) aGroupOfSensitives = new Select3D_SensitiveGroup (aSensitiveOwner);
1306 SelectionGeometry::SeqOfCurves::Iterator aCurveIt (mySelectionGeom.DimensionLine);
1307 for (; aCurveIt.More(); aCurveIt.Next())
1309 const SelectionGeometry::HCurve& aCurveData = aCurveIt.Value();
1311 TColgp_Array1OfPnt aSensitivePnts (1, aCurveData->Length());
1312 for (Standard_Integer aPntIt = 1; aPntIt <= aCurveData->Length(); ++aPntIt)
1314 aSensitivePnts.ChangeValue (aPntIt) = aCurveData->Value (aPntIt);
1317 aGroupOfSensitives->Add (new Select3D_SensitiveCurve (aSensitiveOwner, aSensitivePnts));
1320 Standard_Real anArrowLength = myDrawer->DimensionAspect()->ArrowAspect()->Length();
1321 Standard_Real anArrowAngle = myDrawer->DimensionAspect()->ArrowAspect()->Angle();
1323 // sensitives for arrows
1324 SelectionGeometry::SeqOfArrows::Iterator anArrowIt (mySelectionGeom.Arrows);
1325 for (; anArrowIt.More(); anArrowIt.Next())
1327 const SelectionGeometry::HArrow& anArrow = anArrowIt.Value();
1329 gp_Pnt aSidePnt1 (gp::Origin());
1330 gp_Pnt aSidePnt2 (gp::Origin());
1331 const gp_Dir& aPlane = GetPlane().Axis().Direction();
1332 const gp_Pnt& aPeak = anArrow->Position;
1333 const gp_Dir& aDir = anArrow->Direction;
1335 // compute points for arrow in plane
1336 PointsForArrow (aPeak, aDir, aPlane, anArrowLength, anArrowAngle, aSidePnt1, aSidePnt2);
1338 aGroupOfSensitives->Add (new Select3D_SensitiveTriangle (aSensitiveOwner, aPeak, aSidePnt1, aSidePnt2));
1340 if (!myDrawer->DimensionAspect()->IsArrows3d())
1345 // compute points for orthogonal sensitive plane
1346 gp_Dir anOrthoPlane = anArrow->Direction.Crossed (aPlane);
1348 PointsForArrow (aPeak, aDir, anOrthoPlane, anArrowLength, anArrowAngle, aSidePnt1, aSidePnt2);
1350 aGroupOfSensitives->Add (new Select3D_SensitiveTriangle (aSensitiveOwner, aPeak, aSidePnt1, aSidePnt2));
1353 theSelection->Add (aGroupOfSensitives);
1356 // sensitives for text element
1357 if (aSelectionMode == PrsDim_DimensionSelectionMode_All || aSelectionMode == PrsDim_DimensionSelectionMode_Text)
1359 Handle(Select3D_SensitiveEntity) aTextSensitive;
1361 gp_Ax2 aTextAxes (mySelectionGeom.TextPos,
1362 GetPlane().Axis().Direction(),
1363 mySelectionGeom.TextDir);
1365 if (myDrawer->DimensionAspect()->IsText3d())
1367 // sensitive planar rectangle for text
1368 Standard_Real aDx = mySelectionGeom.TextWidth * 0.5;
1369 Standard_Real aDy = mySelectionGeom.TextHeight * 0.5;
1371 gp_Trsf aLabelPlane;
1372 aLabelPlane.SetTransformation (aTextAxes, gp::XOY());
1374 TColgp_Array1OfPnt aRectanglePoints(1, 4);
1375 aRectanglePoints.ChangeValue(1) = gp_Pnt (-aDx, -aDy, 0.0).Transformed (aLabelPlane);
1376 aRectanglePoints.ChangeValue(2) = gp_Pnt (-aDx, aDy, 0.0).Transformed (aLabelPlane);
1377 aRectanglePoints.ChangeValue(3) = gp_Pnt ( aDx, aDy, 0.0).Transformed (aLabelPlane);
1378 aRectanglePoints.ChangeValue(4) = gp_Pnt ( aDx, -aDy, 0.0).Transformed (aLabelPlane);
1380 Poly_Array1OfTriangle aTriangles(1, 2);
1381 aTriangles.ChangeValue(1) = Poly_Triangle(1, 2, 3);
1382 aTriangles.ChangeValue(2) = Poly_Triangle(1, 3, 4);
1384 Handle(Poly_Triangulation) aRectanglePoly =
1385 new Poly_Triangulation(aRectanglePoints, aTriangles);
1388 new Select3D_SensitiveTriangulation (aSensitiveOwner, aRectanglePoly, TopLoc_Location(), Standard_True);
1392 gp_Circ aTextGeom (aTextAxes, mySelToleranceForText2d != 0.0
1393 ? mySelToleranceForText2d : 1.0);
1394 aTextSensitive = new Select3D_SensitiveCircle (aSensitiveOwner, aTextGeom, Standard_True);
1397 theSelection->Add (aTextSensitive);
1400 // callback for flyout sensitive calculation
1401 if (aSelectionMode == PrsDim_DimensionSelectionMode_All)
1403 ComputeFlyoutSelection (theSelection, aSensitiveOwner);
1407 //=======================================================================
1408 //function : PointsForArrow
1410 //=======================================================================
1411 void PrsDim_Dimension::PointsForArrow (const gp_Pnt& thePeakPnt,
1412 const gp_Dir& theDirection,
1413 const gp_Dir& thePlane,
1414 const Standard_Real theArrowLength,
1415 const Standard_Real theArrowAngle,
1416 gp_Pnt& theSidePnt1,
1417 gp_Pnt& theSidePnt2)
1419 gp_Lin anArrowLin (thePeakPnt, theDirection.Reversed());
1420 gp_Pnt anArrowEnd = ElCLib::Value (theArrowLength, anArrowLin);
1421 gp_Lin anEdgeLin (anArrowEnd, theDirection.Crossed (thePlane));
1423 Standard_Real anEdgeLength = Tan (theArrowAngle) * theArrowLength;
1425 theSidePnt1 = ElCLib::Value ( anEdgeLength, anEdgeLin);
1426 theSidePnt2 = ElCLib::Value (-anEdgeLength, anEdgeLin);
1429 //=======================================================================
1430 //function : GetTextPositionForLinear
1432 //=======================================================================
1433 gp_Pnt PrsDim_Dimension::GetTextPositionForLinear (const gp_Pnt& theFirstPoint,
1434 const gp_Pnt& theSecondPoint,
1435 const Standard_Boolean theIsOneSide) const
1439 return gp::Origin();
1442 gp_Pnt aTextPosition (gp::Origin());
1444 Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
1446 // Get label alignment and arrow orientation.
1447 Standard_Integer aLabelPosition = 0;
1448 Standard_Boolean isArrowsExternal = Standard_False;
1449 FitTextAlignmentForLinear (theFirstPoint, theSecondPoint, theIsOneSide,
1450 aDimensionAspect->TextHorizontalPosition(),
1451 aLabelPosition, isArrowsExternal);
1453 // Compute dimension line points.
1454 gp_Dir aPlaneNormal = GetPlane().Axis().Direction();
1455 gp_Vec aTargetPointsVec (theFirstPoint, theSecondPoint);
1457 // Compute flyout direction vector
1458 gp_Dir aFlyoutVector = aPlaneNormal ^ gp_Dir (aTargetPointsVec);
1460 // create lines for layouts
1461 gp_Lin aLine1 (theFirstPoint, aFlyoutVector);
1462 gp_Lin aLine2 (theSecondPoint, aFlyoutVector);
1463 // Get flyout end points
1464 gp_Pnt aLineBegPoint = ElCLib::Value (ElCLib::Parameter (aLine1, theFirstPoint) + GetFlyout(), aLine1);
1465 gp_Pnt aLineEndPoint = ElCLib::Value (ElCLib::Parameter (aLine2, theSecondPoint) + GetFlyout(), aLine2);
1467 // Get text position.
1468 switch (aLabelPosition & LabelPosition_HMask)
1470 case LabelPosition_Left:
1472 gp_Dir aTargetPointsDir = gce_MakeDir (theFirstPoint, theSecondPoint);
1473 Standard_Real anExtensionSize = aDimensionAspect->ExtensionSize();
1475 Standard_Real anOffset = isArrowsExternal
1476 ? anExtensionSize + aDimensionAspect->ArrowAspect()->Length()
1478 gp_Vec anExtensionVec = gp_Vec (aTargetPointsDir) * -anOffset;
1479 aTextPosition = aLineEndPoint.Translated (anExtensionVec);
1482 case LabelPosition_Right:
1484 gp_Dir aTargetPointsDir = gce_MakeDir (theFirstPoint, theSecondPoint);
1485 Standard_Real anExtensionSize = aDimensionAspect->ExtensionSize();
1487 Standard_Real anOffset = isArrowsExternal
1488 ? anExtensionSize + aDimensionAspect->ArrowAspect()->Length()
1490 gp_Vec anExtensionVec = gp_Vec (aTargetPointsDir) * anOffset;
1491 aTextPosition = aLineBegPoint.Translated (anExtensionVec);
1494 case LabelPosition_HCenter:
1496 aTextPosition = (aLineBegPoint.XYZ() + aLineEndPoint.XYZ()) * 0.5;
1501 return aTextPosition;
1504 //=======================================================================
1505 //function : AdjustParametersForLinear
1507 //=======================================================================
1508 Standard_Boolean PrsDim_Dimension::AdjustParametersForLinear (const gp_Pnt& theTextPos,
1509 const gp_Pnt& theFirstPoint,
1510 const gp_Pnt& theSecondPoint,
1511 Standard_Real& theExtensionSize,
1512 Prs3d_DimensionTextHorizontalPosition& theAlignment,
1513 Standard_Real& theFlyout,
1515 Standard_Boolean& theIsPlaneOld) const
1517 Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
1518 Standard_Real anArrowLength = aDimensionAspect->ArrowAspect()->Length();
1520 gp_Dir aTargetPointsDir = gce_MakeDir (theFirstPoint, theSecondPoint);
1521 gp_Vec aTargetPointsVec (theFirstPoint, theSecondPoint);
1523 // Don't set new plane if the text position lies on the attachment points line.
1524 gp_Lin aTargetPointsLin (theFirstPoint, aTargetPointsDir);
1525 if (!aTargetPointsLin.Contains (theTextPos, Precision::Confusion()))
1527 //Set new automatic plane.
1528 thePlane = gce_MakePln (theTextPos, theFirstPoint, theSecondPoint);
1529 theIsPlaneOld = Standard_False;
1532 // Compute flyout direction vector.
1533 gp_Dir aPlaneNormal = GetPlane().Axis().Direction();
1534 gp_Dir aPositiveFlyout = aPlaneNormal ^ aTargetPointsDir;
1536 // Additional check of collinearity of the plane normal and attachment points vector.
1537 if (aPlaneNormal.IsParallel (aTargetPointsDir, Precision::Angular()))
1539 return Standard_False;
1543 gp_Vec aFirstToTextVec (theFirstPoint, theTextPos);
1545 Standard_Real aCos = aFirstToTextVec.Normalized() * gp_Vec (aTargetPointsDir);
1547 gp_Pnt aTextPosProj = theFirstPoint.Translated
1548 (gp_Vec (aTargetPointsDir) * aFirstToTextVec.Magnitude() * aCos);
1550 // Compute flyout value and direction.
1551 gp_Vec aFlyoutVector = gp_Vec (aTextPosProj, theTextPos);
1554 if (aFlyoutVector.Magnitude() > Precision::Confusion())
1556 theFlyout = gp_Dir (aFlyoutVector).IsOpposite (aPositiveFlyout, Precision::Angular())
1557 ? -aFlyoutVector.Magnitude()
1558 : aFlyoutVector.Magnitude();
1561 // Compute attach points (through which main dimension line passes).
1562 gp_Pnt aFirstAttach = theFirstPoint.Translated (aFlyoutVector);
1563 gp_Pnt aSecondAttach = theSecondPoint.Translated (aFlyoutVector);
1565 // Set horizontal text alignment.
1568 theAlignment = Prs3d_DTHP_Left;
1570 Standard_Real aNewExtSize = theTextPos.Distance (aFirstAttach) - anArrowLength;
1571 theExtensionSize = aNewExtSize < 0.0 ? 0.0 : aNewExtSize;
1573 else if (aTextPosProj.Distance (theFirstPoint) > theFirstPoint.Distance (theSecondPoint))
1575 theAlignment = Prs3d_DTHP_Right;
1577 Standard_Real aNewExtSize = theTextPos.Distance (aSecondAttach) - anArrowLength;
1578 theExtensionSize = aNewExtSize < 0.0 ? 0.0 : aNewExtSize;
1582 theAlignment = Prs3d_DTHP_Center;
1584 return Standard_True;
1587 //=======================================================================
1588 //function : FitTextAlignmentForLinear
1590 //=======================================================================
1591 void PrsDim_Dimension::FitTextAlignmentForLinear (const gp_Pnt& theFirstPoint,
1592 const gp_Pnt& theSecondPoint,
1593 const Standard_Boolean theIsOneSide,
1594 const Prs3d_DimensionTextHorizontalPosition& theHorizontalTextPos,
1595 Standard_Integer& theLabelPosition,
1596 Standard_Boolean& theIsArrowsExternal) const
1598 theLabelPosition = LabelPosition_None;
1599 theIsArrowsExternal = Standard_False;
1601 // Compute dimension line points
1602 gp_Ax1 aPlaneNormal = GetPlane().Axis();
1603 gp_Dir aTargetPointsVector = gce_MakeDir (theFirstPoint, theSecondPoint);
1605 // compute flyout direction vector
1606 gp_Dir aFlyoutVector = aPlaneNormal.Direction() ^ aTargetPointsVector;
1608 // create lines for layouts
1609 gp_Lin aLine1 (theFirstPoint, aFlyoutVector);
1610 gp_Lin aLine2 (theSecondPoint, aFlyoutVector);
1612 // Get flyout end points
1613 gp_Pnt aLineBegPoint = ElCLib::Value (ElCLib::Parameter (aLine1, theFirstPoint) + GetFlyout(), aLine1);
1614 gp_Pnt aLineEndPoint = ElCLib::Value (ElCLib::Parameter (aLine2, theSecondPoint) + GetFlyout(), aLine2);
1616 Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
1618 // For extensions we need to know arrow size, text size and extension size: get it from aspect
1619 Standard_Real anArrowLength = aDimensionAspect->ArrowAspect()->Length();
1621 // prepare label string and compute its geometrical width
1622 Standard_Real aLabelWidth;
1623 TCollection_ExtendedString aLabelString = GetValueString (aLabelWidth);
1625 // Add margins to cut dimension lines for 3d text
1626 if (aDimensionAspect->IsText3d())
1628 aLabelWidth += aDimensionAspect->TextAspect()->Height() * THE_3D_TEXT_MARGIN * 2.0;
1631 // Handle user-defined and automatic arrow placement
1632 switch (aDimensionAspect->ArrowOrientation())
1634 case Prs3d_DAO_External: theIsArrowsExternal = true; break;
1635 case Prs3d_DAO_Internal: theIsArrowsExternal = false; break;
1638 // Add margin to ensure a small tail between text and arrow
1639 Standard_Real anArrowMargin = aDimensionAspect->IsText3d()
1640 ? aDimensionAspect->TextAspect()->Height() * THE_3D_TEXT_MARGIN
1643 Standard_Real aDimensionWidth = aLineBegPoint.Distance (aLineEndPoint);
1644 Standard_Real anArrowsWidth = theIsOneSide
1645 ? anArrowLength + anArrowMargin
1646 : (anArrowLength + anArrowMargin) * 2.0;
1648 theIsArrowsExternal = aDimensionWidth < aLabelWidth + anArrowsWidth;
1653 // Handle user-defined and automatic text placement
1654 switch (theHorizontalTextPos)
1656 case Prs3d_DTHP_Left : theLabelPosition |= LabelPosition_Left; break;
1657 case Prs3d_DTHP_Right : theLabelPosition |= LabelPosition_Right; break;
1658 case Prs3d_DTHP_Center: theLabelPosition |= LabelPosition_HCenter; break;
1659 case Prs3d_DTHP_Fit:
1661 Standard_Real aDimensionWidth = aLineBegPoint.Distance (aLineEndPoint);
1662 Standard_Real anArrowsWidth = theIsOneSide ? anArrowLength : 2.0 * anArrowLength;
1663 Standard_Real aContentWidth = theIsArrowsExternal ? aLabelWidth : aLabelWidth + anArrowsWidth;
1665 theLabelPosition |= aDimensionWidth < aContentWidth ? LabelPosition_Left : LabelPosition_HCenter;
1670 // Handle vertical text placement options
1671 switch (aDimensionAspect->TextVerticalPosition())
1673 case Prs3d_DTVP_Above : theLabelPosition |= LabelPosition_Above; break;
1674 case Prs3d_DTVP_Below : theLabelPosition |= LabelPosition_Below; break;
1675 case Prs3d_DTVP_Center : theLabelPosition |= LabelPosition_VCenter; break;
1679 //=======================================================================
1680 //function : UnsetFixedTextPosition
1682 //=======================================================================
1683 void PrsDim_Dimension::UnsetFixedTextPosition()
1685 myIsTextPositionFixed = Standard_False;
1686 myFixedTextPosition = gp::Origin();