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 <Adaptor3d_Curve.hxx>
21 #include <AIS_InteractiveContext.hxx>
22 #include <BRepAdaptor_Curve.hxx>
23 #include <BRepAdaptor_Surface.hxx>
24 #include <BRepBndLib.hxx>
25 #include <Bnd_Box.hxx>
27 #include <Font_BRepFont.hxx>
28 #include <Font_BRepTextBuilder.hxx>
29 #include <GC_MakeCircle.hxx>
30 #include <Geom_Line.hxx>
31 #include <GeomAdaptor_Curve.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_PresentationManager.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_ShadingAspect.hxx>
49 #include <Prs3d_Text.hxx>
50 #include <SelectMgr_EntityOwner.hxx>
51 #include <SelectMgr_Selection.hxx>
52 #include <SelectMgr_SequenceOfOwner.hxx>
53 #include <Select3D_SensitiveCircle.hxx>
54 #include <Select3D_SensitiveGroup.hxx>
55 #include <Select3D_SensitiveCurve.hxx>
56 #include <Select3D_SensitiveSegment.hxx>
57 #include <Select3D_SensitiveTriangle.hxx>
58 #include <Select3D_SensitiveTriangulation.hxx>
59 #include <Poly_Array1OfTriangle.hxx>
60 #include <Poly_Triangulation.hxx>
61 #include <Standard_CString.hxx>
62 #include <Standard_ProgramError.hxx>
63 #include <StdPrs_ShadedShape.hxx>
64 #include <StdPrs_WFShape.hxx>
65 #include <TCollection_AsciiString.hxx>
66 #include <TCollection_ExtendedString.hxx>
67 #include <TopExp_Explorer.hxx>
69 #include <TopoDS_Edge.hxx>
70 #include <TopoDS_Vertex.hxx>
71 #include <V3d_Viewer.hxx>
73 #include <Units_UnitsDictionary.hxx>
74 #include <UnitsAPI.hxx>
75 #include <UnitsAPI_SystemUnits.hxx>
77 IMPLEMENT_STANDARD_RTTIEXT(PrsDim_Dimension, AIS_InteractiveObject)
81 // default text strings
82 static const TCollection_ExtendedString THE_EMPTY_LABEL;
83 static const TCollection_AsciiString THE_UNDEFINED_UNITS;
85 // default text margin and resolution
86 static const Standard_Real THE_3D_TEXT_MARGIN = 0.1;
88 // default selection priorities
89 static const Standard_Integer THE_NEUTRAL_SEL_PRIORITY = 5;
90 static const Standard_Integer THE_LOCAL_SEL_PRIORITY = 6;
93 //=======================================================================
94 //function : Constructor
96 //=======================================================================
97 PrsDim_Dimension::PrsDim_Dimension (const PrsDim_KindOfDimension theType)
98 : AIS_InteractiveObject (),
99 mySelToleranceForText2d(0.0),
100 myValueType (ValueType_Computed),
102 myCustomStringValue (),
103 myIsTextPositionFixed (Standard_False),
104 mySpecialSymbol (' '),
105 myDisplaySpecialSymbol (PrsDim_DisplaySpecialSymbol_No),
106 myGeometryType (GeometryType_UndefShapes),
107 myIsPlaneCustom (Standard_False),
109 myIsGeometryValid (Standard_False),
110 myKindOfDimension (theType)
114 //=======================================================================
115 //function : SetCustomValue
117 //=======================================================================
118 void PrsDim_Dimension::SetCustomValue (const Standard_Real theValue)
120 if (myValueType == ValueType_CustomReal && myCustomValue == theValue)
125 myValueType = ValueType_CustomReal;
126 myCustomValue = theValue;
131 //=======================================================================
132 //function : SetCustomValue
134 //=======================================================================
135 void PrsDim_Dimension::SetCustomValue (const TCollection_ExtendedString& theValue)
137 if (myValueType == ValueType_CustomText && myCustomStringValue == theValue)
142 myValueType = ValueType_CustomText;
143 myCustomStringValue = theValue;
148 //=======================================================================
149 //function : SetUserPlane
151 //=======================================================================
152 void PrsDim_Dimension::SetCustomPlane (const gp_Pln& thePlane)
155 myIsPlaneCustom = Standard_True;
157 // Disable fixed (custom) text position
158 UnsetFixedTextPosition();
160 // Check validity if geometry has been set already.
167 //=======================================================================
168 //function : SetDimensionAspect
170 //=======================================================================
171 void PrsDim_Dimension::SetDimensionAspect (const Handle(Prs3d_DimensionAspect)& theDimensionAspect)
173 myDrawer->SetDimensionAspect (theDimensionAspect);
178 //=======================================================================
179 //function : SetDisplaySpecialSymbol
181 //=======================================================================
182 void PrsDim_Dimension::SetDisplaySpecialSymbol (const PrsDim_DisplaySpecialSymbol theDisplaySpecSymbol)
184 if (myDisplaySpecialSymbol == theDisplaySpecSymbol)
189 myDisplaySpecialSymbol = theDisplaySpecSymbol;
194 //=======================================================================
195 //function : SetSpecialSymbol
197 //=======================================================================
198 void PrsDim_Dimension::SetSpecialSymbol (const Standard_ExtCharacter theSpecialSymbol)
200 if (mySpecialSymbol == theSpecialSymbol)
205 mySpecialSymbol = theSpecialSymbol;
210 //=======================================================================
211 //function : SetSelToleranceForText2d
213 //=======================================================================
214 void PrsDim_Dimension::SetSelToleranceForText2d (const Standard_Real theTol)
216 if (mySelToleranceForText2d == theTol)
221 mySelToleranceForText2d = theTol;
226 //=======================================================================
227 //function : SetFlyout
229 //=======================================================================
230 void PrsDim_Dimension::SetFlyout (const Standard_Real theFlyout)
232 if (myFlyout == theFlyout)
237 myFlyout = theFlyout;
239 // Disable fixed text position
240 UnsetFixedTextPosition();
245 //=======================================================================
246 //function : GetDisplayUnits
248 //=======================================================================
249 const TCollection_AsciiString& PrsDim_Dimension::GetDisplayUnits() const
251 return THE_UNDEFINED_UNITS;
254 //=======================================================================
255 //function : GetModelUnits
257 //=======================================================================
258 const TCollection_AsciiString& PrsDim_Dimension::GetModelUnits() const
260 return THE_UNDEFINED_UNITS;
263 //=======================================================================
264 //function : ValueToDisplayUnits
266 //=======================================================================
267 Standard_Real PrsDim_Dimension::ValueToDisplayUnits() const
269 return UnitsAPI::AnyToAny (GetValue(),
270 GetModelUnits().ToCString(),
271 GetDisplayUnits().ToCString());
274 //=======================================================================
275 //function : GetValueString
277 //=======================================================================
278 TCollection_ExtendedString PrsDim_Dimension::GetValueString (Standard_Real& theWidth) const
280 TCollection_ExtendedString aValueStr;
281 if (myValueType == ValueType_CustomText)
283 aValueStr = myCustomStringValue;
287 // format value string using "sprintf"
288 TCollection_AsciiString aFormatStr = myDrawer->DimensionAspect()->ValueStringFormat();
290 char aFmtBuffer[256];
291 sprintf (aFmtBuffer, aFormatStr.ToCString(), ValueToDisplayUnits());
292 aValueStr = TCollection_ExtendedString (aFmtBuffer);
295 // add units to values string
296 if (myDrawer->DimensionAspect()->IsUnitsDisplayed())
299 aValueStr += TCollection_ExtendedString (GetDisplayUnits());
302 switch (myDisplaySpecialSymbol)
304 case PrsDim_DisplaySpecialSymbol_Before: aValueStr.Insert (1, mySpecialSymbol); break;
305 case PrsDim_DisplaySpecialSymbol_After: aValueStr.Insert (aValueStr.Length() + 1, mySpecialSymbol); break;
306 case PrsDim_DisplaySpecialSymbol_No: break;
309 // Get text style parameters
310 Handle(Prs3d_TextAspect) aTextAspect = myDrawer->DimensionAspect()->TextAspect();
311 NCollection_Utf8String anUTFString (aValueStr.ToExtString());
315 if (myDrawer->DimensionAspect()->IsText3d())
317 // text width produced by BRepFont
319 if (aFont.FindAndInit (aTextAspect->Aspect()->Font(), aTextAspect->Aspect()->GetTextFontAspect(), aTextAspect->Height(), Font_StrictLevel_Any))
321 for (NCollection_Utf8Iter anIter = anUTFString.Iterator(); *anIter != 0; )
323 Standard_Utf32Char aCurrChar = *anIter;
324 Standard_Utf32Char aNextChar = *(++anIter);
325 theWidth += aFont.AdvanceX (aCurrChar, aNextChar);
331 // Text width for 1:1 scale 2D case
332 Font_FTFontParams aFontParams;
333 const Graphic3d_RenderingParams& aRendParams = GetContext()->CurrentViewer()->DefaultRenderingParams();
334 aFontParams.PointSize = (unsigned int )aTextAspect->Height();
335 aFontParams.Resolution = aRendParams.Resolution;
336 aFontParams.FontHinting = aRendParams.FontHinting;
337 if (Handle(Font_FTFont) aFont = Font_FTFont::FindAndCreate (aTextAspect->Aspect()->Font(),
338 aTextAspect->Aspect()->GetTextFontAspect(),
340 Font_StrictLevel_Any))
342 for (NCollection_Utf8Iter anIter = anUTFString.Iterator(); *anIter != 0; )
344 Standard_Utf32Char aCurrChar = *anIter;
345 Standard_Utf32Char aNextChar = *(++anIter);
346 theWidth += (Standard_Real) aFont->AdvanceX (aCurrChar, aNextChar);
354 //=======================================================================
355 //function : DrawArrow
357 //=======================================================================
358 void PrsDim_Dimension::DrawArrow (const Handle(Prs3d_Presentation)& thePresentation,
359 const gp_Pnt& theLocation,
360 const gp_Dir& theDirection)
362 Handle(Graphic3d_Group) aGroup = thePresentation->NewGroup();
364 Standard_Real aLength = myDrawer->DimensionAspect()->ArrowAspect()->Length();
365 Standard_Real anAngle = myDrawer->DimensionAspect()->ArrowAspect()->Angle();
367 if (myDrawer->DimensionAspect()->IsArrows3d())
369 Prs3d_Arrow::Draw (aGroup,
374 aGroup->SetGroupPrimitivesAspect (myDrawer->DimensionAspect()->ArrowAspect()->Aspect());
378 gp_Pnt aLeftPoint (gp::Origin());
379 gp_Pnt aRightPoint (gp::Origin());
380 const gp_Dir& aPlane = GetPlane().Axis().Direction();
382 PointsForArrow (theLocation, theDirection, aPlane, aLength, anAngle, aLeftPoint, aRightPoint);
384 Handle(Graphic3d_ArrayOfTriangles) anArrow = new Graphic3d_ArrayOfTriangles(3);
386 anArrow->AddVertex (aLeftPoint);
387 anArrow->AddVertex (theLocation);
388 anArrow->AddVertex (aRightPoint);
390 // Set aspect for arrow triangles
391 Graphic3d_PolygonOffset aPolOffset;
392 aPolOffset.Mode = Aspect_POM_Off;
393 aPolOffset.Factor = 0.0f;
394 aPolOffset.Units = 0.0f;
395 Handle(Graphic3d_AspectFillArea3d) aShadingStyle = new Graphic3d_AspectFillArea3d();
396 aShadingStyle->SetInteriorStyle (Aspect_IS_SOLID);
397 aShadingStyle->SetColor (myDrawer->DimensionAspect()->ArrowAspect()->Aspect()->Color());
398 aShadingStyle->SetShadingModel (Graphic3d_TOSM_UNLIT);
399 aShadingStyle->SetPolygonOffset (aPolOffset);
401 aGroup->SetPrimitivesAspect (aShadingStyle);
402 aGroup->AddPrimitiveArray (anArrow);
405 SelectionGeometry::Arrow& aSensitiveArrow = mySelectionGeom.NewArrow();
406 aSensitiveArrow.Position = theLocation;
407 aSensitiveArrow.Direction = theDirection;
410 //=======================================================================
411 //function : drawText
413 //=======================================================================
414 void PrsDim_Dimension::drawText (const Handle(Prs3d_Presentation)& thePresentation,
415 const gp_Pnt& theTextPos,
416 const gp_Dir& theTextDir,
417 const TCollection_ExtendedString& theText,
418 const Standard_Integer theLabelPosition)
420 Handle(Graphic3d_Group) aGroup = thePresentation->NewGroup();
421 if (myDrawer->DimensionAspect()->IsText3d())
423 // getting font parameters
424 Handle(Prs3d_TextAspect) aTextAspect = myDrawer->DimensionAspect()->TextAspect();
425 Quantity_Color aColor = aTextAspect->Aspect()->Color();
426 Font_FontAspect aFontAspect = aTextAspect->Aspect()->GetTextFontAspect();
427 Standard_Real aFontHeight = aTextAspect->Height();
429 // creating TopoDS_Shape for text
430 Font_BRepFont aFont (aTextAspect->Aspect()->Font().ToCString(),
431 aFontAspect, aFontHeight);
432 NCollection_Utf8String anUTFString (theText.ToExtString());
434 Font_BRepTextBuilder aBuilder;
435 TopoDS_Shape aTextShape = aBuilder.Perform (aFont, anUTFString);
437 // compute text width with kerning
438 Standard_Real aTextWidth = 0.0;
439 Standard_Real aTextHeight = aFont.Ascender() + aFont.Descender();
441 for (NCollection_Utf8Iter anIter = anUTFString.Iterator(); *anIter != 0; )
443 Standard_Utf32Char aCurrChar = *anIter;
444 Standard_Utf32Char aNextChar = *(++anIter);
445 aTextWidth += aFont.AdvanceX (aCurrChar, aNextChar);
448 // formating text position in XOY plane
449 Standard_Integer aHLabelPos = theLabelPosition & LabelPosition_HMask;
450 Standard_Integer aVLabelPos = theLabelPosition & LabelPosition_VMask;
452 gp_Dir aTextDir (aHLabelPos == LabelPosition_Left ? -theTextDir : theTextDir);
454 // compute label offsets
455 Standard_Real aMarginSize = aFontHeight * THE_3D_TEXT_MARGIN;
456 Standard_Real aCenterHOffset = 0.0;
457 Standard_Real aCenterVOffset = 0.0;
460 case LabelPosition_HCenter : aCenterHOffset = 0.0; break;
461 case LabelPosition_Right : aCenterHOffset = aTextWidth / 2.0 + aMarginSize; break;
462 case LabelPosition_Left : aCenterHOffset = -aTextWidth / 2.0 - aMarginSize; break;
466 case LabelPosition_VCenter : aCenterVOffset = 0.0; break;
467 case LabelPosition_Above : aCenterVOffset = aTextHeight / 2.0 + aMarginSize; break;
468 case LabelPosition_Below : aCenterVOffset = -aTextHeight / 2.0 - aMarginSize; break;
471 // compute shape offset transformation
472 Standard_Real aShapeHOffset = aCenterHOffset - aTextWidth / 2.0;
473 Standard_Real aShapeVOffset = aCenterVOffset - aTextHeight / 2.0;
475 // center shape in its bounding box (suppress border spacing added by FT_Font)
477 BRepBndLib::AddClose (aTextShape, aShapeBnd);
479 Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
480 aShapeBnd.Get (aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
482 Standard_Real aXalign = aTextWidth * 0.5 - (aXmax + aXmin) * 0.5;
483 Standard_Real aYalign = aTextHeight * 0.5 - (aYmax + aYmin) * 0.5;
484 aShapeHOffset += aXalign;
485 aShapeVOffset += aYalign;
487 gp_Trsf anOffsetTrsf;
488 anOffsetTrsf.SetTranslation (gp::Origin(), gp_Pnt (aShapeHOffset, aShapeVOffset, 0.0));
489 aTextShape.Move (anOffsetTrsf);
491 // transform text to myWorkingPlane coordinate system
492 gp_Ax3 aTextCoordSystem (theTextPos, GetPlane().Axis().Direction(), aTextDir);
493 gp_Trsf aTextPlaneTrsf;
494 aTextPlaneTrsf.SetTransformation (aTextCoordSystem, gp_Ax3 (gp::XOY()));
495 aTextShape.Move (aTextPlaneTrsf);
497 // set text flipping anchors
498 gp_Trsf aCenterOffsetTrsf;
499 gp_Pnt aCenterOffset (aCenterHOffset, aCenterVOffset, 0.0);
500 aCenterOffsetTrsf.SetTranslation (gp::Origin(), aCenterOffset);
502 gp_Pnt aCenterOfLabel (gp::Origin());
503 aCenterOfLabel.Transform (aCenterOffsetTrsf);
504 aCenterOfLabel.Transform (aTextPlaneTrsf);
506 gp_Ax2 aFlippingAxes (aCenterOfLabel, GetPlane().Axis().Direction(), aTextDir);
507 aGroup->SetFlippingOptions (Standard_True, aFlippingAxes);
510 if (myDrawer->DimensionAspect()->IsTextShaded())
512 // Setting text shading and color parameters
513 if (!myDrawer->HasOwnShadingAspect())
515 myDrawer->SetShadingAspect (new Prs3d_ShadingAspect());
518 Graphic3d_MaterialAspect aShadeMat (Graphic3d_NameOfMaterial_DEFAULT);
519 aShadeMat.SetAmbientColor (Quantity_NOC_BLACK);
520 aShadeMat.SetDiffuseColor (Quantity_NOC_BLACK);
521 aShadeMat.SetSpecularColor(Quantity_NOC_BLACK);
522 myDrawer->ShadingAspect()->Aspect()->SetInteriorColor (aColor);
523 myDrawer->ShadingAspect()->Aspect()->SetBackInteriorColor (aColor);
524 myDrawer->ShadingAspect()->SetMaterial (aShadeMat);
527 StdPrs_ShadedShape::Add (thePresentation, aTextShape, myDrawer);
531 // Setting color for text
532 if (!myDrawer->HasOwnFreeBoundaryAspect())
534 myDrawer->SetFreeBoundaryAspect (new Prs3d_LineAspect (aColor, Aspect_TOL_SOLID, 1.0));
536 myDrawer->FreeBoundaryAspect()->Aspect()->SetColor (aColor);
539 if (Handle(Graphic3d_ArrayOfPrimitives) anEdges = StdPrs_WFShape::AddAllEdges (aTextShape, myDrawer))
541 aGroup->SetGroupPrimitivesAspect (myDrawer->FreeBoundaryAspect()->Aspect());
542 aGroup->AddPrimitiveArray (anEdges);
545 thePresentation->CurrentGroup()->SetFlippingOptions (Standard_False, gp_Ax2());
547 mySelectionGeom.TextPos = aCenterOfLabel;
548 mySelectionGeom.TextDir = aTextDir;
549 mySelectionGeom.TextWidth = aTextWidth + aMarginSize * 2.0;
550 mySelectionGeom.TextHeight = aTextHeight;
555 // generate primitives for 2D text
556 myDrawer->DimensionAspect()->TextAspect()->Aspect()->SetDisplayType (Aspect_TODT_DIMENSION);
558 Prs3d_Text::Draw (aGroup,
559 myDrawer->DimensionAspect()->TextAspect(),
563 mySelectionGeom.TextPos = theTextPos;
564 mySelectionGeom.TextDir = theTextDir;
565 mySelectionGeom.TextWidth = 0.0;
566 mySelectionGeom.TextHeight = 0.0;
569 //=======================================================================
570 //function : DrawExtension
572 //=======================================================================
573 void PrsDim_Dimension::DrawExtension (const Handle(Prs3d_Presentation)& thePresentation,
574 const Standard_Real theExtensionSize,
575 const gp_Pnt& theExtensionStart,
576 const gp_Dir& theExtensionDir,
577 const TCollection_ExtendedString& theLabelString,
578 const Standard_Real theLabelWidth,
579 const Standard_Integer theMode,
580 const Standard_Integer theLabelPosition)
582 // reference line for extension starting at its connection point
583 gp_Lin anExtensionLine (theExtensionStart, theExtensionDir);
585 Standard_Boolean hasLabel = theLabelString.Length() > 0;
586 if (hasLabel && (theMode == ComputeMode_All || theMode == ComputeMode_Text))
588 // compute text primitives; get its model width
589 gp_Pnt aTextPos = ElCLib::Value (theExtensionSize, anExtensionLine);
590 gp_Dir aTextDir = theExtensionDir;
592 Handle(Graphic3d_Group) aGroup = thePresentation->NewGroup();
593 drawText (thePresentation,
600 if (theMode != ComputeMode_All && theMode != ComputeMode_Line)
605 Standard_Boolean isShortLine = !myDrawer->DimensionAspect()->IsText3d()
606 || theLabelPosition & LabelPosition_VCenter;
608 // compute graphical primitives and sensitives for extension line
609 gp_Pnt anExtStart = theExtensionStart;
610 gp_Pnt anExtEnd = !hasLabel || isShortLine
611 ? ElCLib::Value (theExtensionSize, anExtensionLine)
612 : ElCLib::Value (theExtensionSize + theLabelWidth, anExtensionLine);
614 // add graphical primitives
615 Handle(Graphic3d_ArrayOfSegments) anExtPrimitive = new Graphic3d_ArrayOfSegments (2);
616 anExtPrimitive->AddVertex (anExtStart);
617 anExtPrimitive->AddVertex (anExtEnd);
619 // add selection primitives
620 SelectionGeometry::Curve& aSensitiveCurve = mySelectionGeom.NewCurve();
621 aSensitiveCurve.Append (anExtStart);
622 aSensitiveCurve.Append (anExtEnd);
624 Handle(Graphic3d_Group) aGroup = thePresentation->NewGroup();
625 if (!myDrawer->DimensionAspect()->IsText3d() && theMode == ComputeMode_All)
627 aGroup->SetStencilTestOptions (Standard_True);
629 Handle(Graphic3d_AspectLine3d) aDimensionLineStyle = myDrawer->DimensionAspect()->LineAspect()->Aspect();
630 aGroup->SetPrimitivesAspect (aDimensionLineStyle);
631 aGroup->AddPrimitiveArray (anExtPrimitive);
632 if (!myDrawer->DimensionAspect()->IsText3d() && theMode == ComputeMode_All)
634 aGroup->SetStencilTestOptions (Standard_False);
638 //=======================================================================
639 //function : DrawLinearDimension
641 //=======================================================================
642 void PrsDim_Dimension::DrawLinearDimension (const Handle(Prs3d_Presentation)& thePresentation,
643 const Standard_Integer theMode,
644 const gp_Pnt& theFirstPoint,
645 const gp_Pnt& theSecondPoint,
646 const Standard_Boolean theIsOneSide)
648 // do not build any dimension for equal points
649 if (theFirstPoint.IsEqual (theSecondPoint, Precision::Confusion()))
651 throw Standard_ProgramError("Can not build presentation for equal points.");
654 Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
656 // For extensions we need to know arrow size, text size and extension size: get it from aspect
657 Standard_Real anArrowLength = aDimensionAspect->ArrowAspect()->Length();
658 Standard_Real anExtensionSize = aDimensionAspect->ExtensionSize();
659 // prepare label string and compute its geometrical width
660 Standard_Real aLabelWidth;
661 TCollection_ExtendedString aLabelString = GetValueString (aLabelWidth);
663 // add margins to cut dimension lines for 3d text
664 if (aDimensionAspect->IsText3d())
666 aLabelWidth += aDimensionAspect->TextAspect()->Height() * THE_3D_TEXT_MARGIN * 2.0;
669 // handle user-defined and automatic arrow placement
670 Standard_Boolean isArrowsExternal = Standard_False;
671 Standard_Integer aLabelPosition = LabelPosition_None;
673 Prs3d_DimensionTextHorizontalPosition aHorisontalTextPos = aDimensionAspect->TextHorizontalPosition();
674 if (IsTextPositionCustom())
676 if (!AdjustParametersForLinear (myFixedTextPosition, theFirstPoint, theSecondPoint,
677 anExtensionSize, aHorisontalTextPos, myFlyout, myPlane, myIsPlaneCustom))
679 throw Standard_ProgramError("Can not adjust plane to the custom label position.");
683 FitTextAlignmentForLinear (theFirstPoint, theSecondPoint, theIsOneSide, aHorisontalTextPos,
684 aLabelPosition, isArrowsExternal);
686 // compute dimension line points
687 gp_Pnt aLineBegPoint, aLineEndPoint;
688 ComputeFlyoutLinePoints (theFirstPoint, theSecondPoint, aLineBegPoint, aLineEndPoint);
689 gp_Lin aDimensionLine = gce_MakeLin (aLineBegPoint, aLineEndPoint);
691 // compute arrows positions and directions
692 gp_Dir aFirstArrowDir = aDimensionLine.Direction().Reversed();
693 gp_Dir aSecondArrowDir = aDimensionLine.Direction();
694 gp_Dir aFirstExtensionDir = aDimensionLine.Direction().Reversed();
695 gp_Dir aSecondExtensionDir = aDimensionLine.Direction();
697 gp_Pnt aFirstArrowBegin (0.0, 0.0, 0.0);
698 gp_Pnt aFirstArrowEnd (0.0, 0.0, 0.0);
699 gp_Pnt aSecondArrowBegin (0.0, 0.0, 0.0);
700 gp_Pnt aSecondArrowEnd (0.0, 0.0, 0.0);
702 if (isArrowsExternal)
704 aFirstArrowDir.Reverse();
705 aSecondArrowDir.Reverse();
708 aFirstArrowBegin = aLineBegPoint;
709 aSecondArrowBegin = aLineEndPoint;
710 aFirstArrowEnd = aLineBegPoint.Translated (-gp_Vec (aFirstArrowDir).Scaled (anArrowLength));
711 aSecondArrowEnd = aLineEndPoint.Translated (-gp_Vec (aSecondArrowDir).Scaled (anArrowLength));
713 gp_Pnt aCenterLineBegin = isArrowsExternal
714 ? aLineBegPoint : aFirstArrowEnd;
716 gp_Pnt aCenterLineEnd = isArrowsExternal || theIsOneSide
717 ? aLineEndPoint : aSecondArrowEnd;
720 switch (aLabelPosition & LabelPosition_HMask)
722 // ------------------------------------------------------------------------ //
724 // -------------------------------------------------------------------------//
725 case LabelPosition_HCenter:
727 // add label on dimension or extension line to presentation
728 gp_Pnt aTextPos = IsTextPositionCustom() ? myFixedTextPosition
729 : (aCenterLineBegin.XYZ() + aCenterLineEnd.XYZ()) * 0.5;
730 gp_Dir aTextDir = aDimensionLine.Direction();
732 // add text primitives
733 if (theMode == ComputeMode_All || theMode == ComputeMode_Text)
735 thePresentation->NewGroup();
736 drawText (thePresentation,
743 // add dimension line primitives
744 if (theMode == ComputeMode_All || theMode == ComputeMode_Line)
746 Standard_Boolean isLineBreak = aDimensionAspect->TextVerticalPosition() == Prs3d_DTVP_Center
747 && aDimensionAspect->IsText3d();
749 Handle(Graphic3d_ArrayOfSegments) aPrimSegments = new Graphic3d_ArrayOfSegments (isLineBreak ? 4 : 2);
751 // compute continuous or sectioned main line segments
754 Standard_Real aPTextPosition = ElCLib::Parameter (aDimensionLine, aTextPos);
755 gp_Pnt aSection1Beg = aCenterLineBegin;
756 gp_Pnt aSection1End = ElCLib::Value (aPTextPosition - (aLabelWidth * 0.5), aDimensionLine);
757 gp_Pnt aSection2Beg = ElCLib::Value (aPTextPosition + (aLabelWidth * 0.5), aDimensionLine);
758 gp_Pnt aSection2End = aCenterLineEnd;
760 aPrimSegments->AddVertex (aSection1Beg);
761 aPrimSegments->AddVertex (aSection1End);
762 aPrimSegments->AddVertex (aSection2Beg);
763 aPrimSegments->AddVertex (aSection2End);
765 SelectionGeometry::Curve& aLeftSensitiveCurve = mySelectionGeom.NewCurve();
766 SelectionGeometry::Curve& aRightSensitiveCurve = mySelectionGeom.NewCurve();
767 aLeftSensitiveCurve.Append (aSection1Beg);
768 aLeftSensitiveCurve.Append (aSection1End);
769 aRightSensitiveCurve.Append (aSection2Beg);
770 aRightSensitiveCurve.Append (aSection2End);
774 aPrimSegments->AddVertex (aCenterLineBegin);
775 aPrimSegments->AddVertex (aCenterLineEnd);
777 SelectionGeometry::Curve& aSensitiveCurve = mySelectionGeom.NewCurve();
778 aSensitiveCurve.Append (aCenterLineBegin);
779 aSensitiveCurve.Append (aCenterLineEnd);
782 // set text label justification
783 Graphic3d_VerticalTextAlignment aTextJustificaton = Graphic3d_VTA_BOTTOM;
784 switch (aLabelPosition & LabelPosition_VMask)
786 case LabelPosition_Above :
787 case LabelPosition_VCenter : aTextJustificaton = Graphic3d_VTA_BOTTOM; break;
788 case LabelPosition_Below : aTextJustificaton = Graphic3d_VTA_TOP; break;
790 aDimensionAspect->TextAspect()->SetVerticalJustification (aTextJustificaton);
792 // main dimension line, short extension
794 Handle(Graphic3d_Group) aGroup = thePresentation->NewGroup();
795 if (!aDimensionAspect->IsText3d() && theMode == ComputeMode_All)
797 aGroup->SetStencilTestOptions (Standard_True);
799 aGroup->SetPrimitivesAspect (aDimensionAspect->LineAspect()->Aspect());
800 aGroup->AddPrimitiveArray (aPrimSegments);
801 if (!aDimensionAspect->IsText3d() && theMode == ComputeMode_All)
803 aGroup->SetStencilTestOptions (Standard_False);
807 // add arrows to presentation
809 Handle(Graphic3d_Group) aGroup = thePresentation->NewGroup();
810 DrawArrow (thePresentation, aFirstArrowBegin, aFirstArrowDir);
813 DrawArrow (thePresentation, aSecondArrowBegin, aSecondArrowDir);
817 if (!isArrowsExternal)
822 // add arrow extension lines to presentation
824 DrawExtension (thePresentation, aDimensionAspect->ArrowTailSize(),
825 aFirstArrowEnd, aFirstExtensionDir,
826 THE_EMPTY_LABEL, 0.0, theMode, LabelPosition_None);
829 DrawExtension (thePresentation, aDimensionAspect->ArrowTailSize(),
830 aSecondArrowEnd, aSecondExtensionDir,
831 THE_EMPTY_LABEL, 0.0, theMode, LabelPosition_None);
837 // ------------------------------------------------------------------------ //
839 // -------------------------------------------------------------------------//
841 case LabelPosition_Left:
843 // add label on dimension or extension line to presentation
845 // Left extension with the text
846 DrawExtension (thePresentation, anExtensionSize,
857 // add dimension line primitives
858 if (theMode == ComputeMode_All || theMode == ComputeMode_Line)
860 // add central dimension line
862 Handle(Graphic3d_Group) aGroup = thePresentation->NewGroup();
864 // add graphical primitives
865 Handle(Graphic3d_ArrayOfSegments) aPrimSegments = new Graphic3d_ArrayOfSegments (2);
866 aPrimSegments->AddVertex (aCenterLineBegin);
867 aPrimSegments->AddVertex (aCenterLineEnd);
869 aGroup->SetPrimitivesAspect (aDimensionAspect->LineAspect()->Aspect());
870 aGroup->AddPrimitiveArray (aPrimSegments);
872 // add selection primitives
873 SelectionGeometry::Curve& aSensitiveCurve = mySelectionGeom.NewCurve();
874 aSensitiveCurve.Append (aCenterLineBegin);
875 aSensitiveCurve.Append (aCenterLineEnd);
878 // add arrows to presentation
880 Handle(Graphic3d_Group) aGroup = thePresentation->NewGroup();
881 DrawArrow (thePresentation, aFirstArrowBegin, aFirstArrowDir);
884 DrawArrow (thePresentation, aSecondArrowBegin, aSecondArrowDir);
888 if (!isArrowsExternal || theIsOneSide)
893 // add extension lines for external arrows
895 DrawExtension (thePresentation, aDimensionAspect->ArrowTailSize(),
896 aSecondArrowEnd, aSecondExtensionDir,
897 THE_EMPTY_LABEL, 0.0, theMode, LabelPosition_None);
903 // ------------------------------------------------------------------------ //
905 // -------------------------------------------------------------------------//
907 case LabelPosition_Right:
909 // add label on dimension or extension line to presentation
911 // Right extension with text
912 DrawExtension (thePresentation, anExtensionSize,
917 aLabelString, aLabelWidth,
921 if (theMode == ComputeMode_All || theMode == ComputeMode_Line)
923 // add central dimension line
925 Handle(Graphic3d_Group) aGroup = thePresentation->NewGroup();
927 // add graphical primitives
928 Handle(Graphic3d_ArrayOfSegments) aPrimSegments = new Graphic3d_ArrayOfSegments (2);
929 aPrimSegments->AddVertex (aCenterLineBegin);
930 aPrimSegments->AddVertex (aCenterLineEnd);
931 aGroup->SetGroupPrimitivesAspect (aDimensionAspect->LineAspect()->Aspect());
932 aGroup->AddPrimitiveArray (aPrimSegments);
934 // add selection primitives
935 SelectionGeometry::Curve& aSensitiveCurve = mySelectionGeom.NewCurve();
936 aSensitiveCurve.Append (aCenterLineBegin);
937 aSensitiveCurve.Append (aCenterLineEnd);
940 // add arrows to presentation
942 thePresentation->NewGroup();
943 DrawArrow (thePresentation, aSecondArrowBegin, aSecondArrowDir);
946 DrawArrow (thePresentation, aFirstArrowBegin, aFirstArrowDir);
950 if (!isArrowsExternal || theIsOneSide)
955 // add extension lines for external arrows
957 DrawExtension (thePresentation, aDimensionAspect->ArrowTailSize(),
958 aFirstArrowEnd, aFirstExtensionDir,
959 THE_EMPTY_LABEL, 0.0, theMode, LabelPosition_None);
967 // add flyout lines to presentation
968 if (theMode == ComputeMode_All)
970 Handle(Graphic3d_Group) aGroup = thePresentation->NewGroup();
972 Handle(Graphic3d_ArrayOfSegments) aPrimSegments = new Graphic3d_ArrayOfSegments(4);
973 aPrimSegments->AddVertex (theFirstPoint);
974 aPrimSegments->AddVertex (aLineBegPoint);
976 aPrimSegments->AddVertex (theSecondPoint);
977 aPrimSegments->AddVertex (aLineEndPoint);
979 aGroup->SetGroupPrimitivesAspect (aDimensionAspect->LineAspect()->Aspect());
980 aGroup->AddPrimitiveArray (aPrimSegments);
983 mySelectionGeom.IsComputed = Standard_True;
986 //=======================================================================
987 //function : ComputeFlyoutLinePoints
989 //=======================================================================
990 void PrsDim_Dimension::ComputeFlyoutLinePoints (const gp_Pnt& theFirstPoint, const gp_Pnt& theSecondPoint,
991 gp_Pnt& theLineBegPoint, gp_Pnt& theLineEndPoint)
993 // compute dimension line points
994 gp_Ax1 aPlaneNormal = GetPlane().Axis();
995 // compute flyout direction vector
996 gp_Dir aTargetPointsVector = gce_MakeDir (theFirstPoint, theSecondPoint);
997 gp_Dir aFlyoutVector = aPlaneNormal.Direction() ^ aTargetPointsVector;
998 // create lines for layouts
999 gp_Lin aLine1 (theFirstPoint, aFlyoutVector);
1000 gp_Lin aLine2 (theSecondPoint, aFlyoutVector);
1002 // Get flyout end points
1003 theLineBegPoint = ElCLib::Value (ElCLib::Parameter (aLine1, theFirstPoint) + GetFlyout(), aLine1);
1004 theLineEndPoint = ElCLib::Value (ElCLib::Parameter (aLine2, theSecondPoint) + GetFlyout(), aLine2);
1007 //=======================================================================
1008 //function : ComputeLinearFlyouts
1010 //=======================================================================
1011 void PrsDim_Dimension::ComputeLinearFlyouts (const Handle(SelectMgr_Selection)& theSelection,
1012 const Handle(SelectMgr_EntityOwner)& theOwner,
1013 const gp_Pnt& theFirstPoint,
1014 const gp_Pnt& theSecondPoint)
1016 // count flyout direction
1017 gp_Ax1 aPlaneNormal = GetPlane().Axis();
1018 gp_Dir aTargetPointsVector = gce_MakeDir (theFirstPoint, theSecondPoint);
1020 // count a flyout direction vector.
1021 gp_Dir aFlyoutVector = aPlaneNormal.Direction() ^ aTargetPointsVector;
1023 // create lines for layouts
1024 gp_Lin aLine1 (theFirstPoint, aFlyoutVector);
1025 gp_Lin aLine2 (theSecondPoint, aFlyoutVector);
1027 // get flyout end points
1028 gp_Pnt aFlyoutEnd1 = ElCLib::Value (ElCLib::Parameter (aLine1, theFirstPoint) + GetFlyout(), aLine1);
1029 gp_Pnt aFlyoutEnd2 = ElCLib::Value (ElCLib::Parameter (aLine2, theSecondPoint) + GetFlyout(), aLine2);
1031 // fill sensitive entity for flyouts
1032 Handle(Select3D_SensitiveGroup) aSensitiveEntity = new Select3D_SensitiveGroup (theOwner);
1033 aSensitiveEntity->Add (new Select3D_SensitiveSegment (theOwner, theFirstPoint, aFlyoutEnd1));
1034 aSensitiveEntity->Add (new Select3D_SensitiveSegment (theOwner, theSecondPoint, aFlyoutEnd2));
1035 theSelection->Add (aSensitiveEntity);
1038 //=======================================================================
1039 //function : CircleFromPlanarFace
1040 //purpose : if possible computes circle from planar face
1041 //=======================================================================
1042 Standard_Boolean PrsDim_Dimension::CircleFromPlanarFace (const TopoDS_Face& theFace,
1043 Handle(Geom_Curve)& theCurve,
1044 gp_Pnt& theFirstPoint,
1045 gp_Pnt& theLastPoint)
1047 TopExp_Explorer anIt (theFace, TopAbs_EDGE);
1048 for ( ; anIt.More(); anIt.Next())
1050 TopoDS_Edge aCurEdge = TopoDS::Edge (anIt.Current());
1051 if (PrsDim::ComputeGeometry (aCurEdge, theCurve, theFirstPoint, theLastPoint))
1053 if (theCurve->IsInstance (STANDARD_TYPE(Geom_Circle)))
1055 return Standard_True;
1059 return Standard_False;
1062 //=======================================================================
1063 //function : CircleFromEdge
1064 //purpose : if possible computes circle from edge
1065 //=======================================================================
1066 Standard_Boolean PrsDim_Dimension::CircleFromEdge (const TopoDS_Edge& theEdge,
1068 gp_Pnt& theFirstPoint,
1069 gp_Pnt& theLastPoint)
1071 BRepAdaptor_Curve anAdaptedCurve (theEdge);
1072 switch (anAdaptedCurve.GetType())
1074 case GeomAbs_Circle:
1076 theCircle = anAdaptedCurve.Circle();
1079 case GeomAbs_Ellipse:
1081 gp_Elips anEll = anAdaptedCurve.Ellipse();
1082 if ((anEll.MinorRadius() - anEll.MajorRadius()) >= Precision::Confusion())
1084 return Standard_False;
1086 theCircle = gp_Circ(anEll.Position(),anEll.MinorRadius());
1090 case GeomAbs_Hyperbola:
1091 case GeomAbs_Parabola:
1092 case GeomAbs_BezierCurve:
1093 case GeomAbs_BSplineCurve:
1094 case GeomAbs_OtherCurve:
1096 return Standard_False;
1099 theFirstPoint = anAdaptedCurve.Value (anAdaptedCurve.FirstParameter());
1100 theLastPoint = anAdaptedCurve.Value (anAdaptedCurve.LastParameter());
1101 return Standard_True;
1104 //=======================================================================
1105 //function : InitCircularDimension
1107 //=======================================================================
1108 Standard_Boolean PrsDim_Dimension::InitCircularDimension (const TopoDS_Shape& theShape,
1110 gp_Pnt& theMiddleArcPoint,
1111 Standard_Boolean& theIsClosed)
1114 Handle(Geom_Surface) aBasisSurf;
1115 PrsDim_KindOfSurface aSurfType = PrsDim_KOS_OtherSurface;
1116 gp_Pnt aFirstPoint, aLastPoint;
1117 Standard_Real anOffset = 0.0;
1118 Standard_Real aFirstParam = 0.0;
1119 Standard_Real aLastParam = 0.0;
1121 // Discover circular geometry
1122 switch (theShape.ShapeType())
1126 PrsDim::GetPlaneFromFace (TopoDS::Face (theShape), aPln, aBasisSurf, aSurfType, anOffset);
1128 if (aSurfType == PrsDim_KOS_Plane)
1130 Handle(Geom_Curve) aCurve;
1131 if (!CircleFromPlanarFace (TopoDS::Face (theShape), aCurve, aFirstPoint, aLastPoint))
1133 return Standard_False;
1136 theCircle = Handle(Geom_Circle)::DownCast (aCurve)->Circ();
1141 BRepAdaptor_Surface aSurf1 (TopoDS::Face (theShape));
1142 Standard_Real aFirstU = aSurf1.FirstUParameter();
1143 Standard_Real aLastU = aSurf1.LastUParameter();
1144 Standard_Real aFirstV = aSurf1.FirstVParameter();
1145 Standard_Real aLastV = aSurf1.LastVParameter();
1146 Standard_Real aMidU = (aFirstU + aLastU) * 0.5;
1147 Standard_Real aMidV = (aFirstV + aLastV) * 0.5;
1148 aSurf1.D0 (aMidU, aMidV, aCurPos);
1149 Handle (Adaptor3d_Curve) aBasisCurve;
1150 Standard_Boolean isExpectedType = Standard_False;
1151 if (aSurfType == PrsDim_KOS_Cylinder)
1153 isExpectedType = Standard_True;
1157 if (aSurfType == PrsDim_KOS_Revolution)
1159 aBasisCurve = aSurf1.BasisCurve();
1160 if (aBasisCurve->GetType() == GeomAbs_Line)
1162 isExpectedType = Standard_True;
1165 else if (aSurfType == PrsDim_KOS_Extrusion)
1167 aBasisCurve = aSurf1.BasisCurve();
1168 if (aBasisCurve->GetType() == GeomAbs_Circle)
1170 isExpectedType = Standard_True;
1175 if (!isExpectedType)
1177 return Standard_False;
1180 Handle(Geom_Curve) aCurve = aBasisSurf->VIso(aMidV);
1181 if (aCurve->DynamicType() == STANDARD_TYPE (Geom_Circle))
1183 theCircle = Handle(Geom_Circle)::DownCast (aCurve)->Circ();
1185 else if (aCurve->DynamicType() == STANDARD_TYPE (Geom_TrimmedCurve))
1187 Handle(Geom_TrimmedCurve) aTrimmedCurve = Handle(Geom_TrimmedCurve)::DownCast (aCurve);
1188 aFirstU = aTrimmedCurve->FirstParameter();
1189 aLastU = aTrimmedCurve->LastParameter();
1190 if (aTrimmedCurve->BasisCurve()->DynamicType() == STANDARD_TYPE (Geom_Circle))
1192 theCircle = Handle(Geom_Circle)::DownCast(aTrimmedCurve->BasisCurve())->Circ();
1197 // Compute a circle from 3 points on "aCurve"
1199 aSurf1.D0 (aFirstU, aMidV, aP1);
1200 aSurf1.D0 (aLastU, aMidV, aP2);
1201 GC_MakeCircle aMkCirc (aP1, aCurPos, aP2);
1202 theCircle = aMkCirc.Value()->Circ();
1205 aFirstPoint = ElCLib::Value (aFirstU, theCircle);
1206 aLastPoint = ElCLib::Value (aLastU, theCircle);
1213 TopExp_Explorer anIt (theShape, TopAbs_EDGE);
1216 anEdge = TopoDS::Edge (anIt.Current());
1218 if (!PrsDim_Dimension::CircleFromEdge (anEdge, theCircle, aFirstPoint, aLastPoint))
1220 return Standard_False;
1226 TopoDS_Edge anEdge = TopoDS::Edge (theShape);
1227 if (!PrsDim_Dimension::CircleFromEdge (anEdge, theCircle, aFirstPoint, aLastPoint))
1229 return Standard_False;
1233 case TopAbs_COMPOUND:
1234 case TopAbs_COMPSOLID:
1240 return Standard_False;
1243 theIsClosed = aFirstPoint.IsEqual (aLastPoint, Precision::Confusion());
1245 gp_Pnt aCenter = theCircle.Location();
1247 if (theIsClosed) // Circle
1249 gp_Dir anXDir = theCircle.XAxis().Direction();
1250 theMiddleArcPoint = aCenter.Translated (gp_Vec (anXDir) * theCircle.Radius());
1254 aFirstParam = ElCLib::Parameter (theCircle, aFirstPoint);
1255 aLastParam = ElCLib::Parameter (theCircle, aLastPoint);
1256 if (aFirstParam > aLastParam)
1258 aFirstParam -= 2.0 * M_PI;
1261 Standard_Real aParCurPos = (aFirstParam + aLastParam) * 0.5;
1262 gp_Vec aVec = gp_Vec (aCenter, ElCLib::Value (aParCurPos, theCircle)).Normalized () * theCircle.Radius ();
1263 theMiddleArcPoint = aCenter.Translated (aVec);
1266 return Standard_True;
1269 //=======================================================================
1270 //function : ComputeSelection
1272 //=======================================================================
1273 void PrsDim_Dimension::ComputeSelection (const Handle(SelectMgr_Selection)& theSelection,
1274 const Standard_Integer theMode)
1276 if (!mySelectionGeom.IsComputed)
1281 PrsDim_DimensionSelectionMode aSelectionMode = (PrsDim_DimensionSelectionMode)theMode;
1283 // init appropriate entity owner
1284 Handle(SelectMgr_EntityOwner) aSensitiveOwner;
1286 switch (aSelectionMode)
1288 // neutral selection owner
1289 case PrsDim_DimensionSelectionMode_All:
1290 aSensitiveOwner = new SelectMgr_EntityOwner (this, THE_NEUTRAL_SEL_PRIORITY);
1293 // local selection owners
1294 case PrsDim_DimensionSelectionMode_Line:
1295 case PrsDim_DimensionSelectionMode_Text:
1296 aSensitiveOwner = new PrsDim_DimensionOwner (this, aSelectionMode, THE_LOCAL_SEL_PRIORITY);
1300 if (aSelectionMode == PrsDim_DimensionSelectionMode_All || aSelectionMode == PrsDim_DimensionSelectionMode_Line)
1302 // sensitives for dimension line segments
1303 Handle(Select3D_SensitiveGroup) aGroupOfSensitives = new Select3D_SensitiveGroup (aSensitiveOwner);
1305 SelectionGeometry::SeqOfCurves::Iterator aCurveIt (mySelectionGeom.DimensionLine);
1306 for (; aCurveIt.More(); aCurveIt.Next())
1308 const SelectionGeometry::HCurve& aCurveData = aCurveIt.Value();
1310 TColgp_Array1OfPnt aSensitivePnts (1, aCurveData->Length());
1311 for (Standard_Integer aPntIt = 1; aPntIt <= aCurveData->Length(); ++aPntIt)
1313 aSensitivePnts.ChangeValue (aPntIt) = aCurveData->Value (aPntIt);
1316 aGroupOfSensitives->Add (new Select3D_SensitiveCurve (aSensitiveOwner, aSensitivePnts));
1319 Standard_Real anArrowLength = myDrawer->DimensionAspect()->ArrowAspect()->Length();
1320 Standard_Real anArrowAngle = myDrawer->DimensionAspect()->ArrowAspect()->Angle();
1322 // sensitives for arrows
1323 SelectionGeometry::SeqOfArrows::Iterator anArrowIt (mySelectionGeom.Arrows);
1324 for (; anArrowIt.More(); anArrowIt.Next())
1326 const SelectionGeometry::HArrow& anArrow = anArrowIt.Value();
1328 gp_Pnt aSidePnt1 (gp::Origin());
1329 gp_Pnt aSidePnt2 (gp::Origin());
1330 const gp_Dir& aPlane = GetPlane().Axis().Direction();
1331 const gp_Pnt& aPeak = anArrow->Position;
1332 const gp_Dir& aDir = anArrow->Direction;
1334 // compute points for arrow in plane
1335 PointsForArrow (aPeak, aDir, aPlane, anArrowLength, anArrowAngle, aSidePnt1, aSidePnt2);
1337 aGroupOfSensitives->Add (new Select3D_SensitiveTriangle (aSensitiveOwner, aPeak, aSidePnt1, aSidePnt2));
1339 if (!myDrawer->DimensionAspect()->IsArrows3d())
1344 // compute points for orthogonal sensitive plane
1345 gp_Dir anOrthoPlane = anArrow->Direction.Crossed (aPlane);
1347 PointsForArrow (aPeak, aDir, anOrthoPlane, anArrowLength, anArrowAngle, aSidePnt1, aSidePnt2);
1349 aGroupOfSensitives->Add (new Select3D_SensitiveTriangle (aSensitiveOwner, aPeak, aSidePnt1, aSidePnt2));
1352 theSelection->Add (aGroupOfSensitives);
1355 // sensitives for text element
1356 if (aSelectionMode == PrsDim_DimensionSelectionMode_All || aSelectionMode == PrsDim_DimensionSelectionMode_Text)
1358 Handle(Select3D_SensitiveEntity) aTextSensitive;
1360 gp_Ax2 aTextAxes (mySelectionGeom.TextPos,
1361 GetPlane().Axis().Direction(),
1362 mySelectionGeom.TextDir);
1364 if (myDrawer->DimensionAspect()->IsText3d())
1366 // sensitive planar rectangle for text
1367 Standard_Real aDx = mySelectionGeom.TextWidth * 0.5;
1368 Standard_Real aDy = mySelectionGeom.TextHeight * 0.5;
1370 gp_Trsf aLabelPlane;
1371 aLabelPlane.SetTransformation (aTextAxes, gp::XOY());
1373 TColgp_Array1OfPnt aRectanglePoints(1, 4);
1374 aRectanglePoints.ChangeValue(1) = gp_Pnt (-aDx, -aDy, 0.0).Transformed (aLabelPlane);
1375 aRectanglePoints.ChangeValue(2) = gp_Pnt (-aDx, aDy, 0.0).Transformed (aLabelPlane);
1376 aRectanglePoints.ChangeValue(3) = gp_Pnt ( aDx, aDy, 0.0).Transformed (aLabelPlane);
1377 aRectanglePoints.ChangeValue(4) = gp_Pnt ( aDx, -aDy, 0.0).Transformed (aLabelPlane);
1379 Poly_Array1OfTriangle aTriangles(1, 2);
1380 aTriangles.ChangeValue(1) = Poly_Triangle(1, 2, 3);
1381 aTriangles.ChangeValue(2) = Poly_Triangle(1, 3, 4);
1383 Handle(Poly_Triangulation) aRectanglePoly =
1384 new Poly_Triangulation(aRectanglePoints, aTriangles);
1387 new Select3D_SensitiveTriangulation (aSensitiveOwner, aRectanglePoly, TopLoc_Location(), Standard_True);
1391 gp_Circ aTextGeom (aTextAxes, mySelToleranceForText2d != 0.0
1392 ? mySelToleranceForText2d : 1.0);
1393 aTextSensitive = new Select3D_SensitiveCircle (aSensitiveOwner, aTextGeom, Standard_True);
1396 theSelection->Add (aTextSensitive);
1399 // callback for flyout sensitive calculation
1400 if (aSelectionMode == PrsDim_DimensionSelectionMode_All)
1402 ComputeFlyoutSelection (theSelection, aSensitiveOwner);
1406 //=======================================================================
1407 //function : PointsForArrow
1409 //=======================================================================
1410 void PrsDim_Dimension::PointsForArrow (const gp_Pnt& thePeakPnt,
1411 const gp_Dir& theDirection,
1412 const gp_Dir& thePlane,
1413 const Standard_Real theArrowLength,
1414 const Standard_Real theArrowAngle,
1415 gp_Pnt& theSidePnt1,
1416 gp_Pnt& theSidePnt2)
1418 gp_Lin anArrowLin (thePeakPnt, theDirection.Reversed());
1419 gp_Pnt anArrowEnd = ElCLib::Value (theArrowLength, anArrowLin);
1420 gp_Lin anEdgeLin (anArrowEnd, theDirection.Crossed (thePlane));
1422 Standard_Real anEdgeLength = Tan (theArrowAngle) * theArrowLength;
1424 theSidePnt1 = ElCLib::Value ( anEdgeLength, anEdgeLin);
1425 theSidePnt2 = ElCLib::Value (-anEdgeLength, anEdgeLin);
1428 //=======================================================================
1429 //function : GetTextPositionForLinear
1431 //=======================================================================
1432 gp_Pnt PrsDim_Dimension::GetTextPositionForLinear (const gp_Pnt& theFirstPoint,
1433 const gp_Pnt& theSecondPoint,
1434 const Standard_Boolean theIsOneSide) const
1438 return gp::Origin();
1441 gp_Pnt aTextPosition (gp::Origin());
1443 Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
1445 // Get label alignment and arrow orientation.
1446 Standard_Integer aLabelPosition = 0;
1447 Standard_Boolean isArrowsExternal = Standard_False;
1448 FitTextAlignmentForLinear (theFirstPoint, theSecondPoint, theIsOneSide,
1449 aDimensionAspect->TextHorizontalPosition(),
1450 aLabelPosition, isArrowsExternal);
1452 // Compute dimension line points.
1453 gp_Dir aPlaneNormal = GetPlane().Axis().Direction();
1454 gp_Vec aTargetPointsVec (theFirstPoint, theSecondPoint);
1456 // Compute flyout direction vector
1457 gp_Dir aFlyoutVector = aPlaneNormal ^ gp_Dir (aTargetPointsVec);
1459 // create lines for layouts
1460 gp_Lin aLine1 (theFirstPoint, aFlyoutVector);
1461 gp_Lin aLine2 (theSecondPoint, aFlyoutVector);
1462 // Get flyout end points
1463 gp_Pnt aLineBegPoint = ElCLib::Value (ElCLib::Parameter (aLine1, theFirstPoint) + GetFlyout(), aLine1);
1464 gp_Pnt aLineEndPoint = ElCLib::Value (ElCLib::Parameter (aLine2, theSecondPoint) + GetFlyout(), aLine2);
1466 // Get text position.
1467 switch (aLabelPosition & LabelPosition_HMask)
1469 case LabelPosition_Left:
1471 gp_Dir aTargetPointsDir = gce_MakeDir (theFirstPoint, theSecondPoint);
1472 Standard_Real anExtensionSize = aDimensionAspect->ExtensionSize();
1474 Standard_Real anOffset = isArrowsExternal
1475 ? anExtensionSize + aDimensionAspect->ArrowAspect()->Length()
1477 gp_Vec anExtensionVec = gp_Vec (aTargetPointsDir) * -anOffset;
1478 aTextPosition = aLineEndPoint.Translated (anExtensionVec);
1481 case LabelPosition_Right:
1483 gp_Dir aTargetPointsDir = gce_MakeDir (theFirstPoint, theSecondPoint);
1484 Standard_Real anExtensionSize = aDimensionAspect->ExtensionSize();
1486 Standard_Real anOffset = isArrowsExternal
1487 ? anExtensionSize + aDimensionAspect->ArrowAspect()->Length()
1489 gp_Vec anExtensionVec = gp_Vec (aTargetPointsDir) * anOffset;
1490 aTextPosition = aLineBegPoint.Translated (anExtensionVec);
1493 case LabelPosition_HCenter:
1495 aTextPosition = (aLineBegPoint.XYZ() + aLineEndPoint.XYZ()) * 0.5;
1500 return aTextPosition;
1503 //=======================================================================
1504 //function : AdjustParametersForLinear
1506 //=======================================================================
1507 Standard_Boolean PrsDim_Dimension::AdjustParametersForLinear (const gp_Pnt& theTextPos,
1508 const gp_Pnt& theFirstPoint,
1509 const gp_Pnt& theSecondPoint,
1510 Standard_Real& theExtensionSize,
1511 Prs3d_DimensionTextHorizontalPosition& theAlignment,
1512 Standard_Real& theFlyout,
1514 Standard_Boolean& theIsPlaneOld) const
1516 Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
1517 Standard_Real anArrowLength = aDimensionAspect->ArrowAspect()->Length();
1519 gp_Dir aTargetPointsDir = gce_MakeDir (theFirstPoint, theSecondPoint);
1520 gp_Vec aTargetPointsVec (theFirstPoint, theSecondPoint);
1522 // Don't set new plane if the text position lies on the attachment points line.
1523 gp_Lin aTargetPointsLin (theFirstPoint, aTargetPointsDir);
1524 if (!aTargetPointsLin.Contains (theTextPos, Precision::Confusion()))
1526 //Set new automatic plane.
1527 thePlane = gce_MakePln (theTextPos, theFirstPoint, theSecondPoint);
1528 theIsPlaneOld = Standard_False;
1531 // Compute flyout direction vector.
1532 gp_Dir aPlaneNormal = GetPlane().Axis().Direction();
1533 gp_Dir aPositiveFlyout = aPlaneNormal ^ aTargetPointsDir;
1535 // Additional check of collinearity of the plane normal and attachment points vector.
1536 if (aPlaneNormal.IsParallel (aTargetPointsDir, Precision::Angular()))
1538 return Standard_False;
1542 gp_Vec aFirstToTextVec (theFirstPoint, theTextPos);
1544 Standard_Real aCos = aFirstToTextVec.Normalized() * gp_Vec (aTargetPointsDir);
1546 gp_Pnt aTextPosProj = theFirstPoint.Translated
1547 (gp_Vec (aTargetPointsDir) * aFirstToTextVec.Magnitude() * aCos);
1549 // Compute flyout value and direction.
1550 gp_Vec aFlyoutVector = gp_Vec (aTextPosProj, theTextPos);
1553 if (aFlyoutVector.Magnitude() > Precision::Confusion())
1555 theFlyout = gp_Dir (aFlyoutVector).IsOpposite (aPositiveFlyout, Precision::Angular())
1556 ? -aFlyoutVector.Magnitude()
1557 : aFlyoutVector.Magnitude();
1560 // Compute attach points (through which main dimension line passes).
1561 gp_Pnt aFirstAttach = theFirstPoint.Translated (aFlyoutVector);
1562 gp_Pnt aSecondAttach = theSecondPoint.Translated (aFlyoutVector);
1564 // Set horizontal text alignment.
1567 theAlignment = Prs3d_DTHP_Left;
1569 Standard_Real aNewExtSize = theTextPos.Distance (aFirstAttach) - anArrowLength;
1570 theExtensionSize = aNewExtSize < 0.0 ? 0.0 : aNewExtSize;
1572 else if (aTextPosProj.Distance (theFirstPoint) > theFirstPoint.Distance (theSecondPoint))
1574 theAlignment = Prs3d_DTHP_Right;
1576 Standard_Real aNewExtSize = theTextPos.Distance (aSecondAttach) - anArrowLength;
1577 theExtensionSize = aNewExtSize < 0.0 ? 0.0 : aNewExtSize;
1581 theAlignment = Prs3d_DTHP_Center;
1583 return Standard_True;
1586 //=======================================================================
1587 //function : FitTextAlignmentForLinear
1589 //=======================================================================
1590 void PrsDim_Dimension::FitTextAlignmentForLinear (const gp_Pnt& theFirstPoint,
1591 const gp_Pnt& theSecondPoint,
1592 const Standard_Boolean theIsOneSide,
1593 const Prs3d_DimensionTextHorizontalPosition& theHorizontalTextPos,
1594 Standard_Integer& theLabelPosition,
1595 Standard_Boolean& theIsArrowsExternal) const
1597 theLabelPosition = LabelPosition_None;
1598 theIsArrowsExternal = Standard_False;
1600 // Compute dimension line points
1601 gp_Ax1 aPlaneNormal = GetPlane().Axis();
1602 gp_Dir aTargetPointsVector = gce_MakeDir (theFirstPoint, theSecondPoint);
1604 // compute flyout direction vector
1605 gp_Dir aFlyoutVector = aPlaneNormal.Direction() ^ aTargetPointsVector;
1607 // create lines for layouts
1608 gp_Lin aLine1 (theFirstPoint, aFlyoutVector);
1609 gp_Lin aLine2 (theSecondPoint, aFlyoutVector);
1611 // Get flyout end points
1612 gp_Pnt aLineBegPoint = ElCLib::Value (ElCLib::Parameter (aLine1, theFirstPoint) + GetFlyout(), aLine1);
1613 gp_Pnt aLineEndPoint = ElCLib::Value (ElCLib::Parameter (aLine2, theSecondPoint) + GetFlyout(), aLine2);
1615 Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
1617 // For extensions we need to know arrow size, text size and extension size: get it from aspect
1618 Standard_Real anArrowLength = aDimensionAspect->ArrowAspect()->Length();
1620 // prepare label string and compute its geometrical width
1621 Standard_Real aLabelWidth;
1622 TCollection_ExtendedString aLabelString = GetValueString (aLabelWidth);
1624 // Add margins to cut dimension lines for 3d text
1625 if (aDimensionAspect->IsText3d())
1627 aLabelWidth += aDimensionAspect->TextAspect()->Height() * THE_3D_TEXT_MARGIN * 2.0;
1630 // Handle user-defined and automatic arrow placement
1631 switch (aDimensionAspect->ArrowOrientation())
1633 case Prs3d_DAO_External: theIsArrowsExternal = true; break;
1634 case Prs3d_DAO_Internal: theIsArrowsExternal = false; break;
1637 // Add margin to ensure a small tail between text and arrow
1638 Standard_Real anArrowMargin = aDimensionAspect->IsText3d()
1639 ? aDimensionAspect->TextAspect()->Height() * THE_3D_TEXT_MARGIN
1642 Standard_Real aDimensionWidth = aLineBegPoint.Distance (aLineEndPoint);
1643 Standard_Real anArrowsWidth = theIsOneSide
1644 ? anArrowLength + anArrowMargin
1645 : (anArrowLength + anArrowMargin) * 2.0;
1647 theIsArrowsExternal = aDimensionWidth < aLabelWidth + anArrowsWidth;
1652 // Handle user-defined and automatic text placement
1653 switch (theHorizontalTextPos)
1655 case Prs3d_DTHP_Left : theLabelPosition |= LabelPosition_Left; break;
1656 case Prs3d_DTHP_Right : theLabelPosition |= LabelPosition_Right; break;
1657 case Prs3d_DTHP_Center: theLabelPosition |= LabelPosition_HCenter; break;
1658 case Prs3d_DTHP_Fit:
1660 Standard_Real aDimensionWidth = aLineBegPoint.Distance (aLineEndPoint);
1661 Standard_Real anArrowsWidth = theIsOneSide ? anArrowLength : 2.0 * anArrowLength;
1662 Standard_Real aContentWidth = theIsArrowsExternal ? aLabelWidth : aLabelWidth + anArrowsWidth;
1664 theLabelPosition |= aDimensionWidth < aContentWidth ? LabelPosition_Left : LabelPosition_HCenter;
1669 // Handle vertical text placement options
1670 switch (aDimensionAspect->TextVerticalPosition())
1672 case Prs3d_DTVP_Above : theLabelPosition |= LabelPosition_Above; break;
1673 case Prs3d_DTVP_Below : theLabelPosition |= LabelPosition_Below; break;
1674 case Prs3d_DTVP_Center : theLabelPosition |= LabelPosition_VCenter; break;
1678 //=======================================================================
1679 //function : UnsetFixedTextPosition
1681 //=======================================================================
1682 void PrsDim_Dimension::UnsetFixedTextPosition()
1684 myIsTextPositionFixed = Standard_False;
1685 myFixedTextPosition = gp::Origin();