1 // Created on: 2013-11-11
2 // Created by: Anastasia BORISOVA
3 // Copyright (c) 2013-2014 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
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.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16 #include <PrsDim_Dimension.hxx>
17
18 #include <PrsDim.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>
26 #include <ElCLib.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>
68 #include <TopoDS.hxx>
69 #include <TopoDS_Edge.hxx>
70 #include <TopoDS_Vertex.hxx>
71 #include <V3d_Viewer.hxx>
72 #include <Units.hxx>
73 #include <Units_UnitsDictionary.hxx>
74 #include <UnitsAPI.hxx>
75
76 IMPLEMENT_STANDARD_RTTIEXT(PrsDim_Dimension, AIS_InteractiveObject)
77
78 namespace
79 {
80 // default text strings
81 static const TCollection_ExtendedString THE_EMPTY_LABEL;
82 static const TCollection_AsciiString THE_UNDEFINED_UNITS;
83
84 // default text margin and resolution
85 static const Standard_Real THE_3D_TEXT_MARGIN = 0.1;
86
87 // default selection priorities
88 static const Standard_Integer THE_NEUTRAL_SEL_PRIORITY = 5;
89 static const Standard_Integer THE_LOCAL_SEL_PRIORITY = 6;
90 }
91
92 //=======================================================================
93 //function : Constructor
94 //purpose :
95 //=======================================================================
PrsDim_Dimension(const PrsDim_KindOfDimension theType)96 PrsDim_Dimension::PrsDim_Dimension (const PrsDim_KindOfDimension theType)
97 : AIS_InteractiveObject (),
98 mySelToleranceForText2d(0.0),
99 myValueType (ValueType_Computed),
100 myCustomValue (0.0),
101 myCustomStringValue (),
102 myIsTextPositionFixed (Standard_False),
103 mySpecialSymbol (' '),
104 myDisplaySpecialSymbol (PrsDim_DisplaySpecialSymbol_No),
105 myGeometryType (GeometryType_UndefShapes),
106 myIsPlaneCustom (Standard_False),
107 myFlyout (0.0),
108 myIsGeometryValid (Standard_False),
109 myKindOfDimension (theType)
110 {
111 }
112
113 //=======================================================================
114 //function : SetCustomValue
115 //purpose :
116 //=======================================================================
SetCustomValue(const Standard_Real theValue)117 void PrsDim_Dimension::SetCustomValue (const Standard_Real theValue)
118 {
119 if (myValueType == ValueType_CustomReal && myCustomValue == theValue)
120 {
121 return;
122 }
123
124 myValueType = ValueType_CustomReal;
125 myCustomValue = theValue;
126
127 SetToUpdate();
128 }
129
130 //=======================================================================
131 //function : SetCustomValue
132 //purpose :
133 //=======================================================================
SetCustomValue(const TCollection_ExtendedString & theValue)134 void PrsDim_Dimension::SetCustomValue (const TCollection_ExtendedString& theValue)
135 {
136 if (myValueType == ValueType_CustomText && myCustomStringValue == theValue)
137 {
138 return;
139 }
140
141 myValueType = ValueType_CustomText;
142 myCustomStringValue = theValue;
143
144 SetToUpdate();
145 }
146
147 //=======================================================================
148 //function : SetUserPlane
149 //purpose :
150 //=======================================================================
SetCustomPlane(const gp_Pln & thePlane)151 void PrsDim_Dimension::SetCustomPlane (const gp_Pln& thePlane)
152 {
153 myPlane = thePlane;
154 myIsPlaneCustom = Standard_True;
155
156 // Disable fixed (custom) text position
157 UnsetFixedTextPosition();
158
159 // Check validity if geometry has been set already.
160 if (IsValid())
161 {
162 SetToUpdate();
163 }
164 }
165
166 //=======================================================================
167 //function : SetDimensionAspect
168 //purpose :
169 //=======================================================================
SetDimensionAspect(const Handle (Prs3d_DimensionAspect)& theDimensionAspect)170 void PrsDim_Dimension::SetDimensionAspect (const Handle(Prs3d_DimensionAspect)& theDimensionAspect)
171 {
172 myDrawer->SetDimensionAspect (theDimensionAspect);
173
174 SetToUpdate();
175 }
176
177 //=======================================================================
178 //function : SetDisplaySpecialSymbol
179 //purpose :
180 //=======================================================================
SetDisplaySpecialSymbol(const PrsDim_DisplaySpecialSymbol theDisplaySpecSymbol)181 void PrsDim_Dimension::SetDisplaySpecialSymbol (const PrsDim_DisplaySpecialSymbol theDisplaySpecSymbol)
182 {
183 if (myDisplaySpecialSymbol == theDisplaySpecSymbol)
184 {
185 return;
186 }
187
188 myDisplaySpecialSymbol = theDisplaySpecSymbol;
189
190 SetToUpdate();
191 }
192
193 //=======================================================================
194 //function : SetSpecialSymbol
195 //purpose :
196 //=======================================================================
SetSpecialSymbol(const Standard_ExtCharacter theSpecialSymbol)197 void PrsDim_Dimension::SetSpecialSymbol (const Standard_ExtCharacter theSpecialSymbol)
198 {
199 if (mySpecialSymbol == theSpecialSymbol)
200 {
201 return;
202 }
203
204 mySpecialSymbol = theSpecialSymbol;
205
206 SetToUpdate();
207 }
208
209 //=======================================================================
210 //function : SetSelToleranceForText2d
211 //purpose :
212 //=======================================================================
SetSelToleranceForText2d(const Standard_Real theTol)213 void PrsDim_Dimension::SetSelToleranceForText2d (const Standard_Real theTol)
214 {
215 if (mySelToleranceForText2d == theTol)
216 {
217 return;
218 }
219
220 mySelToleranceForText2d = theTol;
221
222 SetToUpdate();
223 }
224
225 //=======================================================================
226 //function : SetFlyout
227 //purpose :
228 //=======================================================================
SetFlyout(const Standard_Real theFlyout)229 void PrsDim_Dimension::SetFlyout (const Standard_Real theFlyout)
230 {
231 if (myFlyout == theFlyout)
232 {
233 return;
234 }
235
236 myFlyout = theFlyout;
237
238 // Disable fixed text position
239 UnsetFixedTextPosition();
240
241 SetToUpdate();
242 }
243
244 //=======================================================================
245 //function : GetDisplayUnits
246 //purpose :
247 //=======================================================================
GetDisplayUnits() const248 const TCollection_AsciiString& PrsDim_Dimension::GetDisplayUnits() const
249 {
250 return THE_UNDEFINED_UNITS;
251 }
252
253 //=======================================================================
254 //function : GetModelUnits
255 //purpose :
256 //=======================================================================
GetModelUnits() const257 const TCollection_AsciiString& PrsDim_Dimension::GetModelUnits() const
258 {
259 return THE_UNDEFINED_UNITS;
260 }
261
262 //=======================================================================
263 //function : ValueToDisplayUnits
264 //purpose :
265 //=======================================================================
ValueToDisplayUnits() const266 Standard_Real PrsDim_Dimension::ValueToDisplayUnits() const
267 {
268 return UnitsAPI::AnyToAny (GetValue(),
269 GetModelUnits().ToCString(),
270 GetDisplayUnits().ToCString());
271 }
272
273 //=======================================================================
274 //function : GetValueString
275 //purpose :
276 //=======================================================================
GetValueString(Standard_Real & theWidth) const277 TCollection_ExtendedString PrsDim_Dimension::GetValueString (Standard_Real& theWidth) const
278 {
279 TCollection_ExtendedString aValueStr;
280 if (myValueType == ValueType_CustomText)
281 {
282 aValueStr = myCustomStringValue;
283 }
284 else
285 {
286 // format value string using "sprintf"
287 TCollection_AsciiString aFormatStr = myDrawer->DimensionAspect()->ValueStringFormat();
288
289 char aFmtBuffer[256];
290 sprintf (aFmtBuffer, aFormatStr.ToCString(), ValueToDisplayUnits());
291 aValueStr = TCollection_ExtendedString (aFmtBuffer);
292 }
293
294 // add units to values string
295 if (myDrawer->DimensionAspect()->IsUnitsDisplayed())
296 {
297 aValueStr += " ";
298 aValueStr += TCollection_ExtendedString (GetDisplayUnits());
299 }
300
301 switch (myDisplaySpecialSymbol)
302 {
303 case PrsDim_DisplaySpecialSymbol_Before: aValueStr.Insert (1, mySpecialSymbol); break;
304 case PrsDim_DisplaySpecialSymbol_After: aValueStr.Insert (aValueStr.Length() + 1, mySpecialSymbol); break;
305 case PrsDim_DisplaySpecialSymbol_No: break;
306 }
307
308 // Get text style parameters
309 Handle(Prs3d_TextAspect) aTextAspect = myDrawer->DimensionAspect()->TextAspect();
310 NCollection_Utf8String anUTFString (aValueStr.ToExtString());
311
312 theWidth = 0.0;
313
314 if (myDrawer->DimensionAspect()->IsText3d())
315 {
316 // text width produced by BRepFont
317 Font_BRepFont aFont;
318 if (aFont.FindAndInit (aTextAspect->Aspect()->Font(), aTextAspect->Aspect()->GetTextFontAspect(), aTextAspect->Height(), Font_StrictLevel_Any))
319 {
320 for (NCollection_Utf8Iter anIter = anUTFString.Iterator(); *anIter != 0; )
321 {
322 Standard_Utf32Char aCurrChar = *anIter;
323 Standard_Utf32Char aNextChar = *(++anIter);
324 theWidth += aFont.AdvanceX (aCurrChar, aNextChar);
325 }
326 }
327 }
328 else
329 {
330 // Text width for 1:1 scale 2D case
331 Font_FTFontParams aFontParams;
332 const Graphic3d_RenderingParams& aRendParams = GetContext()->CurrentViewer()->DefaultRenderingParams();
333 aFontParams.PointSize = (unsigned int )aTextAspect->Height();
334 aFontParams.Resolution = aRendParams.Resolution;
335 aFontParams.FontHinting = aRendParams.FontHinting;
336 if (Handle(Font_FTFont) aFont = Font_FTFont::FindAndCreate (aTextAspect->Aspect()->Font(),
337 aTextAspect->Aspect()->GetTextFontAspect(),
338 aFontParams,
339 Font_StrictLevel_Any))
340 {
341 for (NCollection_Utf8Iter anIter = anUTFString.Iterator(); *anIter != 0; )
342 {
343 Standard_Utf32Char aCurrChar = *anIter;
344 Standard_Utf32Char aNextChar = *(++anIter);
345 theWidth += (Standard_Real) aFont->AdvanceX (aCurrChar, aNextChar);
346 }
347 }
348 }
349
350 return aValueStr;
351 }
352
353 //=======================================================================
354 //function : DrawArrow
355 //purpose :
356 //=======================================================================
DrawArrow(const Handle (Prs3d_Presentation)& thePresentation,const gp_Pnt & theLocation,const gp_Dir & theDirection)357 void PrsDim_Dimension::DrawArrow (const Handle(Prs3d_Presentation)& thePresentation,
358 const gp_Pnt& theLocation,
359 const gp_Dir& theDirection)
360 {
361 Handle(Graphic3d_Group) aGroup = thePresentation->NewGroup();
362
363 Standard_Real aLength = myDrawer->DimensionAspect()->ArrowAspect()->Length();
364 Standard_Real anAngle = myDrawer->DimensionAspect()->ArrowAspect()->Angle();
365 Standard_Boolean isZoomable = myDrawer->DimensionAspect()->ArrowAspect()->IsZoomable();
366
367 if (myDrawer->DimensionAspect()->IsArrows3d())
368 {
369 Prs3d_Arrow::Draw (aGroup,
370 theLocation,
371 theDirection,
372 anAngle,
373 aLength);
374 aGroup->SetGroupPrimitivesAspect (myDrawer->DimensionAspect()->ArrowAspect()->Aspect());
375 }
376 else
377 {
378 gp_Pnt aLocation = isZoomable ? theLocation : gp::Origin();
379 gp_Pnt aLeftPoint (gp::Origin());
380 gp_Pnt aRightPoint (gp::Origin());
381 const gp_Dir& aPlane = GetPlane().Axis().Direction();
382
383 PointsForArrow (aLocation, theDirection, aPlane, aLength, anAngle, aLeftPoint, aRightPoint);
384
385 Handle(Graphic3d_ArrayOfTriangles) anArrow = new Graphic3d_ArrayOfTriangles(3);
386
387 anArrow->AddVertex (aLeftPoint);
388 anArrow->AddVertex (aLocation);
389 anArrow->AddVertex (aRightPoint);
390
391 // Set aspect for arrow triangles
392 Graphic3d_PolygonOffset aPolOffset;
393 aPolOffset.Mode = Aspect_POM_Off;
394 aPolOffset.Factor = 0.0f;
395 aPolOffset.Units = 0.0f;
396 Handle(Graphic3d_AspectFillArea3d) aShadingStyle = new Graphic3d_AspectFillArea3d();
397 aShadingStyle->SetInteriorStyle (Aspect_IS_SOLID);
398 aShadingStyle->SetColor (myDrawer->DimensionAspect()->ArrowAspect()->Aspect()->Color());
399 aShadingStyle->SetShadingModel (Graphic3d_TypeOfShadingModel_Unlit);
400 aShadingStyle->SetPolygonOffset (aPolOffset);
401
402 aGroup->SetPrimitivesAspect (aShadingStyle);
403 aGroup->AddPrimitiveArray (anArrow);
404 if (!isZoomable)
405 {
406 aGroup->SetTransformPersistence (new Graphic3d_TransformPers (Graphic3d_TMF_ZoomPers, theLocation));
407 }
408 }
409
410 SelectionGeometry::Arrow& aSensitiveArrow = mySelectionGeom.NewArrow();
411 aSensitiveArrow.Position = theLocation;
412 aSensitiveArrow.Direction = theDirection;
413 }
414
415 //=======================================================================
416 //function : drawText
417 //purpose :
418 //=======================================================================
drawText(const Handle (Prs3d_Presentation)& thePresentation,const gp_Pnt & theTextPos,const gp_Dir & theTextDir,const TCollection_ExtendedString & theText,const Standard_Integer theLabelPosition)419 void PrsDim_Dimension::drawText (const Handle(Prs3d_Presentation)& thePresentation,
420 const gp_Pnt& theTextPos,
421 const gp_Dir& theTextDir,
422 const TCollection_ExtendedString& theText,
423 const Standard_Integer theLabelPosition)
424 {
425 Handle(Graphic3d_Group) aGroup = thePresentation->NewGroup();
426 if (myDrawer->DimensionAspect()->IsText3d())
427 {
428 // getting font parameters
429 Handle(Prs3d_TextAspect) aTextAspect = myDrawer->DimensionAspect()->TextAspect();
430 Quantity_Color aColor = aTextAspect->Aspect()->Color();
431 Font_FontAspect aFontAspect = aTextAspect->Aspect()->GetTextFontAspect();
432 Standard_Real aFontHeight = aTextAspect->Height();
433
434 // creating TopoDS_Shape for text
435 Font_BRepFont aFont (aTextAspect->Aspect()->Font().ToCString(),
436 aFontAspect, aFontHeight);
437 NCollection_Utf8String anUTFString (theText.ToExtString());
438
439 Font_BRepTextBuilder aBuilder;
440 TopoDS_Shape aTextShape = aBuilder.Perform (aFont, anUTFString);
441
442 // compute text width with kerning
443 Standard_Real aTextWidth = 0.0;
444 Standard_Real aTextHeight = aFont.Ascender() + aFont.Descender();
445
446 for (NCollection_Utf8Iter anIter = anUTFString.Iterator(); *anIter != 0; )
447 {
448 Standard_Utf32Char aCurrChar = *anIter;
449 Standard_Utf32Char aNextChar = *(++anIter);
450 aTextWidth += aFont.AdvanceX (aCurrChar, aNextChar);
451 }
452
453 // formating text position in XOY plane
454 Standard_Integer aHLabelPos = theLabelPosition & LabelPosition_HMask;
455 Standard_Integer aVLabelPos = theLabelPosition & LabelPosition_VMask;
456
457 gp_Dir aTextDir (aHLabelPos == LabelPosition_Left ? -theTextDir : theTextDir);
458
459 // compute label offsets
460 Standard_Real aMarginSize = aFontHeight * THE_3D_TEXT_MARGIN;
461 Standard_Real aCenterHOffset = 0.0;
462 Standard_Real aCenterVOffset = 0.0;
463 switch (aHLabelPos)
464 {
465 case LabelPosition_HCenter : aCenterHOffset = 0.0; break;
466 case LabelPosition_Right : aCenterHOffset = aTextWidth / 2.0 + aMarginSize; break;
467 case LabelPosition_Left : aCenterHOffset = -aTextWidth / 2.0 - aMarginSize; break;
468 }
469 switch (aVLabelPos)
470 {
471 case LabelPosition_VCenter : aCenterVOffset = 0.0; break;
472 case LabelPosition_Above : aCenterVOffset = aTextHeight / 2.0 + aMarginSize; break;
473 case LabelPosition_Below : aCenterVOffset = -aTextHeight / 2.0 - aMarginSize; break;
474 }
475
476 // compute shape offset transformation
477 Standard_Real aShapeHOffset = aCenterHOffset - aTextWidth / 2.0;
478 Standard_Real aShapeVOffset = aCenterVOffset - aTextHeight / 2.0;
479
480 // center shape in its bounding box (suppress border spacing added by FT_Font)
481 Bnd_Box aShapeBnd;
482 BRepBndLib::AddClose (aTextShape, aShapeBnd);
483
484 Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
485 aShapeBnd.Get (aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
486
487 Standard_Real aXalign = aTextWidth * 0.5 - (aXmax + aXmin) * 0.5;
488 Standard_Real aYalign = aTextHeight * 0.5 - (aYmax + aYmin) * 0.5;
489 aShapeHOffset += aXalign;
490 aShapeVOffset += aYalign;
491
492 gp_Trsf anOffsetTrsf;
493 anOffsetTrsf.SetTranslation (gp::Origin(), gp_Pnt (aShapeHOffset, aShapeVOffset, 0.0));
494 aTextShape.Move (anOffsetTrsf);
495
496 // transform text to myWorkingPlane coordinate system
497 gp_Ax3 aTextCoordSystem (theTextPos, GetPlane().Axis().Direction(), aTextDir);
498 gp_Trsf aTextPlaneTrsf;
499 aTextPlaneTrsf.SetTransformation (aTextCoordSystem, gp_Ax3 (gp::XOY()));
500 aTextShape.Move (aTextPlaneTrsf);
501
502 // set text flipping anchors
503 gp_Trsf aCenterOffsetTrsf;
504 gp_Pnt aCenterOffset (aCenterHOffset, aCenterVOffset, 0.0);
505 aCenterOffsetTrsf.SetTranslation (gp::Origin(), aCenterOffset);
506
507 gp_Pnt aCenterOfLabel (gp::Origin());
508 aCenterOfLabel.Transform (aCenterOffsetTrsf);
509 aCenterOfLabel.Transform (aTextPlaneTrsf);
510
511 gp_Ax2 aFlippingAxes (aCenterOfLabel, GetPlane().Axis().Direction(), aTextDir);
512 aGroup->SetFlippingOptions (Standard_True, aFlippingAxes);
513
514 // draw text
515 if (myDrawer->DimensionAspect()->IsTextShaded())
516 {
517 // Setting text shading and color parameters
518 if (!myDrawer->HasOwnShadingAspect())
519 {
520 myDrawer->SetShadingAspect (new Prs3d_ShadingAspect());
521 }
522
523 Graphic3d_MaterialAspect aShadeMat (Graphic3d_NameOfMaterial_DEFAULT);
524 aShadeMat.SetAmbientColor (Quantity_NOC_BLACK);
525 aShadeMat.SetDiffuseColor (Quantity_NOC_BLACK);
526 aShadeMat.SetSpecularColor(Quantity_NOC_BLACK);
527 myDrawer->ShadingAspect()->Aspect()->SetInteriorColor (aColor);
528 myDrawer->ShadingAspect()->Aspect()->SetBackInteriorColor (aColor);
529 myDrawer->ShadingAspect()->SetMaterial (aShadeMat);
530
531 // drawing text
532 StdPrs_ShadedShape::Add (thePresentation, aTextShape, myDrawer);
533 }
534 else
535 {
536 // Setting color for text
537 if (!myDrawer->HasOwnFreeBoundaryAspect())
538 {
539 myDrawer->SetFreeBoundaryAspect (new Prs3d_LineAspect (aColor, Aspect_TOL_SOLID, 1.0));
540 }
541 myDrawer->FreeBoundaryAspect()->Aspect()->SetColor (aColor);
542
543 // drawing text
544 if (Handle(Graphic3d_ArrayOfPrimitives) anEdges = StdPrs_WFShape::AddAllEdges (aTextShape, myDrawer))
545 {
546 aGroup->SetGroupPrimitivesAspect (myDrawer->FreeBoundaryAspect()->Aspect());
547 aGroup->AddPrimitiveArray (anEdges);
548 }
549 }
550 thePresentation->CurrentGroup()->SetFlippingOptions (Standard_False, gp_Ax2());
551
552 mySelectionGeom.TextPos = aCenterOfLabel;
553 mySelectionGeom.TextDir = aTextDir;
554 mySelectionGeom.TextWidth = aTextWidth + aMarginSize * 2.0;
555 mySelectionGeom.TextHeight = aTextHeight;
556
557 return;
558 }
559
560 // generate primitives for 2D text
561 myDrawer->DimensionAspect()->TextAspect()->Aspect()->SetDisplayType (Aspect_TODT_DIMENSION);
562
563 Prs3d_Text::Draw (aGroup,
564 myDrawer->DimensionAspect()->TextAspect(),
565 theText,
566 theTextPos);
567
568 mySelectionGeom.TextPos = theTextPos;
569 mySelectionGeom.TextDir = theTextDir;
570 mySelectionGeom.TextWidth = 0.0;
571 mySelectionGeom.TextHeight = 0.0;
572 }
573
574 //=======================================================================
575 //function : DrawExtension
576 //purpose :
577 //=======================================================================
DrawExtension(const Handle (Prs3d_Presentation)& thePresentation,const Standard_Real theExtensionSize,const gp_Pnt & theExtensionStart,const gp_Dir & theExtensionDir,const TCollection_ExtendedString & theLabelString,const Standard_Real theLabelWidth,const Standard_Integer theMode,const Standard_Integer theLabelPosition)578 void PrsDim_Dimension::DrawExtension (const Handle(Prs3d_Presentation)& thePresentation,
579 const Standard_Real theExtensionSize,
580 const gp_Pnt& theExtensionStart,
581 const gp_Dir& theExtensionDir,
582 const TCollection_ExtendedString& theLabelString,
583 const Standard_Real theLabelWidth,
584 const Standard_Integer theMode,
585 const Standard_Integer theLabelPosition)
586 {
587 // reference line for extension starting at its connection point
588 gp_Lin anExtensionLine (theExtensionStart, theExtensionDir);
589
590 Standard_Boolean hasLabel = theLabelString.Length() > 0;
591 if (hasLabel && (theMode == ComputeMode_All || theMode == ComputeMode_Text))
592 {
593 // compute text primitives; get its model width
594 gp_Pnt aTextPos = ElCLib::Value (theExtensionSize, anExtensionLine);
595 gp_Dir aTextDir = theExtensionDir;
596
597 Handle(Graphic3d_Group) aGroup = thePresentation->NewGroup();
598 drawText (thePresentation,
599 aTextPos,
600 aTextDir,
601 theLabelString,
602 theLabelPosition);
603 }
604
605 if (theMode != ComputeMode_All && theMode != ComputeMode_Line)
606 {
607 return;
608 }
609
610 Standard_Boolean isShortLine = !myDrawer->DimensionAspect()->IsText3d()
611 || theLabelPosition & LabelPosition_VCenter;
612
613 // compute graphical primitives and sensitives for extension line
614 gp_Pnt anExtStart = theExtensionStart;
615 gp_Pnt anExtEnd = !hasLabel || isShortLine
616 ? ElCLib::Value (theExtensionSize, anExtensionLine)
617 : ElCLib::Value (theExtensionSize + theLabelWidth, anExtensionLine);
618
619 // add graphical primitives
620 Handle(Graphic3d_ArrayOfSegments) anExtPrimitive = new Graphic3d_ArrayOfSegments (2);
621 anExtPrimitive->AddVertex (anExtStart);
622 anExtPrimitive->AddVertex (anExtEnd);
623
624 // add selection primitives
625 SelectionGeometry::Curve& aSensitiveCurve = mySelectionGeom.NewCurve();
626 aSensitiveCurve.Append (anExtStart);
627 aSensitiveCurve.Append (anExtEnd);
628
629 Handle(Graphic3d_Group) aGroup = thePresentation->NewGroup();
630 if (!myDrawer->DimensionAspect()->IsText3d() && theMode == ComputeMode_All)
631 {
632 aGroup->SetStencilTestOptions (Standard_True);
633 }
634 Handle(Graphic3d_AspectLine3d) aDimensionLineStyle = myDrawer->DimensionAspect()->LineAspect()->Aspect();
635 aGroup->SetPrimitivesAspect (aDimensionLineStyle);
636 aGroup->AddPrimitiveArray (anExtPrimitive);
637 if (!myDrawer->DimensionAspect()->IsText3d() && theMode == ComputeMode_All)
638 {
639 aGroup->SetStencilTestOptions (Standard_False);
640 }
641 }
642
643 //=======================================================================
644 //function : DrawLinearDimension
645 //purpose :
646 //=======================================================================
DrawLinearDimension(const Handle (Prs3d_Presentation)& thePresentation,const Standard_Integer theMode,const gp_Pnt & theFirstPoint,const gp_Pnt & theSecondPoint,const Standard_Boolean theIsOneSide)647 void PrsDim_Dimension::DrawLinearDimension (const Handle(Prs3d_Presentation)& thePresentation,
648 const Standard_Integer theMode,
649 const gp_Pnt& theFirstPoint,
650 const gp_Pnt& theSecondPoint,
651 const Standard_Boolean theIsOneSide)
652 {
653 // do not build any dimension for equal points
654 if (theFirstPoint.IsEqual (theSecondPoint, Precision::Confusion()))
655 {
656 throw Standard_ProgramError("Can not build presentation for equal points.");
657 }
658
659 Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
660
661 // For extensions we need to know arrow size, text size and extension size: get it from aspect
662 Standard_Real anArrowLength = aDimensionAspect->ArrowAspect()->Length();
663 Standard_Real anExtensionSize = aDimensionAspect->ExtensionSize();
664 // prepare label string and compute its geometrical width
665 Standard_Real aLabelWidth;
666 TCollection_ExtendedString aLabelString = GetValueString (aLabelWidth);
667
668 // add margins to cut dimension lines for 3d text
669 if (aDimensionAspect->IsText3d())
670 {
671 aLabelWidth += aDimensionAspect->TextAspect()->Height() * THE_3D_TEXT_MARGIN * 2.0;
672 }
673
674 // handle user-defined and automatic arrow placement
675 Standard_Boolean isArrowsExternal = Standard_False;
676 Standard_Integer aLabelPosition = LabelPosition_None;
677
678 Prs3d_DimensionTextHorizontalPosition aHorisontalTextPos = aDimensionAspect->TextHorizontalPosition();
679 if (IsTextPositionCustom())
680 {
681 if (!AdjustParametersForLinear (myFixedTextPosition, theFirstPoint, theSecondPoint,
682 anExtensionSize, aHorisontalTextPos, myFlyout, myPlane, myIsPlaneCustom))
683 {
684 throw Standard_ProgramError("Can not adjust plane to the custom label position.");
685 }
686 }
687
688 FitTextAlignmentForLinear (theFirstPoint, theSecondPoint, theIsOneSide, aHorisontalTextPos,
689 aLabelPosition, isArrowsExternal);
690
691 // compute dimension line points
692 gp_Pnt aLineBegPoint, aLineEndPoint;
693 ComputeFlyoutLinePoints (theFirstPoint, theSecondPoint, aLineBegPoint, aLineEndPoint);
694 gp_Lin aDimensionLine = gce_MakeLin (aLineBegPoint, aLineEndPoint);
695
696 // compute arrows positions and directions
697 gp_Dir aFirstArrowDir = aDimensionLine.Direction().Reversed();
698 gp_Dir aSecondArrowDir = aDimensionLine.Direction();
699 gp_Dir aFirstExtensionDir = aDimensionLine.Direction().Reversed();
700 gp_Dir aSecondExtensionDir = aDimensionLine.Direction();
701
702 gp_Pnt aFirstArrowBegin (0.0, 0.0, 0.0);
703 gp_Pnt aFirstArrowEnd (0.0, 0.0, 0.0);
704 gp_Pnt aSecondArrowBegin (0.0, 0.0, 0.0);
705 gp_Pnt aSecondArrowEnd (0.0, 0.0, 0.0);
706
707 if (isArrowsExternal)
708 {
709 aFirstArrowDir.Reverse();
710 aSecondArrowDir.Reverse();
711 }
712
713 aFirstArrowBegin = aLineBegPoint;
714 aSecondArrowBegin = aLineEndPoint;
715 aFirstArrowEnd = aLineBegPoint;
716 aSecondArrowEnd = aLineEndPoint;
717
718 if (aDimensionAspect->ArrowAspect()->IsZoomable())
719 {
720 aFirstArrowEnd.Translate (-gp_Vec (aFirstArrowDir).Scaled (anArrowLength));
721 aSecondArrowEnd.Translate (-gp_Vec (aSecondArrowDir).Scaled (anArrowLength));
722 }
723
724 gp_Pnt aCenterLineBegin = isArrowsExternal
725 ? aLineBegPoint : aFirstArrowEnd;
726
727 gp_Pnt aCenterLineEnd = isArrowsExternal || theIsOneSide
728 ? aLineEndPoint : aSecondArrowEnd;
729
730
731 switch (aLabelPosition & LabelPosition_HMask)
732 {
733 // ------------------------------------------------------------------------ //
734 // CENTER //
735 // -------------------------------------------------------------------------//
736 case LabelPosition_HCenter:
737 {
738 // add label on dimension or extension line to presentation
739 gp_Pnt aTextPos = IsTextPositionCustom() ? myFixedTextPosition
740 : (aCenterLineBegin.XYZ() + aCenterLineEnd.XYZ()) * 0.5;
741 gp_Dir aTextDir = aDimensionLine.Direction();
742
743 // add text primitives
744 if (theMode == ComputeMode_All || theMode == ComputeMode_Text)
745 {
746 thePresentation->NewGroup();
747 drawText (thePresentation,
748 aTextPos,
749 aTextDir,
750 aLabelString,
751 aLabelPosition);
752 }
753
754 // add dimension line primitives
755 if (theMode == ComputeMode_All || theMode == ComputeMode_Line)
756 {
757 Standard_Boolean isLineBreak = aDimensionAspect->TextVerticalPosition() == Prs3d_DTVP_Center
758 && aDimensionAspect->IsText3d();
759
760 Handle(Graphic3d_ArrayOfSegments) aPrimSegments = new Graphic3d_ArrayOfSegments (isLineBreak ? 4 : 2);
761
762 // compute continuous or sectioned main line segments
763 if (isLineBreak)
764 {
765 Standard_Real aPTextPosition = ElCLib::Parameter (aDimensionLine, aTextPos);
766 gp_Pnt aSection1Beg = aCenterLineBegin;
767 gp_Pnt aSection1End = ElCLib::Value (aPTextPosition - (aLabelWidth * 0.5), aDimensionLine);
768 gp_Pnt aSection2Beg = ElCLib::Value (aPTextPosition + (aLabelWidth * 0.5), aDimensionLine);
769 gp_Pnt aSection2End = aCenterLineEnd;
770
771 aPrimSegments->AddVertex (aSection1Beg);
772 aPrimSegments->AddVertex (aSection1End);
773 aPrimSegments->AddVertex (aSection2Beg);
774 aPrimSegments->AddVertex (aSection2End);
775
776 SelectionGeometry::Curve& aLeftSensitiveCurve = mySelectionGeom.NewCurve();
777 SelectionGeometry::Curve& aRightSensitiveCurve = mySelectionGeom.NewCurve();
778 aLeftSensitiveCurve.Append (aSection1Beg);
779 aLeftSensitiveCurve.Append (aSection1End);
780 aRightSensitiveCurve.Append (aSection2Beg);
781 aRightSensitiveCurve.Append (aSection2End);
782 }
783 else
784 {
785 aPrimSegments->AddVertex (aCenterLineBegin);
786 aPrimSegments->AddVertex (aCenterLineEnd);
787
788 SelectionGeometry::Curve& aSensitiveCurve = mySelectionGeom.NewCurve();
789 aSensitiveCurve.Append (aCenterLineBegin);
790 aSensitiveCurve.Append (aCenterLineEnd);
791 }
792
793 // set text label justification
794 Graphic3d_VerticalTextAlignment aTextJustificaton = Graphic3d_VTA_BOTTOM;
795 switch (aLabelPosition & LabelPosition_VMask)
796 {
797 case LabelPosition_Above :
798 case LabelPosition_VCenter : aTextJustificaton = Graphic3d_VTA_BOTTOM; break;
799 case LabelPosition_Below : aTextJustificaton = Graphic3d_VTA_TOP; break;
800 }
801 aDimensionAspect->TextAspect()->SetVerticalJustification (aTextJustificaton);
802
803 // main dimension line, short extension
804 {
805 Handle(Graphic3d_Group) aGroup = thePresentation->NewGroup();
806 if (!aDimensionAspect->IsText3d() && theMode == ComputeMode_All)
807 {
808 aGroup->SetStencilTestOptions (Standard_True);
809 }
810 aGroup->SetPrimitivesAspect (aDimensionAspect->LineAspect()->Aspect());
811 aGroup->AddPrimitiveArray (aPrimSegments);
812 if (!aDimensionAspect->IsText3d() && theMode == ComputeMode_All)
813 {
814 aGroup->SetStencilTestOptions (Standard_False);
815 }
816 }
817
818 // add arrows to presentation
819 {
820 Handle(Graphic3d_Group) aGroup = thePresentation->NewGroup();
821 DrawArrow (thePresentation, aFirstArrowBegin, aFirstArrowDir);
822 if (!theIsOneSide)
823 {
824 DrawArrow (thePresentation, aSecondArrowBegin, aSecondArrowDir);
825 }
826 }
827
828 if (!isArrowsExternal)
829 {
830 break;
831 }
832
833 // add arrow extension lines to presentation
834 {
835 DrawExtension (thePresentation, aDimensionAspect->ArrowTailSize(),
836 aFirstArrowEnd, aFirstExtensionDir,
837 THE_EMPTY_LABEL, 0.0, theMode, LabelPosition_None);
838 if (!theIsOneSide)
839 {
840 DrawExtension (thePresentation, aDimensionAspect->ArrowTailSize(),
841 aSecondArrowEnd, aSecondExtensionDir,
842 THE_EMPTY_LABEL, 0.0, theMode, LabelPosition_None);
843 }
844 }
845 }
846 break;
847 }
848 // ------------------------------------------------------------------------ //
849 // LEFT //
850 // -------------------------------------------------------------------------//
851
852 case LabelPosition_Left:
853 {
854 // add label on dimension or extension line to presentation
855 {
856 // Left extension with the text
857 DrawExtension (thePresentation, anExtensionSize,
858 isArrowsExternal
859 ? aFirstArrowEnd
860 : aFirstArrowBegin,
861 aFirstExtensionDir,
862 aLabelString,
863 aLabelWidth,
864 theMode,
865 aLabelPosition);
866 }
867
868 // add dimension line primitives
869 if (theMode == ComputeMode_All || theMode == ComputeMode_Line)
870 {
871 // add central dimension line
872 {
873 Handle(Graphic3d_Group) aGroup = thePresentation->NewGroup();
874
875 // add graphical primitives
876 Handle(Graphic3d_ArrayOfSegments) aPrimSegments = new Graphic3d_ArrayOfSegments (2);
877 aPrimSegments->AddVertex (aCenterLineBegin);
878 aPrimSegments->AddVertex (aCenterLineEnd);
879
880 aGroup->SetPrimitivesAspect (aDimensionAspect->LineAspect()->Aspect());
881 aGroup->AddPrimitiveArray (aPrimSegments);
882
883 // add selection primitives
884 SelectionGeometry::Curve& aSensitiveCurve = mySelectionGeom.NewCurve();
885 aSensitiveCurve.Append (aCenterLineBegin);
886 aSensitiveCurve.Append (aCenterLineEnd);
887 }
888
889 // add arrows to presentation
890 {
891 Handle(Graphic3d_Group) aGroup = thePresentation->NewGroup();
892 DrawArrow (thePresentation, aFirstArrowBegin, aFirstArrowDir);
893 if (!theIsOneSide)
894 {
895 DrawArrow (thePresentation, aSecondArrowBegin, aSecondArrowDir);
896 }
897 }
898
899 if (!isArrowsExternal || theIsOneSide)
900 {
901 break;
902 }
903
904 // add extension lines for external arrows
905 {
906 DrawExtension (thePresentation, aDimensionAspect->ArrowTailSize(),
907 aSecondArrowEnd, aSecondExtensionDir,
908 THE_EMPTY_LABEL, 0.0, theMode, LabelPosition_None);
909 }
910 }
911
912 break;
913 }
914 // ------------------------------------------------------------------------ //
915 // RIGHT //
916 // -------------------------------------------------------------------------//
917
918 case LabelPosition_Right:
919 {
920 // add label on dimension or extension line to presentation
921
922 // Right extension with text
923 DrawExtension (thePresentation, anExtensionSize,
924 isArrowsExternal
925 ? aSecondArrowEnd
926 : aSecondArrowBegin,
927 aSecondExtensionDir,
928 aLabelString, aLabelWidth,
929 theMode,
930 aLabelPosition);
931
932 if (theMode == ComputeMode_All || theMode == ComputeMode_Line)
933 {
934 // add central dimension line
935 {
936 Handle(Graphic3d_Group) aGroup = thePresentation->NewGroup();
937
938 // add graphical primitives
939 Handle(Graphic3d_ArrayOfSegments) aPrimSegments = new Graphic3d_ArrayOfSegments (2);
940 aPrimSegments->AddVertex (aCenterLineBegin);
941 aPrimSegments->AddVertex (aCenterLineEnd);
942 aGroup->SetGroupPrimitivesAspect (aDimensionAspect->LineAspect()->Aspect());
943 aGroup->AddPrimitiveArray (aPrimSegments);
944
945 // add selection primitives
946 SelectionGeometry::Curve& aSensitiveCurve = mySelectionGeom.NewCurve();
947 aSensitiveCurve.Append (aCenterLineBegin);
948 aSensitiveCurve.Append (aCenterLineEnd);
949 }
950
951 // add arrows to presentation
952 {
953 thePresentation->NewGroup();
954 DrawArrow (thePresentation, aSecondArrowBegin, aSecondArrowDir);
955 if (!theIsOneSide)
956 {
957 DrawArrow (thePresentation, aFirstArrowBegin, aFirstArrowDir);
958 }
959 }
960
961 if (!isArrowsExternal || theIsOneSide)
962 {
963 break;
964 }
965
966 // add extension lines for external arrows
967 {
968 DrawExtension (thePresentation, aDimensionAspect->ArrowTailSize(),
969 aFirstArrowEnd, aFirstExtensionDir,
970 THE_EMPTY_LABEL, 0.0, theMode, LabelPosition_None);
971 }
972 }
973
974 break;
975 }
976 }
977
978 // add flyout lines to presentation
979 if (theMode == ComputeMode_All)
980 {
981 Handle(Graphic3d_Group) aGroup = thePresentation->NewGroup();
982
983 Handle(Graphic3d_ArrayOfSegments) aPrimSegments = new Graphic3d_ArrayOfSegments(4);
984 aPrimSegments->AddVertex (theFirstPoint);
985 aPrimSegments->AddVertex (aLineBegPoint);
986
987 aPrimSegments->AddVertex (theSecondPoint);
988 aPrimSegments->AddVertex (aLineEndPoint);
989
990 aGroup->SetGroupPrimitivesAspect (aDimensionAspect->LineAspect()->Aspect());
991 aGroup->AddPrimitiveArray (aPrimSegments);
992 }
993
994 mySelectionGeom.IsComputed = Standard_True;
995 }
996
997 //=======================================================================
998 //function : ComputeFlyoutLinePoints
999 //purpose :
1000 //=======================================================================
ComputeFlyoutLinePoints(const gp_Pnt & theFirstPoint,const gp_Pnt & theSecondPoint,gp_Pnt & theLineBegPoint,gp_Pnt & theLineEndPoint)1001 void PrsDim_Dimension::ComputeFlyoutLinePoints (const gp_Pnt& theFirstPoint, const gp_Pnt& theSecondPoint,
1002 gp_Pnt& theLineBegPoint, gp_Pnt& theLineEndPoint)
1003 {
1004 // compute dimension line points
1005 gp_Ax1 aPlaneNormal = GetPlane().Axis();
1006 // compute flyout direction vector
1007 gp_Dir aTargetPointsVector = gce_MakeDir (theFirstPoint, theSecondPoint);
1008 gp_Dir aFlyoutVector = aPlaneNormal.Direction() ^ aTargetPointsVector;
1009 // create lines for layouts
1010 gp_Lin aLine1 (theFirstPoint, aFlyoutVector);
1011 gp_Lin aLine2 (theSecondPoint, aFlyoutVector);
1012
1013 // Get flyout end points
1014 theLineBegPoint = ElCLib::Value (ElCLib::Parameter (aLine1, theFirstPoint) + GetFlyout(), aLine1);
1015 theLineEndPoint = ElCLib::Value (ElCLib::Parameter (aLine2, theSecondPoint) + GetFlyout(), aLine2);
1016 }
1017
1018 //=======================================================================
1019 //function : ComputeLinearFlyouts
1020 //purpose :
1021 //=======================================================================
ComputeLinearFlyouts(const Handle (SelectMgr_Selection)& theSelection,const Handle (SelectMgr_EntityOwner)& theOwner,const gp_Pnt & theFirstPoint,const gp_Pnt & theSecondPoint)1022 void PrsDim_Dimension::ComputeLinearFlyouts (const Handle(SelectMgr_Selection)& theSelection,
1023 const Handle(SelectMgr_EntityOwner)& theOwner,
1024 const gp_Pnt& theFirstPoint,
1025 const gp_Pnt& theSecondPoint)
1026 {
1027 // count flyout direction
1028 gp_Ax1 aPlaneNormal = GetPlane().Axis();
1029 gp_Dir aTargetPointsVector = gce_MakeDir (theFirstPoint, theSecondPoint);
1030
1031 // count a flyout direction vector.
1032 gp_Dir aFlyoutVector = aPlaneNormal.Direction() ^ aTargetPointsVector;
1033
1034 // create lines for layouts
1035 gp_Lin aLine1 (theFirstPoint, aFlyoutVector);
1036 gp_Lin aLine2 (theSecondPoint, aFlyoutVector);
1037
1038 // get flyout end points
1039 gp_Pnt aFlyoutEnd1 = ElCLib::Value (ElCLib::Parameter (aLine1, theFirstPoint) + GetFlyout(), aLine1);
1040 gp_Pnt aFlyoutEnd2 = ElCLib::Value (ElCLib::Parameter (aLine2, theSecondPoint) + GetFlyout(), aLine2);
1041
1042 // fill sensitive entity for flyouts
1043 Handle(Select3D_SensitiveGroup) aSensitiveEntity = new Select3D_SensitiveGroup (theOwner);
1044 aSensitiveEntity->Add (new Select3D_SensitiveSegment (theOwner, theFirstPoint, aFlyoutEnd1));
1045 aSensitiveEntity->Add (new Select3D_SensitiveSegment (theOwner, theSecondPoint, aFlyoutEnd2));
1046 theSelection->Add (aSensitiveEntity);
1047 }
1048
1049 //=======================================================================
1050 //function : CircleFromPlanarFace
1051 //purpose : if possible computes circle from planar face
1052 //=======================================================================
CircleFromPlanarFace(const TopoDS_Face & theFace,Handle (Geom_Curve)& theCurve,gp_Pnt & theFirstPoint,gp_Pnt & theLastPoint)1053 Standard_Boolean PrsDim_Dimension::CircleFromPlanarFace (const TopoDS_Face& theFace,
1054 Handle(Geom_Curve)& theCurve,
1055 gp_Pnt& theFirstPoint,
1056 gp_Pnt& theLastPoint)
1057 {
1058 TopExp_Explorer anIt (theFace, TopAbs_EDGE);
1059 for ( ; anIt.More(); anIt.Next())
1060 {
1061 TopoDS_Edge aCurEdge = TopoDS::Edge (anIt.Current());
1062 if (PrsDim::ComputeGeometry (aCurEdge, theCurve, theFirstPoint, theLastPoint))
1063 {
1064 if (theCurve->IsInstance (STANDARD_TYPE(Geom_Circle)))
1065 {
1066 return Standard_True;
1067 }
1068 }
1069 }
1070 return Standard_False;
1071 }
1072
1073 //=======================================================================
1074 //function : CircleFromEdge
1075 //purpose : if possible computes circle from edge
1076 //=======================================================================
CircleFromEdge(const TopoDS_Edge & theEdge,gp_Circ & theCircle,gp_Pnt & theFirstPoint,gp_Pnt & theLastPoint)1077 Standard_Boolean PrsDim_Dimension::CircleFromEdge (const TopoDS_Edge& theEdge,
1078 gp_Circ& theCircle,
1079 gp_Pnt& theFirstPoint,
1080 gp_Pnt& theLastPoint)
1081 {
1082 BRepAdaptor_Curve anAdaptedCurve (theEdge);
1083 switch (anAdaptedCurve.GetType())
1084 {
1085 case GeomAbs_Circle:
1086 {
1087 theCircle = anAdaptedCurve.Circle();
1088 break;
1089 }
1090 case GeomAbs_Ellipse:
1091 {
1092 gp_Elips anEll = anAdaptedCurve.Ellipse();
1093 if ((anEll.MinorRadius() - anEll.MajorRadius()) >= Precision::Confusion())
1094 {
1095 return Standard_False;
1096 }
1097 theCircle = gp_Circ(anEll.Position(),anEll.MinorRadius());
1098 break;
1099 }
1100 case GeomAbs_Line:
1101 case GeomAbs_Hyperbola:
1102 case GeomAbs_Parabola:
1103 case GeomAbs_BezierCurve:
1104 case GeomAbs_BSplineCurve:
1105 case GeomAbs_OtherCurve:
1106 default:
1107 return Standard_False;
1108 }
1109
1110 theFirstPoint = anAdaptedCurve.Value (anAdaptedCurve.FirstParameter());
1111 theLastPoint = anAdaptedCurve.Value (anAdaptedCurve.LastParameter());
1112 return Standard_True;
1113 }
1114
1115 //=======================================================================
1116 //function : InitCircularDimension
1117 //purpose :
1118 //=======================================================================
InitCircularDimension(const TopoDS_Shape & theShape,gp_Circ & theCircle,gp_Pnt & theMiddleArcPoint,Standard_Boolean & theIsClosed)1119 Standard_Boolean PrsDim_Dimension::InitCircularDimension (const TopoDS_Shape& theShape,
1120 gp_Circ& theCircle,
1121 gp_Pnt& theMiddleArcPoint,
1122 Standard_Boolean& theIsClosed)
1123 {
1124 gp_Pln aPln;
1125 Handle(Geom_Surface) aBasisSurf;
1126 PrsDim_KindOfSurface aSurfType = PrsDim_KOS_OtherSurface;
1127 gp_Pnt aFirstPoint, aLastPoint;
1128 Standard_Real anOffset = 0.0;
1129 Standard_Real aFirstParam = 0.0;
1130 Standard_Real aLastParam = 0.0;
1131
1132 // Discover circular geometry
1133 switch (theShape.ShapeType())
1134 {
1135 case TopAbs_FACE:
1136 {
1137 PrsDim::GetPlaneFromFace (TopoDS::Face (theShape), aPln, aBasisSurf, aSurfType, anOffset);
1138
1139 if (aSurfType == PrsDim_KOS_Plane)
1140 {
1141 Handle(Geom_Curve) aCurve;
1142 if (!CircleFromPlanarFace (TopoDS::Face (theShape), aCurve, aFirstPoint, aLastPoint))
1143 {
1144 return Standard_False;
1145 }
1146
1147 theCircle = Handle(Geom_Circle)::DownCast (aCurve)->Circ();
1148 }
1149 else
1150 {
1151 gp_Pnt aCurPos;
1152 BRepAdaptor_Surface aSurf1 (TopoDS::Face (theShape));
1153 Standard_Real aFirstU = aSurf1.FirstUParameter();
1154 Standard_Real aLastU = aSurf1.LastUParameter();
1155 Standard_Real aFirstV = aSurf1.FirstVParameter();
1156 Standard_Real aLastV = aSurf1.LastVParameter();
1157 Standard_Real aMidU = (aFirstU + aLastU) * 0.5;
1158 Standard_Real aMidV = (aFirstV + aLastV) * 0.5;
1159 aSurf1.D0 (aMidU, aMidV, aCurPos);
1160 Handle (Adaptor3d_Curve) aBasisCurve;
1161 Standard_Boolean isExpectedType = Standard_False;
1162 if (aSurfType == PrsDim_KOS_Cylinder)
1163 {
1164 isExpectedType = Standard_True;
1165 }
1166 else
1167 {
1168 if (aSurfType == PrsDim_KOS_Revolution)
1169 {
1170 aBasisCurve = aSurf1.BasisCurve();
1171 if (aBasisCurve->GetType() == GeomAbs_Line)
1172 {
1173 isExpectedType = Standard_True;
1174 }
1175 }
1176 else if (aSurfType == PrsDim_KOS_Extrusion)
1177 {
1178 aBasisCurve = aSurf1.BasisCurve();
1179 if (aBasisCurve->GetType() == GeomAbs_Circle)
1180 {
1181 isExpectedType = Standard_True;
1182 }
1183 }
1184 }
1185
1186 if (!isExpectedType)
1187 {
1188 return Standard_False;
1189 }
1190
1191 Handle(Geom_Curve) aCurve = aBasisSurf->VIso(aMidV);
1192 if (aCurve->DynamicType() == STANDARD_TYPE (Geom_Circle))
1193 {
1194 theCircle = Handle(Geom_Circle)::DownCast (aCurve)->Circ();
1195 }
1196 else if (aCurve->DynamicType() == STANDARD_TYPE (Geom_TrimmedCurve))
1197 {
1198 Handle(Geom_TrimmedCurve) aTrimmedCurve = Handle(Geom_TrimmedCurve)::DownCast (aCurve);
1199 aFirstU = aTrimmedCurve->FirstParameter();
1200 aLastU = aTrimmedCurve->LastParameter();
1201 if (aTrimmedCurve->BasisCurve()->DynamicType() == STANDARD_TYPE (Geom_Circle))
1202 {
1203 theCircle = Handle(Geom_Circle)::DownCast(aTrimmedCurve->BasisCurve())->Circ();
1204 }
1205 }
1206 else
1207 {
1208 // Compute a circle from 3 points on "aCurve"
1209 gp_Pnt aP1, aP2;
1210 aSurf1.D0 (aFirstU, aMidV, aP1);
1211 aSurf1.D0 (aLastU, aMidV, aP2);
1212 GC_MakeCircle aMkCirc (aP1, aCurPos, aP2);
1213 theCircle = aMkCirc.Value()->Circ();
1214 }
1215
1216 aFirstPoint = ElCLib::Value (aFirstU, theCircle);
1217 aLastPoint = ElCLib::Value (aLastU, theCircle);
1218 }
1219 break;
1220 }
1221 case TopAbs_WIRE:
1222 {
1223 TopoDS_Edge anEdge;
1224 TopExp_Explorer anIt (theShape, TopAbs_EDGE);
1225 if (anIt.More())
1226 {
1227 anEdge = TopoDS::Edge (anIt.Current());
1228 }
1229 if (!PrsDim_Dimension::CircleFromEdge (anEdge, theCircle, aFirstPoint, aLastPoint))
1230 {
1231 return Standard_False;
1232 }
1233 break;
1234 }
1235 case TopAbs_EDGE:
1236 {
1237 TopoDS_Edge anEdge = TopoDS::Edge (theShape);
1238 if (!PrsDim_Dimension::CircleFromEdge (anEdge, theCircle, aFirstPoint, aLastPoint))
1239 {
1240 return Standard_False;
1241 }
1242 break;
1243 }
1244 case TopAbs_COMPOUND:
1245 case TopAbs_COMPSOLID:
1246 case TopAbs_SOLID:
1247 case TopAbs_SHELL:
1248 case TopAbs_VERTEX:
1249 case TopAbs_SHAPE:
1250 default:
1251 return Standard_False;
1252 }
1253
1254 theIsClosed = aFirstPoint.IsEqual (aLastPoint, Precision::Confusion());
1255
1256 gp_Pnt aCenter = theCircle.Location();
1257
1258 if (theIsClosed) // Circle
1259 {
1260 gp_Dir anXDir = theCircle.XAxis().Direction();
1261 theMiddleArcPoint = aCenter.Translated (gp_Vec (anXDir) * theCircle.Radius());
1262 }
1263 else // Arc
1264 {
1265 aFirstParam = ElCLib::Parameter (theCircle, aFirstPoint);
1266 aLastParam = ElCLib::Parameter (theCircle, aLastPoint);
1267 if (aFirstParam > aLastParam)
1268 {
1269 aFirstParam -= 2.0 * M_PI;
1270 }
1271
1272 Standard_Real aParCurPos = (aFirstParam + aLastParam) * 0.5;
1273 gp_Vec aVec = gp_Vec (aCenter, ElCLib::Value (aParCurPos, theCircle)).Normalized () * theCircle.Radius ();
1274 theMiddleArcPoint = aCenter.Translated (aVec);
1275 }
1276
1277 return Standard_True;
1278 }
1279
1280 //=======================================================================
1281 //function : ComputeSelection
1282 //purpose :
1283 //=======================================================================
ComputeSelection(const Handle (SelectMgr_Selection)& theSelection,const Standard_Integer theMode)1284 void PrsDim_Dimension::ComputeSelection (const Handle(SelectMgr_Selection)& theSelection,
1285 const Standard_Integer theMode)
1286 {
1287 if (!mySelectionGeom.IsComputed)
1288 {
1289 return;
1290 }
1291
1292 PrsDim_DimensionSelectionMode aSelectionMode = (PrsDim_DimensionSelectionMode)theMode;
1293
1294 // init appropriate entity owner
1295 Handle(SelectMgr_EntityOwner) aSensitiveOwner;
1296
1297 switch (aSelectionMode)
1298 {
1299 // neutral selection owner
1300 case PrsDim_DimensionSelectionMode_All:
1301 aSensitiveOwner = new SelectMgr_EntityOwner (this, THE_NEUTRAL_SEL_PRIORITY);
1302 break;
1303
1304 // local selection owners
1305 case PrsDim_DimensionSelectionMode_Line:
1306 case PrsDim_DimensionSelectionMode_Text:
1307 aSensitiveOwner = new PrsDim_DimensionOwner (this, aSelectionMode, THE_LOCAL_SEL_PRIORITY);
1308 break;
1309 }
1310
1311 if (aSelectionMode == PrsDim_DimensionSelectionMode_All || aSelectionMode == PrsDim_DimensionSelectionMode_Line)
1312 {
1313 // sensitives for dimension line segments
1314 Handle(Select3D_SensitiveGroup) aGroupOfSensitives = new Select3D_SensitiveGroup (aSensitiveOwner);
1315
1316 SelectionGeometry::SeqOfCurves::Iterator aCurveIt (mySelectionGeom.DimensionLine);
1317 for (; aCurveIt.More(); aCurveIt.Next())
1318 {
1319 const SelectionGeometry::HCurve& aCurveData = aCurveIt.Value();
1320
1321 TColgp_Array1OfPnt aSensitivePnts (1, aCurveData->Length());
1322 for (Standard_Integer aPntIt = 1; aPntIt <= aCurveData->Length(); ++aPntIt)
1323 {
1324 aSensitivePnts.ChangeValue (aPntIt) = aCurveData->Value (aPntIt);
1325 }
1326
1327 aGroupOfSensitives->Add (new Select3D_SensitiveCurve (aSensitiveOwner, aSensitivePnts));
1328 }
1329
1330 Standard_Real anArrowLength = myDrawer->DimensionAspect()->ArrowAspect()->Length();
1331 Standard_Real anArrowAngle = myDrawer->DimensionAspect()->ArrowAspect()->Angle();
1332
1333 // sensitives for arrows
1334 SelectionGeometry::SeqOfArrows::Iterator anArrowIt (mySelectionGeom.Arrows);
1335 for (; anArrowIt.More(); anArrowIt.Next())
1336 {
1337 const SelectionGeometry::HArrow& anArrow = anArrowIt.Value();
1338
1339 gp_Pnt aSidePnt1 (gp::Origin());
1340 gp_Pnt aSidePnt2 (gp::Origin());
1341 const gp_Dir& aPlane = GetPlane().Axis().Direction();
1342 const gp_Pnt& aPeak = anArrow->Position;
1343 const gp_Dir& aDir = anArrow->Direction;
1344
1345 // compute points for arrow in plane
1346 PointsForArrow (aPeak, aDir, aPlane, anArrowLength, anArrowAngle, aSidePnt1, aSidePnt2);
1347
1348 aGroupOfSensitives->Add (new Select3D_SensitiveTriangle (aSensitiveOwner, aPeak, aSidePnt1, aSidePnt2));
1349
1350 if (!myDrawer->DimensionAspect()->IsArrows3d())
1351 {
1352 continue;
1353 }
1354
1355 // compute points for orthogonal sensitive plane
1356 gp_Dir anOrthoPlane = anArrow->Direction.Crossed (aPlane);
1357
1358 PointsForArrow (aPeak, aDir, anOrthoPlane, anArrowLength, anArrowAngle, aSidePnt1, aSidePnt2);
1359
1360 aGroupOfSensitives->Add (new Select3D_SensitiveTriangle (aSensitiveOwner, aPeak, aSidePnt1, aSidePnt2));
1361 }
1362
1363 theSelection->Add (aGroupOfSensitives);
1364 }
1365
1366 // sensitives for text element
1367 if (aSelectionMode == PrsDim_DimensionSelectionMode_All || aSelectionMode == PrsDim_DimensionSelectionMode_Text)
1368 {
1369 Handle(Select3D_SensitiveEntity) aTextSensitive;
1370
1371 gp_Ax2 aTextAxes (mySelectionGeom.TextPos,
1372 GetPlane().Axis().Direction(),
1373 mySelectionGeom.TextDir);
1374
1375 if (myDrawer->DimensionAspect()->IsText3d())
1376 {
1377 // sensitive planar rectangle for text
1378 Standard_Real aDx = mySelectionGeom.TextWidth * 0.5;
1379 Standard_Real aDy = mySelectionGeom.TextHeight * 0.5;
1380
1381 gp_Trsf aLabelPlane;
1382 aLabelPlane.SetTransformation (aTextAxes, gp::XOY());
1383
1384 TColgp_Array1OfPnt aRectanglePoints(1, 4);
1385 aRectanglePoints.ChangeValue(1) = gp_Pnt (-aDx, -aDy, 0.0).Transformed (aLabelPlane);
1386 aRectanglePoints.ChangeValue(2) = gp_Pnt (-aDx, aDy, 0.0).Transformed (aLabelPlane);
1387 aRectanglePoints.ChangeValue(3) = gp_Pnt ( aDx, aDy, 0.0).Transformed (aLabelPlane);
1388 aRectanglePoints.ChangeValue(4) = gp_Pnt ( aDx, -aDy, 0.0).Transformed (aLabelPlane);
1389
1390 Poly_Array1OfTriangle aTriangles(1, 2);
1391 aTriangles.ChangeValue(1) = Poly_Triangle(1, 2, 3);
1392 aTriangles.ChangeValue(2) = Poly_Triangle(1, 3, 4);
1393
1394 Handle(Poly_Triangulation) aRectanglePoly =
1395 new Poly_Triangulation(aRectanglePoints, aTriangles);
1396
1397 aTextSensitive =
1398 new Select3D_SensitiveTriangulation (aSensitiveOwner, aRectanglePoly, TopLoc_Location(), Standard_True);
1399 }
1400 else
1401 {
1402 gp_Circ aTextGeom (aTextAxes, mySelToleranceForText2d != 0.0
1403 ? mySelToleranceForText2d : 1.0);
1404 aTextSensitive = new Select3D_SensitiveCircle (aSensitiveOwner, aTextGeom, Standard_True);
1405 }
1406
1407 theSelection->Add (aTextSensitive);
1408 }
1409
1410 // callback for flyout sensitive calculation
1411 if (aSelectionMode == PrsDim_DimensionSelectionMode_All)
1412 {
1413 ComputeFlyoutSelection (theSelection, aSensitiveOwner);
1414 }
1415 }
1416
1417 //=======================================================================
1418 //function : PointsForArrow
1419 //purpose :
1420 //=======================================================================
PointsForArrow(const gp_Pnt & thePeakPnt,const gp_Dir & theDirection,const gp_Dir & thePlane,const Standard_Real theArrowLength,const Standard_Real theArrowAngle,gp_Pnt & theSidePnt1,gp_Pnt & theSidePnt2)1421 void PrsDim_Dimension::PointsForArrow (const gp_Pnt& thePeakPnt,
1422 const gp_Dir& theDirection,
1423 const gp_Dir& thePlane,
1424 const Standard_Real theArrowLength,
1425 const Standard_Real theArrowAngle,
1426 gp_Pnt& theSidePnt1,
1427 gp_Pnt& theSidePnt2)
1428 {
1429 gp_Lin anArrowLin (thePeakPnt, theDirection.Reversed());
1430 gp_Pnt anArrowEnd = ElCLib::Value (theArrowLength, anArrowLin);
1431 gp_Lin anEdgeLin (anArrowEnd, theDirection.Crossed (thePlane));
1432
1433 Standard_Real anEdgeLength = Tan (theArrowAngle) * theArrowLength;
1434
1435 theSidePnt1 = ElCLib::Value ( anEdgeLength, anEdgeLin);
1436 theSidePnt2 = ElCLib::Value (-anEdgeLength, anEdgeLin);
1437 }
1438
1439 //=======================================================================
1440 //function : GetTextPositionForLinear
1441 //purpose :
1442 //=======================================================================
GetTextPositionForLinear(const gp_Pnt & theFirstPoint,const gp_Pnt & theSecondPoint,const Standard_Boolean theIsOneSide) const1443 gp_Pnt PrsDim_Dimension::GetTextPositionForLinear (const gp_Pnt& theFirstPoint,
1444 const gp_Pnt& theSecondPoint,
1445 const Standard_Boolean theIsOneSide) const
1446 {
1447 if (!IsValid())
1448 {
1449 return gp::Origin();
1450 }
1451
1452 gp_Pnt aTextPosition (gp::Origin());
1453
1454 Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
1455
1456 // Get label alignment and arrow orientation.
1457 Standard_Integer aLabelPosition = 0;
1458 Standard_Boolean isArrowsExternal = Standard_False;
1459 FitTextAlignmentForLinear (theFirstPoint, theSecondPoint, theIsOneSide,
1460 aDimensionAspect->TextHorizontalPosition(),
1461 aLabelPosition, isArrowsExternal);
1462
1463 // Compute dimension line points.
1464 gp_Dir aPlaneNormal = GetPlane().Axis().Direction();
1465 gp_Vec aTargetPointsVec (theFirstPoint, theSecondPoint);
1466
1467 // Compute flyout direction vector
1468 gp_Dir aFlyoutVector = aPlaneNormal ^ gp_Dir (aTargetPointsVec);
1469
1470 // create lines for layouts
1471 gp_Lin aLine1 (theFirstPoint, aFlyoutVector);
1472 gp_Lin aLine2 (theSecondPoint, aFlyoutVector);
1473 // Get flyout end points
1474 gp_Pnt aLineBegPoint = ElCLib::Value (ElCLib::Parameter (aLine1, theFirstPoint) + GetFlyout(), aLine1);
1475 gp_Pnt aLineEndPoint = ElCLib::Value (ElCLib::Parameter (aLine2, theSecondPoint) + GetFlyout(), aLine2);
1476
1477 // Get text position.
1478 switch (aLabelPosition & LabelPosition_HMask)
1479 {
1480 case LabelPosition_Left:
1481 {
1482 gp_Dir aTargetPointsDir = gce_MakeDir (theFirstPoint, theSecondPoint);
1483 Standard_Real anExtensionSize = aDimensionAspect->ExtensionSize();
1484
1485 Standard_Real anOffset = isArrowsExternal
1486 ? anExtensionSize + aDimensionAspect->ArrowAspect()->Length()
1487 : anExtensionSize;
1488 gp_Vec anExtensionVec = gp_Vec (aTargetPointsDir) * -anOffset;
1489 aTextPosition = aLineEndPoint.Translated (anExtensionVec);
1490 }
1491 break;
1492 case LabelPosition_Right:
1493 {
1494 gp_Dir aTargetPointsDir = gce_MakeDir (theFirstPoint, theSecondPoint);
1495 Standard_Real anExtensionSize = aDimensionAspect->ExtensionSize();
1496
1497 Standard_Real anOffset = isArrowsExternal
1498 ? anExtensionSize + aDimensionAspect->ArrowAspect()->Length()
1499 : anExtensionSize;
1500 gp_Vec anExtensionVec = gp_Vec (aTargetPointsDir) * anOffset;
1501 aTextPosition = aLineBegPoint.Translated (anExtensionVec);
1502 }
1503 break;
1504 case LabelPosition_HCenter:
1505 {
1506 aTextPosition = (aLineBegPoint.XYZ() + aLineEndPoint.XYZ()) * 0.5;
1507 }
1508 break;
1509 }
1510
1511 return aTextPosition;
1512 }
1513
1514 //=======================================================================
1515 //function : AdjustParametersForLinear
1516 //purpose :
1517 //=======================================================================
AdjustParametersForLinear(const gp_Pnt & theTextPos,const gp_Pnt & theFirstPoint,const gp_Pnt & theSecondPoint,Standard_Real & theExtensionSize,Prs3d_DimensionTextHorizontalPosition & theAlignment,Standard_Real & theFlyout,gp_Pln & thePlane,Standard_Boolean & theIsPlaneOld) const1518 Standard_Boolean PrsDim_Dimension::AdjustParametersForLinear (const gp_Pnt& theTextPos,
1519 const gp_Pnt& theFirstPoint,
1520 const gp_Pnt& theSecondPoint,
1521 Standard_Real& theExtensionSize,
1522 Prs3d_DimensionTextHorizontalPosition& theAlignment,
1523 Standard_Real& theFlyout,
1524 gp_Pln& thePlane,
1525 Standard_Boolean& theIsPlaneOld) const
1526 {
1527 Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
1528 Standard_Real anArrowLength = aDimensionAspect->ArrowAspect()->Length();
1529
1530 gp_Dir aTargetPointsDir = gce_MakeDir (theFirstPoint, theSecondPoint);
1531 gp_Vec aTargetPointsVec (theFirstPoint, theSecondPoint);
1532
1533 // Don't set new plane if the text position lies on the attachment points line.
1534 gp_Lin aTargetPointsLin (theFirstPoint, aTargetPointsDir);
1535 if (!aTargetPointsLin.Contains (theTextPos, Precision::Confusion()))
1536 {
1537 //Set new automatic plane.
1538 thePlane = gce_MakePln (theTextPos, theFirstPoint, theSecondPoint);
1539 theIsPlaneOld = Standard_False;
1540 }
1541
1542 // Compute flyout direction vector.
1543 gp_Dir aPlaneNormal = GetPlane().Axis().Direction();
1544 gp_Dir aPositiveFlyout = aPlaneNormal ^ aTargetPointsDir;
1545
1546 // Additional check of collinearity of the plane normal and attachment points vector.
1547 if (aPlaneNormal.IsParallel (aTargetPointsDir, Precision::Angular()))
1548 {
1549 return Standard_False;
1550 }
1551
1552 // Set flyout.
1553 gp_Vec aFirstToTextVec (theFirstPoint, theTextPos);
1554
1555 Standard_Real aCos = aFirstToTextVec.Normalized() * gp_Vec (aTargetPointsDir);
1556
1557 gp_Pnt aTextPosProj = theFirstPoint.Translated
1558 (gp_Vec (aTargetPointsDir) * aFirstToTextVec.Magnitude() * aCos);
1559
1560 // Compute flyout value and direction.
1561 gp_Vec aFlyoutVector = gp_Vec (aTextPosProj, theTextPos);
1562
1563 theFlyout = 0.0;
1564 if (aFlyoutVector.Magnitude() > Precision::Confusion())
1565 {
1566 theFlyout = gp_Dir (aFlyoutVector).IsOpposite (aPositiveFlyout, Precision::Angular())
1567 ? -aFlyoutVector.Magnitude()
1568 : aFlyoutVector.Magnitude();
1569 }
1570
1571 // Compute attach points (through which main dimension line passes).
1572 gp_Pnt aFirstAttach = theFirstPoint.Translated (aFlyoutVector);
1573 gp_Pnt aSecondAttach = theSecondPoint.Translated (aFlyoutVector);
1574
1575 // Set horizontal text alignment.
1576 if (aCos < 0.0)
1577 {
1578 theAlignment = Prs3d_DTHP_Left;
1579
1580 Standard_Real aNewExtSize = theTextPos.Distance (aFirstAttach) - anArrowLength;
1581 theExtensionSize = aNewExtSize < 0.0 ? 0.0 : aNewExtSize;
1582 }
1583 else if (aTextPosProj.Distance (theFirstPoint) > theFirstPoint.Distance (theSecondPoint))
1584 {
1585 theAlignment = Prs3d_DTHP_Right;
1586
1587 Standard_Real aNewExtSize = theTextPos.Distance (aSecondAttach) - anArrowLength;
1588 theExtensionSize = aNewExtSize < 0.0 ? 0.0 : aNewExtSize;
1589 }
1590 else
1591 {
1592 theAlignment = Prs3d_DTHP_Center;
1593 }
1594 return Standard_True;
1595 }
1596
1597 //=======================================================================
1598 //function : FitTextAlignmentForLinear
1599 //purpose :
1600 //=======================================================================
FitTextAlignmentForLinear(const gp_Pnt & theFirstPoint,const gp_Pnt & theSecondPoint,const Standard_Boolean theIsOneSide,const Prs3d_DimensionTextHorizontalPosition & theHorizontalTextPos,Standard_Integer & theLabelPosition,Standard_Boolean & theIsArrowsExternal) const1601 void PrsDim_Dimension::FitTextAlignmentForLinear (const gp_Pnt& theFirstPoint,
1602 const gp_Pnt& theSecondPoint,
1603 const Standard_Boolean theIsOneSide,
1604 const Prs3d_DimensionTextHorizontalPosition& theHorizontalTextPos,
1605 Standard_Integer& theLabelPosition,
1606 Standard_Boolean& theIsArrowsExternal) const
1607 {
1608 theLabelPosition = LabelPosition_None;
1609 theIsArrowsExternal = Standard_False;
1610
1611 // Compute dimension line points
1612 gp_Ax1 aPlaneNormal = GetPlane().Axis();
1613 gp_Dir aTargetPointsVector = gce_MakeDir (theFirstPoint, theSecondPoint);
1614
1615 // compute flyout direction vector
1616 gp_Dir aFlyoutVector = aPlaneNormal.Direction() ^ aTargetPointsVector;
1617
1618 // create lines for layouts
1619 gp_Lin aLine1 (theFirstPoint, aFlyoutVector);
1620 gp_Lin aLine2 (theSecondPoint, aFlyoutVector);
1621
1622 // Get flyout end points
1623 gp_Pnt aLineBegPoint = ElCLib::Value (ElCLib::Parameter (aLine1, theFirstPoint) + GetFlyout(), aLine1);
1624 gp_Pnt aLineEndPoint = ElCLib::Value (ElCLib::Parameter (aLine2, theSecondPoint) + GetFlyout(), aLine2);
1625
1626 Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
1627
1628 // For extensions we need to know arrow size, text size and extension size: get it from aspect
1629 Standard_Real anArrowLength = aDimensionAspect->ArrowAspect()->Length();
1630
1631 // prepare label string and compute its geometrical width
1632 Standard_Real aLabelWidth;
1633 TCollection_ExtendedString aLabelString = GetValueString (aLabelWidth);
1634
1635 // Add margins to cut dimension lines for 3d text
1636 if (aDimensionAspect->IsText3d())
1637 {
1638 aLabelWidth += aDimensionAspect->TextAspect()->Height() * THE_3D_TEXT_MARGIN * 2.0;
1639 }
1640
1641 // Handle user-defined and automatic arrow placement
1642 switch (aDimensionAspect->ArrowOrientation())
1643 {
1644 case Prs3d_DAO_External: theIsArrowsExternal = true; break;
1645 case Prs3d_DAO_Internal: theIsArrowsExternal = false; break;
1646 case Prs3d_DAO_Fit:
1647 {
1648 // Add margin to ensure a small tail between text and arrow
1649 Standard_Real anArrowMargin = aDimensionAspect->IsText3d()
1650 ? aDimensionAspect->TextAspect()->Height() * THE_3D_TEXT_MARGIN
1651 : 0.0;
1652
1653 Standard_Real aDimensionWidth = aLineBegPoint.Distance (aLineEndPoint);
1654 Standard_Real anArrowsWidth = theIsOneSide
1655 ? anArrowLength + anArrowMargin
1656 : (anArrowLength + anArrowMargin) * 2.0;
1657
1658 theIsArrowsExternal = aDimensionWidth < aLabelWidth + anArrowsWidth;
1659 break;
1660 }
1661 }
1662
1663 // Handle user-defined and automatic text placement
1664 switch (theHorizontalTextPos)
1665 {
1666 case Prs3d_DTHP_Left : theLabelPosition |= LabelPosition_Left; break;
1667 case Prs3d_DTHP_Right : theLabelPosition |= LabelPosition_Right; break;
1668 case Prs3d_DTHP_Center: theLabelPosition |= LabelPosition_HCenter; break;
1669 case Prs3d_DTHP_Fit:
1670 {
1671 Standard_Real aDimensionWidth = aLineBegPoint.Distance (aLineEndPoint);
1672 Standard_Real anArrowsWidth = theIsOneSide ? anArrowLength : 2.0 * anArrowLength;
1673 Standard_Real aContentWidth = theIsArrowsExternal ? aLabelWidth : aLabelWidth + anArrowsWidth;
1674
1675 theLabelPosition |= aDimensionWidth < aContentWidth ? LabelPosition_Left : LabelPosition_HCenter;
1676 break;
1677 }
1678 }
1679
1680 // Handle vertical text placement options
1681 switch (aDimensionAspect->TextVerticalPosition())
1682 {
1683 case Prs3d_DTVP_Above : theLabelPosition |= LabelPosition_Above; break;
1684 case Prs3d_DTVP_Below : theLabelPosition |= LabelPosition_Below; break;
1685 case Prs3d_DTVP_Center : theLabelPosition |= LabelPosition_VCenter; break;
1686 }
1687 }
1688
1689 //=======================================================================
1690 //function : UnsetFixedTextPosition
1691 //purpose :
1692 //=======================================================================
UnsetFixedTextPosition()1693 void PrsDim_Dimension::UnsetFixedTextPosition()
1694 {
1695 myIsTextPositionFixed = Standard_False;
1696 myFixedTextPosition = gp::Origin();
1697 }
1698