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