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