0024564: Select3D_SensitiveFace gives inaccurate picking depth for AIS_Plane (interio...
[occt.git] / src / AIS / AIS_Dimension.cxx
CommitLineData
60bf98ae 1// Created on: 2013-11-11
2// Created by: Anastasia BORISOVA
3// Copyright (c) 2013 OPEN CASCADE SAS
a6eb515f 4//
973c2be1 5// This file is part of Open CASCADE Technology software library.
a6eb515f 6//
973c2be1 7// This library is free software; you can redistribute it and / or modify it
8// under the terms of the GNU Lesser General Public version 2.1 as published
9// by the Free Software Foundation, with special exception defined in the file
10// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11// distribution for complete text of the license and disclaimer of any warranty.
a6eb515f 12//
973c2be1 13// Alternatively, this file may be used under the terms of Open CASCADE
14// commercial license or contractual agreement.
a6eb515f 15
a6eb515f 16#include <AIS_Dimension.hxx>
d7bffd44 17
18#include <AIS.hxx>
a6eb515f 19#include <AIS_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>
27#include <GC_MakeCircle.hxx>
fe83e1ea 28#include <GeomAdaptor_Curve.hxx>
a6eb515f 29#include <Geom_Circle.hxx>
a6eb515f 30#include <Geom_TrimmedCurve.hxx>
31#include <gce_MakeDir.hxx>
32#include <gce_MakeLin.hxx>
33#include <Graphic3d_ArrayOfSegments.hxx>
34#include <Graphic3d_ArrayOfTriangles.hxx>
35#include <Graphic3d_AspectLine3d.hxx>
36#include <Graphic3d_AspectFillArea3d.hxx>
37#include <Graphic3d_AspectText3d.hxx>
38#include <Graphic3d_Group.hxx>
39#include <PrsMgr_PresentationManager3d.hxx>
40#include <Prs3d_Arrow.hxx>
41#include <Prs3d_ArrowAspect.hxx>
42#include <Prs3d_Drawer.hxx>
43#include <Prs3d_LineAspect.hxx>
44#include <Prs3d_Presentation.hxx>
45#include <Prs3d_Root.hxx>
46#include <Prs3d_ShadingAspect.hxx>
47#include <Prs3d_Text.hxx>
48#include <SelectMgr_EntityOwner.hxx>
49#include <SelectMgr_Selection.hxx>
50#include <SelectMgr_SequenceOfOwner.hxx>
51#include <Select3D_ListIteratorOfListOfSensitive.hxx>
52#include <Select3D_ListOfSensitive.hxx>
a6eb515f 53#include <Select3D_SensitiveCircle.hxx>
54#include <Select3D_SensitiveGroup.hxx>
fe83e1ea 55#include <Select3D_SensitiveCurve.hxx>
a6eb515f 56#include <Select3D_SensitiveSegment.hxx>
fe83e1ea 57#include <Select3D_SensitiveTriangle.hxx>
51f8f60c 58#include <Select3D_SensitiveTriangulation.hxx>
59#include <Poly_Array1OfTriangle.hxx>
60#include <Poly_Triangulation.hxx>
a6eb515f 61#include <Standard_CString.hxx>
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>
68#include <TopoDS_Vertex.hxx>
69#include <Units.hxx>
70#include <Units_UnitsDictionary.hxx>
71#include <UnitsAPI.hxx>
72#include <UnitsAPI_SystemUnits.hxx>
60bf98ae 73#include <Standard_ProgramError.hxx>
a6eb515f 74
75IMPLEMENT_STANDARD_HANDLE(AIS_Dimension, AIS_InteractiveObject)
76IMPLEMENT_STANDARD_RTTIEXT(AIS_Dimension, AIS_InteractiveObject)
77
d7bffd44 78namespace
a6eb515f 79{
fe83e1ea 80 // default text strings
d7bffd44 81 static const Standard_Utf32Char THE_FILL_CHARACTER ('0');
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;
d7bffd44 92};
a6eb515f 93
94//=======================================================================
95//function : Constructor
96//purpose :
97//=======================================================================
60bf98ae 98AIS_Dimension::AIS_Dimension (const AIS_KindOfDimension theType)
a6eb515f 99: AIS_InteractiveObject(),
60bf98ae 100 myCustomValue (0.0),
a6eb515f 101 myIsValueCustom (Standard_False),
a6eb515f 102 mySpecialSymbol (' '),
103 myDisplaySpecialSymbol (AIS_DSS_No),
60bf98ae 104 myGeometryType (GeometryType_UndefShapes),
105 myIsPlaneCustom (Standard_False),
62b6361a 106 myFlyout (0.0),
60bf98ae 107 myIsValid (Standard_False),
108 myKindOfDimension (theType)
a6eb515f 109{
a6eb515f 110}
111
112//=======================================================================
60bf98ae 113//function : SetCustomValue
114//purpose :
a6eb515f 115//=======================================================================
60bf98ae 116void AIS_Dimension::SetCustomValue (const Standard_Real theValue)
a6eb515f 117{
60bf98ae 118 if (myIsValueCustom && myCustomValue == theValue)
119 {
120 return;
121 }
a6eb515f 122
60bf98ae 123 myIsValueCustom = Standard_True;
124
125 myCustomValue = theValue;
126
127 SetToUpdate();
a6eb515f 128}
129
130//=======================================================================
60bf98ae 131//function : GetPlane
a6eb515f 132//purpose :
133//=======================================================================
60bf98ae 134const gp_Pln& AIS_Dimension::GetPlane() const
a6eb515f 135{
60bf98ae 136 return myPlane;
a6eb515f 137}
138
139//=======================================================================
60bf98ae 140//function : GetGeometryType
a6eb515f 141//purpose :
142//=======================================================================
60bf98ae 143const Standard_Integer AIS_Dimension::GetGeometryType () const
a6eb515f 144{
60bf98ae 145 return myGeometryType;
a6eb515f 146}
147
148//=======================================================================
60bf98ae 149//function : SetUserPlane
a6eb515f 150//purpose :
151//=======================================================================
60bf98ae 152void AIS_Dimension::SetCustomPlane (const gp_Pln& thePlane)
a6eb515f 153{
60bf98ae 154 myPlane = thePlane;
155 myIsPlaneCustom = Standard_True;
156
157 // Check validity if geometry has been set already.
158 if (myIsValid)
159 {
160 myIsValid &= CheckPlane (myPlane);
161 SetToUpdate();
162 }
a6eb515f 163}
164
165//=======================================================================
60bf98ae 166//function : SetDimensionAspect
167//purpose :
a6eb515f 168//=======================================================================
60bf98ae 169void AIS_Dimension::SetDimensionAspect (const Handle(Prs3d_DimensionAspect)& theDimensionAspect)
a6eb515f 170{
60bf98ae 171 myDrawer->SetDimensionAspect (theDimensionAspect);
172
173 SetToUpdate();
a6eb515f 174}
175
176//=======================================================================
60bf98ae 177//function : SetDisplaySpecialSymbol
178//purpose :
a6eb515f 179//=======================================================================
60bf98ae 180void AIS_Dimension::SetDisplaySpecialSymbol (const AIS_DisplaySpecialSymbol theDisplaySpecSymbol)
a6eb515f 181{
60bf98ae 182 if (myDisplaySpecialSymbol == theDisplaySpecSymbol)
183 {
184 return;
185 }
186
187 myDisplaySpecialSymbol = theDisplaySpecSymbol;
188
189 SetToUpdate();
a6eb515f 190}
191
192//=======================================================================
60bf98ae 193//function : SetSpecialSymbol
a6eb515f 194//purpose :
195//=======================================================================
60bf98ae 196void AIS_Dimension::SetSpecialSymbol (const Standard_ExtCharacter theSpecialSymbol)
a6eb515f 197{
60bf98ae 198 if (mySpecialSymbol == theSpecialSymbol)
199 {
200 return;
201 }
202
203 mySpecialSymbol = theSpecialSymbol;
204
205 SetToUpdate();
a6eb515f 206}
207
208//=======================================================================
60bf98ae 209//function : SetSelToleranceForText2d
210//purpose :
a6eb515f 211//=======================================================================
60bf98ae 212void AIS_Dimension::SetSelToleranceForText2d (const Standard_Real theTol)
a6eb515f 213{
60bf98ae 214 if (mySelToleranceForText2d == theTol)
215 {
216 return;
217 }
218
219 mySelToleranceForText2d = theTol;
220
221 SetToUpdate();
a6eb515f 222}
223
224//=======================================================================
60bf98ae 225//function : SetFlyout
226//purpose :
a6eb515f 227//=======================================================================
60bf98ae 228void AIS_Dimension::SetFlyout (const Standard_Real theFlyout)
a6eb515f 229{
60bf98ae 230 if (myFlyout == theFlyout)
231 {
232 return;
233 }
a6eb515f 234
60bf98ae 235 myFlyout = theFlyout;
236
237 SetToUpdate();
238}
a6eb515f 239
240//=======================================================================
60bf98ae 241//function : GetDisplayUnits
242//purpose :
a6eb515f 243//=======================================================================
60bf98ae 244const TCollection_AsciiString& AIS_Dimension::GetDisplayUnits() const
a6eb515f 245{
60bf98ae 246 return THE_UNDEFINED_UNITS;
a6eb515f 247}
248
249//=======================================================================
60bf98ae 250//function : GetModelUnits
251//purpose :
a6eb515f 252//=======================================================================
60bf98ae 253const TCollection_AsciiString& AIS_Dimension::GetModelUnits() const
a6eb515f 254{
60bf98ae 255 return THE_UNDEFINED_UNITS;
a6eb515f 256}
257
258//=======================================================================
60bf98ae 259//function : ValueToDisplayUnits
260//purpose :
a6eb515f 261//=======================================================================
60bf98ae 262Standard_Real AIS_Dimension::ValueToDisplayUnits() const
a6eb515f 263{
60bf98ae 264 return UnitsAPI::AnyToAny (GetValue(),
265 GetModelUnits().ToCString(),
266 GetDisplayUnits().ToCString());
a6eb515f 267}
268
269//=======================================================================
60bf98ae 270//function : GetValueString
a6eb515f 271//purpose :
272//=======================================================================
60bf98ae 273TCollection_ExtendedString AIS_Dimension::GetValueString (Standard_Real& theWidth) const
a6eb515f 274{
60bf98ae 275 // format value string using "sprintf"
276 TCollection_AsciiString aFormatStr = myDrawer->DimensionAspect()->ValueStringFormat();
a6eb515f 277
60bf98ae 278 char aFmtBuffer[256];
279 sprintf (aFmtBuffer, aFormatStr.ToCString(), ValueToDisplayUnits());
280 TCollection_ExtendedString aValueStr = TCollection_ExtendedString (aFmtBuffer);
a6eb515f 281
60bf98ae 282 // add units to values string
283 if (myDrawer->DimensionAspect()->IsUnitsDisplayed())
a6eb515f 284 {
60bf98ae 285 aValueStr += " ";
286 aValueStr += TCollection_ExtendedString (GetDisplayUnits());
a6eb515f 287 }
60bf98ae 288
289 switch (myDisplaySpecialSymbol)
a6eb515f 290 {
60bf98ae 291 case AIS_DSS_Before : aValueStr.Insert (1, mySpecialSymbol); break;
292 case AIS_DSS_After : aValueStr.Insert (aValueStr.Length() + 1, mySpecialSymbol); break;
293 case AIS_DSS_No : break;
a6eb515f 294 }
295
d7bffd44 296 // Get text style parameters
a6eb515f 297 Quantity_Color aColor;
d7bffd44 298 Standard_CString aFontName;
a6eb515f 299 Standard_Real aFactor;
300 Standard_Real aSpace;
d7bffd44 301 myDrawer->DimensionAspect()->TextAspect()->Aspect()->Values (aColor, aFontName, aFactor, aSpace);
fe83e1ea 302 Font_FontAspect aFontAspect = myDrawer->DimensionAspect()->TextAspect()->Aspect()->GetTextFontAspect();
303 Standard_Real aFontHeight = myDrawer->DimensionAspect()->TextAspect()->Height();
304
60bf98ae 305 NCollection_Utf8String anUTFString = (Standard_Utf16Char* )aValueStr.ToExtString();
fe83e1ea 306
d7bffd44 307 theWidth = 0.0;
fe83e1ea 308
309 if (myDrawer->DimensionAspect()->IsText3d())
310 {
311 // text width produced by BRepFont
312 Font_BRepFont aFont (aFontName, aFontAspect, aFontHeight);
313
314 for (NCollection_Utf8Iter anIter = anUTFString.Iterator(); *anIter != 0; )
315 {
316 Standard_Utf32Char aCurrChar = *anIter;
317 Standard_Utf32Char aNextChar = *(++anIter);
318 theWidth += aFont.AdvanceX (aCurrChar, aNextChar);
319 }
320 }
321 else
d7bffd44 322 {
fe83e1ea 323 // Text width for 1:1 scale 2D case
60bf98ae 324 Handle(Font_FTFont) aFont = new Font_FTFont();
fe83e1ea 325 aFont->Init (aFontName, aFontAspect, (const unsigned int)aFontHeight, THE_2D_TEXT_RESOLUTION);
326
327 for (NCollection_Utf8Iter anIter = anUTFString.Iterator(); *anIter != 0; )
328 {
329 Standard_Utf32Char aCurrChar = *anIter;
330 Standard_Utf32Char aNextChar = *(++anIter);
331 theWidth += (Standard_Real) aFont->AdvanceX (aCurrChar, aNextChar);
332 }
d7bffd44 333 }
60bf98ae 334
335 return aValueStr;
a6eb515f 336}
337
338//=======================================================================
60bf98ae 339//function : DrawArrow
a6eb515f 340//purpose :
341//=======================================================================
60bf98ae 342void AIS_Dimension::DrawArrow (const Handle(Prs3d_Presentation)& thePresentation,
a6eb515f 343 const gp_Pnt& theLocation,
344 const gp_Dir& theDirection)
345{
346 Prs3d_Root::NewGroup (thePresentation);
fe83e1ea 347
348 Quantity_Length aLength = myDrawer->DimensionAspect()->ArrowAspect()->Length();
349 Standard_Real anAngle = myDrawer->DimensionAspect()->ArrowAspect()->Angle();
a6eb515f 350
351 if (myDrawer->DimensionAspect()->IsArrows3d())
352 {
353 Prs3d_Arrow::Draw (thePresentation,
354 theLocation,
d7bffd44 355 theDirection,
fe83e1ea 356 anAngle,
357 aLength);
a6eb515f 358 }
359 else
360 {
fe83e1ea 361 gp_Pnt aLeftPoint (gp::Origin());
362 gp_Pnt aRightPoint (gp::Origin());
60bf98ae 363 const gp_Dir& aPlane = GetPlane().Axis().Direction();
fe83e1ea 364
365 PointsForArrow (theLocation, theDirection, aPlane, aLength, anAngle, aLeftPoint, aRightPoint);
366
a6eb515f 367 Handle(Graphic3d_ArrayOfTriangles) anArrow = new Graphic3d_ArrayOfTriangles(3);
a6eb515f 368
369 anArrow->AddVertex (aLeftPoint);
370 anArrow->AddVertex (theLocation);
371 anArrow->AddVertex (aRightPoint);
372
373 // Set aspect for arrow triangles
374 Quantity_Color aColor;
375 Aspect_TypeOfLine aTOL;
376 Standard_Real aWidth;
377 myDrawer->DimensionAspect()->ArrowAspect()->Aspect()->Values (aColor, aTOL, aWidth);
378 Graphic3d_MaterialAspect aShadeMat (Graphic3d_NOM_DEFAULT);
379 aShadeMat.SetReflectionModeOff (Graphic3d_TOR_AMBIENT);
380 aShadeMat.SetReflectionModeOff (Graphic3d_TOR_DIFFUSE);
381 aShadeMat.SetReflectionModeOff (Graphic3d_TOR_SPECULAR);
d7bffd44 382
383 Handle(Prs3d_ShadingAspect) aShadingStyle = new Prs3d_ShadingAspect();
384 aShadingStyle->SetColor (aColor);
385 aShadingStyle->SetMaterial (aShadeMat);
386
387 Prs3d_Root::CurrentGroup (thePresentation)->SetPrimitivesAspect (aShadingStyle->Aspect());
388 Prs3d_Root::CurrentGroup (thePresentation)->AddPrimitiveArray (anArrow);
a6eb515f 389 }
fe83e1ea 390
391 SelectionGeometry::Arrow& aSensitiveArrow = mySelectionGeom.NewArrow();
392 aSensitiveArrow.Position = theLocation;
393 aSensitiveArrow.Direction = theDirection;
a6eb515f 394}
395
396//=======================================================================
60bf98ae 397//function : DrawText
a6eb515f 398//purpose :
399//=======================================================================
60bf98ae 400void AIS_Dimension::DrawText (const Handle(Prs3d_Presentation)& thePresentation,
fe83e1ea 401 const gp_Pnt& theTextPos,
402 const gp_Dir& theTextDir,
403 const TCollection_ExtendedString& theText,
404 const Standard_Integer theLabelPosition)
a6eb515f 405{
a6eb515f 406 if (myDrawer->DimensionAspect()->IsText3d())
407 {
fe83e1ea 408 // getting font parameters
a6eb515f 409 Quantity_Color aColor;
410 Standard_CString aFontName;
411 Standard_Real anExpansionFactor;
412 Standard_Real aSpace;
413 myDrawer->DimensionAspect()->TextAspect()->Aspect()->Values (aColor, aFontName, anExpansionFactor, aSpace);
414 Font_FontAspect aFontAspect = myDrawer->DimensionAspect()->TextAspect()->Aspect()->GetTextFontAspect();
fe83e1ea 415 Standard_Real aFontHeight = myDrawer->DimensionAspect()->TextAspect()->Height();
a6eb515f 416
fe83e1ea 417 // creating TopoDS_Shape for text
418 Font_BRepFont aFont (aFontName, aFontAspect, aFontHeight);
419 NCollection_Utf8String anUTFString = (Standard_Utf16Char* )theText.ToExtString();
420 TopoDS_Shape aTextShape = aFont.RenderText (anUTFString);
a6eb515f 421
fe83e1ea 422 // compute text width with kerning
423 Standard_Real aTextWidth = 0.0;
424 Standard_Real aTextHeight = aFont.Ascender() + aFont.Descender();
d7bffd44 425
fe83e1ea 426 for (NCollection_Utf8Iter anIter = anUTFString.Iterator(); *anIter != 0; )
427 {
428 Standard_Utf32Char aCurrChar = *anIter;
429 Standard_Utf32Char aNextChar = *(++anIter);
430 aTextWidth += aFont.AdvanceX (aCurrChar, aNextChar);
431 }
432
433 // formating text position in XOY plane
d7bffd44 434 Standard_Integer aHLabelPos = theLabelPosition & LabelPosition_HMask;
435 Standard_Integer aVLabelPos = theLabelPosition & LabelPosition_VMask;
436
437 gp_Dir aTextDir (aHLabelPos == LabelPosition_Left ? -theTextDir : theTextDir);
438
439 // compute label offsets
fe83e1ea 440 Standard_Real aMarginSize = aFontHeight * THE_3D_TEXT_MARGIN;
d7bffd44 441 Standard_Real aCenterHOffset = 0.0;
442 Standard_Real aCenterVOffset = 0.0;
443 switch (aHLabelPos)
a6eb515f 444 {
d7bffd44 445 case LabelPosition_HCenter : aCenterHOffset = 0.0; break;
446 case LabelPosition_Right : aCenterHOffset = aTextWidth / 2.0 + aMarginSize; break;
447 case LabelPosition_Left : aCenterHOffset = -aTextWidth / 2.0 - aMarginSize; break;
a6eb515f 448 }
d7bffd44 449 switch (aVLabelPos)
a6eb515f 450 {
d7bffd44 451 case LabelPosition_VCenter : aCenterVOffset = 0.0; break;
452 case LabelPosition_Above : aCenterVOffset = aTextHeight / 2.0 + aMarginSize; break;
453 case LabelPosition_Below : aCenterVOffset = -aTextHeight / 2.0 - aMarginSize; break;
a6eb515f 454 }
d7bffd44 455
456 // compute shape offset transformation
fe83e1ea 457 Standard_Real aShapeHOffset = aCenterHOffset - aTextWidth / 2.0;
d7bffd44 458 Standard_Real aShapeVOffset = aCenterVOffset - aTextHeight / 2.0;
459
fe83e1ea 460 // center shape in its bounding box (suppress border spacing added by FT_Font)
461 Bnd_Box aShapeBnd;
462 BRepBndLib::AddClose (aTextShape, aShapeBnd);
463
464 Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
465 aShapeBnd.Get (aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
466
467 Standard_Real aXalign = aTextWidth * 0.5 - (aXmax + aXmin) * 0.5;
468 Standard_Real aYalign = aTextHeight * 0.5 - (aYmax + aYmin) * 0.5;
469 aShapeHOffset += aXalign;
470 aShapeVOffset += aYalign;
471
d7bffd44 472 gp_Trsf anOffsetTrsf;
473 anOffsetTrsf.SetTranslation (gp::Origin(), gp_Pnt (aShapeHOffset, aShapeVOffset, 0.0));
474 aTextShape.Move (anOffsetTrsf);
a6eb515f 475
fe83e1ea 476 // transform text to myWorkingPlane coordinate system
60bf98ae 477 gp_Ax3 aTextCoordSystem (theTextPos, GetPlane().Axis().Direction(), aTextDir);
d7bffd44 478 gp_Trsf aTextPlaneTrsf;
479 aTextPlaneTrsf.SetTransformation (aTextCoordSystem, gp_Ax3 (gp::XOY()));
480 aTextShape.Move (aTextPlaneTrsf);
a6eb515f 481
fe83e1ea 482 // set text flipping anchors
d7bffd44 483 gp_Trsf aCenterOffsetTrsf;
484 gp_Pnt aCenterOffset (aCenterHOffset, aCenterVOffset, 0.0);
485 aCenterOffsetTrsf.SetTranslation (gp::Origin(), aCenterOffset);
486
fe83e1ea 487 gp_Pnt aCenterOfLabel (gp::Origin());
488 aCenterOfLabel.Transform (aCenterOffsetTrsf);
489 aCenterOfLabel.Transform (aTextPlaneTrsf);
d7bffd44 490
60bf98ae 491 gp_Ax2 aFlippingAxes (aCenterOfLabel, GetPlane().Axis().Direction(), aTextDir);
d7bffd44 492 Prs3d_Root::CurrentGroup (thePresentation)->SetFlippingOptions (Standard_True, aFlippingAxes);
493
fe83e1ea 494 // draw text
a6eb515f 495 if (myDrawer->DimensionAspect()->IsTextShaded())
496 {
497 // Setting text shading and color parameters
498 Graphic3d_MaterialAspect aShadeMat (Graphic3d_NOM_DEFAULT);
499 aShadeMat.SetReflectionModeOff (Graphic3d_TOR_AMBIENT);
500 aShadeMat.SetReflectionModeOff (Graphic3d_TOR_DIFFUSE);
501 aShadeMat.SetReflectionModeOff (Graphic3d_TOR_SPECULAR);
502 myDrawer->ShadingAspect()->Aspect()->SetInteriorColor (aColor);
503 myDrawer->ShadingAspect()->Aspect()->SetBackInteriorColor (aColor);
504 myDrawer->ShadingAspect()->SetMaterial (aShadeMat);
505
fe83e1ea 506 // drawing text
a6eb515f 507 StdPrs_ShadedShape::Add (thePresentation, aTextShape, myDrawer);
508 }
509 else
510 {
fe83e1ea 511 // setting color for text
a6eb515f 512 myDrawer->FreeBoundaryAspect()->Aspect()->SetColor (aColor);
fe83e1ea 513 // drawing text
a6eb515f 514 StdPrs_WFShape::Add (thePresentation, aTextShape, myDrawer);
515 }
d7bffd44 516 Prs3d_Root::CurrentGroup (thePresentation)->SetFlippingOptions (Standard_False, gp_Ax2());
517
fe83e1ea 518 mySelectionGeom.TextPos = aCenterOfLabel;
519 mySelectionGeom.TextDir = aTextDir;
520 mySelectionGeom.TextWidth = aTextWidth + aMarginSize * 2.0;
521 mySelectionGeom.TextHeight = aTextHeight;
522
523 return;
a6eb515f 524 }
525
fe83e1ea 526 // generate primitives for 2D text
d7bffd44 527 myDrawer->DimensionAspect()->TextAspect()->Aspect()->SetDisplayType (Aspect_TODT_DIMENSION);
528
529 Prs3d_Text::Draw (thePresentation,
530 myDrawer->DimensionAspect()->TextAspect(),
531 theText,
fe83e1ea 532 theTextPos);
d7bffd44 533
fe83e1ea 534 mySelectionGeom.TextPos = theTextPos;
535 mySelectionGeom.TextDir = theTextDir;
536 mySelectionGeom.TextWidth = 0.0;
537 mySelectionGeom.TextHeight = 0.0;
a6eb515f 538}
539
d7bffd44 540//=======================================================================
60bf98ae 541//function : DrawExtension
a6eb515f 542//purpose :
543//=======================================================================
60bf98ae 544void AIS_Dimension::DrawExtension (const Handle(Prs3d_Presentation)& thePresentation,
d7bffd44 545 const Standard_Real theExtensionSize,
546 const gp_Pnt& theExtensionStart,
547 const gp_Dir& theExtensionDir,
fe83e1ea 548 const TCollection_ExtendedString& theLabelString,
549 const Standard_Real theLabelWidth,
550 const Standard_Integer theMode,
d7bffd44 551 const Standard_Integer theLabelPosition)
a6eb515f 552{
fe83e1ea 553 // reference line for extension starting at its connection point
554 gp_Lin anExtensionLine (theExtensionStart, theExtensionDir);
a6eb515f 555
fe83e1ea 556 Standard_Boolean hasLabel = theLabelString.Length() > 0;
fe83e1ea 557 if (hasLabel && (theMode == ComputeMode_All || theMode == ComputeMode_Text))
a6eb515f 558 {
d7bffd44 559 // compute text primitives; get its model width
fe83e1ea 560 gp_Pnt aTextPos = ElCLib::Value (theExtensionSize, anExtensionLine);
60bf98ae 561 gp_Dir aTextDir = theExtensionDir;
fe83e1ea 562
60bf98ae 563 DrawText (thePresentation,
fe83e1ea 564 aTextPos,
565 aTextDir,
566 theLabelString,
567 theLabelPosition);
a6eb515f 568 }
569
fe83e1ea 570 if (theMode != ComputeMode_All && theMode != ComputeMode_Line)
a6eb515f 571 {
d7bffd44 572 return;
a6eb515f 573 }
574
fe83e1ea 575 Standard_Boolean isShortLine = !myDrawer->DimensionAspect()->IsText3d()
576 || theLabelPosition & LabelPosition_VCenter;
577
d7bffd44 578 // compute graphical primitives and sensitives for extension line
579 gp_Pnt anExtStart = theExtensionStart;
fe83e1ea 580 gp_Pnt anExtEnd = !hasLabel || isShortLine
581 ? ElCLib::Value (theExtensionSize, anExtensionLine)
582 : ElCLib::Value (theExtensionSize + theLabelWidth, anExtensionLine);
d7bffd44 583
fe83e1ea 584 // add graphical primitives
d7bffd44 585 Handle(Graphic3d_ArrayOfSegments) anExtPrimitive = new Graphic3d_ArrayOfSegments (2);
586 anExtPrimitive->AddVertex (anExtStart);
587 anExtPrimitive->AddVertex (anExtEnd);
588
fe83e1ea 589 // add selection primitives
590 SelectionGeometry::Curve& aSensitiveCurve = mySelectionGeom.NewCurve();
591 aSensitiveCurve.Append (anExtStart);
592 aSensitiveCurve.Append (anExtEnd);
a6eb515f 593
fe83e1ea 594 if (!myDrawer->DimensionAspect()->IsText3d() && theMode == ComputeMode_All)
a6eb515f 595 {
d7bffd44 596 Prs3d_Root::CurrentGroup (thePresentation)->SetStencilTestOptions (Standard_True);
597 }
598 Handle(Graphic3d_AspectLine3d) aDimensionLineStyle = myDrawer->DimensionAspect()->LineAspect()->Aspect();
599 Prs3d_Root::CurrentGroup (thePresentation)->SetPrimitivesAspect (aDimensionLineStyle);
600 Prs3d_Root::CurrentGroup (thePresentation)->AddPrimitiveArray (anExtPrimitive);
fe83e1ea 601 if (!myDrawer->DimensionAspect()->IsText3d() && theMode == ComputeMode_All)
d7bffd44 602 {
603 Prs3d_Root::CurrentGroup (thePresentation)->SetStencilTestOptions (Standard_False);
a6eb515f 604 }
605}
606
607//=======================================================================
60bf98ae 608//function : DrawLinearDimension
a6eb515f 609//purpose :
610//=======================================================================
60bf98ae 611void AIS_Dimension::DrawLinearDimension (const Handle(Prs3d_Presentation)& thePresentation,
fe83e1ea 612 const Standard_Integer theMode,
60bf98ae 613 const gp_Pnt& theFirstPoint,
614 const gp_Pnt& theSecondPoint,
615 const Standard_Boolean theIsOneSide)
a6eb515f 616{
60bf98ae 617 // do not build any dimension for equal points
618 if (theFirstPoint.IsEqual (theSecondPoint, Precision::Confusion()))
a6eb515f 619 {
60bf98ae 620 Standard_ProgramError::Raise ("Can not build presentation for equal points.");
a6eb515f 621 }
d7bffd44 622
623 // compute dimension line points
60bf98ae 624 gp_Ax1 aPlaneNormal = GetPlane().Axis();
625 gp_Dir aTargetPointsVector = gce_MakeDir (theFirstPoint, theSecondPoint);
d7bffd44 626
627 // compute flyout direction vector
60bf98ae 628 gp_Dir aFlyoutVector = aPlaneNormal.Direction() ^ aTargetPointsVector;
d7bffd44 629
630 // create lines for layouts
60bf98ae 631 gp_Lin aLine1 (theFirstPoint, aFlyoutVector);
632 gp_Lin aLine2 (theSecondPoint, aFlyoutVector);
d7bffd44 633
634 // Get flyout end points
60bf98ae 635 gp_Pnt aLineBegPoint = ElCLib::Value (ElCLib::Parameter (aLine1, theFirstPoint) + GetFlyout(), aLine1);
636 gp_Pnt aLineEndPoint = ElCLib::Value (ElCLib::Parameter (aLine2, theSecondPoint) + GetFlyout(), aLine2);
d7bffd44 637
a6eb515f 638 Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
a6eb515f 639
d7bffd44 640 gp_Lin aDimensionLine = gce_MakeLin (aLineBegPoint, aLineEndPoint);
a6eb515f 641
d7bffd44 642 // For extensions we need to know arrow size, text size and extension size: get it from aspect
643 Quantity_Length anArrowLength = aDimensionAspect->ArrowAspect()->Length();
644 Standard_Real anExtensionSize = aDimensionAspect->ExtensionSize();
fe83e1ea 645 // prepare label string and compute its geometrical width
646 Standard_Real aLabelWidth;
60bf98ae 647 TCollection_ExtendedString aLabelString = GetValueString (aLabelWidth);
a6eb515f 648
fe83e1ea 649 // add margins to cut dimension lines for 3d text
650 if (aDimensionAspect->IsText3d())
651 {
652 aLabelWidth += aDimensionAspect->TextAspect()->Height() * THE_3D_TEXT_MARGIN * 2.0;
653 }
654
655 // handle user-defined and automatic arrow placement
d7bffd44 656 bool isArrowsExternal = false;
657 switch (aDimensionAspect->ArrowOrientation())
a6eb515f 658 {
d7bffd44 659 case Prs3d_DAO_External: isArrowsExternal = true; break;
660 case Prs3d_DAO_Internal: isArrowsExternal = false; break;
661 case Prs3d_DAO_Fit:
a6eb515f 662 {
fe83e1ea 663 // add margin to ensure a small tail between text and arrow
664 Standard_Real anArrowMargin = aDimensionAspect->IsText3d()
665 ? aDimensionAspect->TextAspect()->Height() * THE_3D_TEXT_MARGIN
666 : 0.0;
667
d7bffd44 668 Standard_Real aDimensionWidth = aLineBegPoint.Distance (aLineEndPoint);
60bf98ae 669 Standard_Real anArrowsWidth = theIsOneSide
fe83e1ea 670 ? anArrowLength + anArrowMargin
671 : (anArrowLength + anArrowMargin) * 2.0;
672
673 isArrowsExternal = aDimensionWidth < aLabelWidth + anArrowsWidth;
d7bffd44 674 break;
a6eb515f 675 }
676 }
a6eb515f 677
fe83e1ea 678 // compute arrows positions and directions
d7bffd44 679 gp_Dir aFirstArrowDir = aDimensionLine.Direction().Reversed();
680 gp_Dir aSecondArrowDir = aDimensionLine.Direction();
681 gp_Dir aFirstExtensionDir = aDimensionLine.Direction().Reversed();
682 gp_Dir aSecondExtensionDir = aDimensionLine.Direction();
683
684 gp_Pnt aFirstArrowBegin (0.0, 0.0, 0.0);
685 gp_Pnt aFirstArrowEnd (0.0, 0.0, 0.0);
686 gp_Pnt aSecondArrowBegin (0.0, 0.0, 0.0);
687 gp_Pnt aSecondArrowEnd (0.0, 0.0, 0.0);
a6eb515f 688
d7bffd44 689 if (isArrowsExternal)
a6eb515f 690 {
691 aFirstArrowDir.Reverse();
692 aSecondArrowDir.Reverse();
a6eb515f 693 }
d7bffd44 694
695 aFirstArrowBegin = aLineBegPoint;
696 aSecondArrowBegin = aLineEndPoint;
697 aFirstArrowEnd = aLineBegPoint.Translated (-gp_Vec (aFirstArrowDir).Scaled (anArrowLength));
698 aSecondArrowEnd = aLineEndPoint.Translated (-gp_Vec (aSecondArrowDir).Scaled (anArrowLength));
699
700 gp_Pnt aCenterLineBegin = isArrowsExternal
60bf98ae 701 ? aLineBegPoint : aFirstArrowEnd;
d7bffd44 702
60bf98ae 703 gp_Pnt aCenterLineEnd = isArrowsExternal || theIsOneSide
d7bffd44 704 ? aLineEndPoint : aSecondArrowEnd;
705
706 Standard_Integer aLabelPosition = LabelPosition_None;
707
fe83e1ea 708 // handle user-defined and automatic text placement
d7bffd44 709 switch (aDimensionAspect->TextHorizontalPosition())
a6eb515f 710 {
d7bffd44 711 case Prs3d_DTHP_Left : aLabelPosition |= LabelPosition_Left; break;
712 case Prs3d_DTHP_Right : aLabelPosition |= LabelPosition_Right; break;
713 case Prs3d_DTHP_Center: aLabelPosition |= LabelPosition_HCenter; break;
714 case Prs3d_DTHP_Fit:
715 {
716 Standard_Real aDimensionWidth = aLineBegPoint.Distance (aLineEndPoint);
60bf98ae 717 Standard_Real anArrowsWidth = theIsOneSide ? anArrowLength : 2.0 * anArrowLength;
fe83e1ea 718 Standard_Real aContentWidth = isArrowsExternal ? aLabelWidth : aLabelWidth + anArrowsWidth;
d7bffd44 719
720 aLabelPosition |= aDimensionWidth < aContentWidth ? LabelPosition_Left : LabelPosition_HCenter;
721 break;
722 }
a6eb515f 723 }
724
fe83e1ea 725 // handle vertical text placement options
d7bffd44 726 switch (aDimensionAspect->TextVerticalPosition())
a6eb515f 727 {
d7bffd44 728 case Prs3d_DTVP_Above : aLabelPosition |= LabelPosition_Above; break;
729 case Prs3d_DTVP_Below : aLabelPosition |= LabelPosition_Below; break;
730 case Prs3d_DTVP_Center : aLabelPosition |= LabelPosition_VCenter; break;
a6eb515f 731 }
732
d7bffd44 733 switch (aLabelPosition & LabelPosition_HMask)
a6eb515f 734 {
d7bffd44 735 // ------------------------------------------------------------------------ //
736 // CENTER //
737 // -------------------------------------------------------------------------//
d7bffd44 738 case LabelPosition_HCenter:
a6eb515f 739 {
d7bffd44 740 // add label on dimension or extension line to presentation
741 Prs3d_Root::NewGroup (thePresentation);
a6eb515f 742
fe83e1ea 743 gp_Pnt aTextPos = (aCenterLineBegin.XYZ() + aCenterLineEnd.XYZ()) * 0.5;
60bf98ae 744 gp_Dir aTextDir = aDimensionLine.Direction();
a6eb515f 745
fe83e1ea 746 // add text primitives
747 if (theMode == ComputeMode_All || theMode == ComputeMode_Text)
a6eb515f 748 {
60bf98ae 749 DrawText (thePresentation,
fe83e1ea 750 aTextPos,
751 aTextDir,
752 aLabelString,
753 aLabelPosition);
a6eb515f 754 }
d7bffd44 755
fe83e1ea 756 // add dimension line primitives
757 if (theMode == ComputeMode_All || theMode == ComputeMode_Line)
758 {
759 Standard_Boolean isLineBreak = aDimensionAspect->TextVerticalPosition() == Prs3d_DTVP_Center
760 && aDimensionAspect->IsText3d();
d7bffd44 761
fe83e1ea 762 Handle(Graphic3d_ArrayOfSegments) aPrimSegments = new Graphic3d_ArrayOfSegments (isLineBreak ? 4 : 2);
d7bffd44 763
fe83e1ea 764 // compute continuous or sectioned main line segments
765 if (isLineBreak)
766 {
767 Standard_Real aPTextPosition = ElCLib::Parameter (aDimensionLine, aTextPos);
768 gp_Pnt aSection1Beg = aCenterLineBegin;
769 gp_Pnt aSection1End = ElCLib::Value (aPTextPosition - (aLabelWidth * 0.5), aDimensionLine);
770 gp_Pnt aSection2Beg = ElCLib::Value (aPTextPosition + (aLabelWidth * 0.5), aDimensionLine);
771 gp_Pnt aSection2End = aCenterLineEnd;
772
773 aPrimSegments->AddVertex (aSection1Beg);
774 aPrimSegments->AddVertex (aSection1End);
775 aPrimSegments->AddVertex (aSection2Beg);
776 aPrimSegments->AddVertex (aSection2End);
777
778 SelectionGeometry::Curve& aLeftSensitiveCurve = mySelectionGeom.NewCurve();
779 SelectionGeometry::Curve& aRightSensitiveCurve = mySelectionGeom.NewCurve();
780 aLeftSensitiveCurve.Append (aSection1Beg);
781 aLeftSensitiveCurve.Append (aSection1End);
782 aRightSensitiveCurve.Append (aSection2Beg);
783 aRightSensitiveCurve.Append (aSection2End);
784 }
785 else
786 {
787 aPrimSegments->AddVertex (aCenterLineBegin);
788 aPrimSegments->AddVertex (aCenterLineEnd);
a6eb515f 789
fe83e1ea 790 SelectionGeometry::Curve& aSensitiveCurve = mySelectionGeom.NewCurve();
791 aSensitiveCurve.Append (aCenterLineBegin);
792 aSensitiveCurve.Append (aCenterLineEnd);
793 }
a6eb515f 794
fe83e1ea 795 // set text label justification
796 Graphic3d_VerticalTextAlignment aTextJustificaton = Graphic3d_VTA_BOTTOM;
797 switch (aLabelPosition & LabelPosition_VMask)
798 {
799 case LabelPosition_Above :
800 case LabelPosition_VCenter : aTextJustificaton = Graphic3d_VTA_BOTTOM; break;
801 case LabelPosition_Below : aTextJustificaton = Graphic3d_VTA_TOP; break;
802 }
803 aDimensionAspect->TextAspect()->SetVerticalJustification (aTextJustificaton);
a6eb515f 804
fe83e1ea 805 // main dimension line, short extension
806 if (!aDimensionAspect->IsText3d() && theMode == ComputeMode_All)
807 {
808 Prs3d_Root::CurrentGroup (thePresentation)->SetStencilTestOptions (Standard_True);
809 }
810 Prs3d_Root::CurrentGroup (thePresentation)->SetPrimitivesAspect (aDimensionAspect->LineAspect()->Aspect());
811 Prs3d_Root::CurrentGroup (thePresentation)->AddPrimitiveArray (aPrimSegments);
812 if (!aDimensionAspect->IsText3d() && theMode == ComputeMode_All)
813 {
814 Prs3d_Root::CurrentGroup (thePresentation)->SetStencilTestOptions (Standard_False);
815 }
d7bffd44 816
fe83e1ea 817 // add arrows to presentation
818 Prs3d_Root::NewGroup (thePresentation);
d7bffd44 819
60bf98ae 820 DrawArrow (thePresentation, aFirstArrowBegin, aFirstArrowDir);
821 if (!theIsOneSide)
fe83e1ea 822 {
60bf98ae 823 DrawArrow (thePresentation, aSecondArrowBegin, aSecondArrowDir);
fe83e1ea 824 }
d7bffd44 825
fe83e1ea 826 if (!isArrowsExternal)
827 {
828 break;
829 }
d7bffd44 830
fe83e1ea 831 // add arrow extension lines to presentation
832 Prs3d_Root::NewGroup (thePresentation);
d7bffd44 833
60bf98ae 834 DrawExtension (thePresentation, anExtensionSize,
fe83e1ea 835 aFirstArrowEnd, aFirstExtensionDir,
836 THE_EMPTY_LABEL, 0.0, theMode, LabelPosition_None);
60bf98ae 837 if (!theIsOneSide)
fe83e1ea 838 {
60bf98ae 839 DrawExtension (thePresentation, anExtensionSize,
fe83e1ea 840 aSecondArrowEnd, aSecondExtensionDir,
841 THE_EMPTY_LABEL, 0.0, theMode, LabelPosition_None);
842 }
a6eb515f 843 }
1d7ca641 844
845 break;
a6eb515f 846 }
d7bffd44 847 // ------------------------------------------------------------------------ //
848 // LEFT //
849 // -------------------------------------------------------------------------//
850
851 case LabelPosition_Left:
a6eb515f 852 {
d7bffd44 853 // add label on dimension or extension line to presentation
854 Prs3d_Root::NewGroup (thePresentation);
a6eb515f 855
a6eb515f 856 // Left extension with the text
60bf98ae 857 DrawExtension (thePresentation, anExtensionSize,
858 isArrowsExternal
859 ? aFirstArrowEnd
860 : aFirstArrowBegin,
d7bffd44 861 aFirstExtensionDir,
fe83e1ea 862 aLabelString,
863 aLabelWidth,
d7bffd44 864 theMode,
865 aLabelPosition);
866
fe83e1ea 867 // add dimension line primitives
868 if (theMode == ComputeMode_All || theMode == ComputeMode_Line)
d7bffd44 869 {
fe83e1ea 870 // add central dimension line
871 Prs3d_Root::NewGroup (thePresentation);
d7bffd44 872
fe83e1ea 873 // add graphical primitives
874 Handle(Graphic3d_ArrayOfSegments) aPrimSegments = new Graphic3d_ArrayOfSegments (2);
875 aPrimSegments->AddVertex (aCenterLineBegin);
876 aPrimSegments->AddVertex (aCenterLineEnd);
d7bffd44 877
fe83e1ea 878 Prs3d_Root::CurrentGroup (thePresentation)->SetPrimitivesAspect (aDimensionAspect->LineAspect()->Aspect());
879 Prs3d_Root::CurrentGroup (thePresentation)->AddPrimitiveArray (aPrimSegments);
d7bffd44 880
fe83e1ea 881 // add selection primitives
882 SelectionGeometry::Curve& aSensitiveCurve = mySelectionGeom.NewCurve();
883 aSensitiveCurve.Append (aCenterLineBegin);
884 aSensitiveCurve.Append (aCenterLineEnd);
a6eb515f 885
fe83e1ea 886 // add arrows to presentation
887 Prs3d_Root::NewGroup (thePresentation);
a6eb515f 888
60bf98ae 889 DrawArrow (thePresentation, aFirstArrowBegin, aFirstArrowDir);
890 if (!theIsOneSide)
fe83e1ea 891 {
60bf98ae 892 DrawArrow (thePresentation, aSecondArrowBegin, aSecondArrowDir);
fe83e1ea 893 }
d7bffd44 894
60bf98ae 895 if (!isArrowsExternal || theIsOneSide)
fe83e1ea 896 {
897 break;
898 }
d7bffd44 899
fe83e1ea 900 // add extension lines for external arrows
901 Prs3d_Root::NewGroup (thePresentation);
d7bffd44 902
60bf98ae 903 DrawExtension (thePresentation, anExtensionSize,
fe83e1ea 904 aSecondArrowEnd, aSecondExtensionDir,
905 THE_EMPTY_LABEL, 0.0, theMode, LabelPosition_None);
906 }
d7bffd44 907
a6eb515f 908 break;
909 }
d7bffd44 910 // ------------------------------------------------------------------------ //
911 // RIGHT //
912 // -------------------------------------------------------------------------//
913
914 case LabelPosition_Right:
a6eb515f 915 {
d7bffd44 916 // add label on dimension or extension line to presentation
917 Prs3d_Root::NewGroup (thePresentation);
918
919 // Right extension with text
60bf98ae 920 DrawExtension (thePresentation, anExtensionSize,
921 isArrowsExternal
922 ? aSecondArrowEnd
923 : aSecondArrowBegin,
d7bffd44 924 aSecondExtensionDir,
fe83e1ea 925 aLabelString, aLabelWidth,
d7bffd44 926 theMode,
927 aLabelPosition);
928
fe83e1ea 929 if (theMode == ComputeMode_All || theMode == ComputeMode_Line)
a6eb515f 930 {
fe83e1ea 931 // add central dimension line
932 Prs3d_Root::NewGroup (thePresentation);
a6eb515f 933
fe83e1ea 934 // add graphical primitives
935 Handle(Graphic3d_ArrayOfSegments) aPrimSegments = new Graphic3d_ArrayOfSegments (2);
936 aPrimSegments->AddVertex (aCenterLineBegin);
937 aPrimSegments->AddVertex (aCenterLineEnd);
938 Prs3d_Root::CurrentGroup (thePresentation)->SetPrimitivesAspect (aDimensionAspect->LineAspect()->Aspect());
939 Prs3d_Root::CurrentGroup (thePresentation)->AddPrimitiveArray (aPrimSegments);
a6eb515f 940
fe83e1ea 941 // add selection primitives
942 SelectionGeometry::Curve& aSensitiveCurve = mySelectionGeom.NewCurve();
943 aSensitiveCurve.Append (aCenterLineBegin);
944 aSensitiveCurve.Append (aCenterLineEnd);
a6eb515f 945
fe83e1ea 946 // add arrows to presentation
947 Prs3d_Root::NewGroup (thePresentation);
d7bffd44 948
60bf98ae 949 DrawArrow (thePresentation, aSecondArrowBegin, aSecondArrowDir);
950 if (!theIsOneSide)
fe83e1ea 951 {
60bf98ae 952 DrawArrow (thePresentation, aFirstArrowBegin, aFirstArrowDir);
fe83e1ea 953 }
d7bffd44 954
60bf98ae 955 if (!isArrowsExternal || theIsOneSide)
fe83e1ea 956 {
957 break;
958 }
a6eb515f 959
fe83e1ea 960 // add extension lines for external arrows
961 Prs3d_Root::NewGroup (thePresentation);
d7bffd44 962
60bf98ae 963 DrawExtension (thePresentation, anExtensionSize,
fe83e1ea 964 aFirstArrowEnd, aFirstExtensionDir,
965 THE_EMPTY_LABEL, 0.0, theMode, LabelPosition_None);
966 }
d7bffd44 967
a6eb515f 968 break;
969 }
970 }
971
d7bffd44 972 // add flyout lines to presentation
fe83e1ea 973 if (theMode == ComputeMode_All)
d7bffd44 974 {
975 Prs3d_Root::NewGroup (thePresentation);
976
977 Handle(Graphic3d_ArrayOfSegments) aPrimSegments = new Graphic3d_ArrayOfSegments(4);
60bf98ae 978 aPrimSegments->AddVertex (theFirstPoint);
d7bffd44 979 aPrimSegments->AddVertex (aLineBegPoint);
980
60bf98ae 981 aPrimSegments->AddVertex (theSecondPoint);
d7bffd44 982 aPrimSegments->AddVertex (aLineEndPoint);
983
984 Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
985 Prs3d_Root::CurrentGroup (thePresentation)->SetPrimitivesAspect (aDimensionAspect->LineAspect()->Aspect());
986 Prs3d_Root::CurrentGroup (thePresentation)->AddPrimitiveArray (aPrimSegments);
987 }
988
60bf98ae 989 myIsComputed = Standard_True;
a6eb515f 990}
991
992//=======================================================================
60bf98ae 993//function : ComputeLinearFlyouts
994//purpose :
a6eb515f 995//=======================================================================
60bf98ae 996void AIS_Dimension::ComputeLinearFlyouts (const Handle(SelectMgr_Selection)& theSelection,
997 const Handle(SelectMgr_EntityOwner)& theOwner,
998 const gp_Pnt& theFirstPoint,
999 const gp_Pnt& theSecondPoint)
a6eb515f 1000{
60bf98ae 1001 // count flyout direction
1002 gp_Ax1 aPlaneNormal = GetPlane().Axis();
1003 gp_Dir aTargetPointsVector = gce_MakeDir (theFirstPoint, theSecondPoint);
a6eb515f 1004
60bf98ae 1005 // count a flyout direction vector.
1006 gp_Dir aFlyoutVector = aPlaneNormal.Direction() ^ aTargetPointsVector;
a6eb515f 1007
60bf98ae 1008 // create lines for layouts
1009 gp_Lin aLine1 (theFirstPoint, aFlyoutVector);
1010 gp_Lin aLine2 (theSecondPoint, aFlyoutVector);
1011
1012 // get flyout end points
1013 gp_Pnt aFlyoutEnd1 = ElCLib::Value (ElCLib::Parameter (aLine1, theFirstPoint) + GetFlyout(), aLine1);
1014 gp_Pnt aFlyoutEnd2 = ElCLib::Value (ElCLib::Parameter (aLine2, theSecondPoint) + GetFlyout(), aLine2);
1015
1016 // fill sensitive entity for flyouts
1017 Handle(Select3D_SensitiveGroup) aSensitiveEntity = new Select3D_SensitiveGroup (theOwner);
1018 aSensitiveEntity->Add (new Select3D_SensitiveSegment (theOwner, theFirstPoint, aFlyoutEnd1));
1019 aSensitiveEntity->Add (new Select3D_SensitiveSegment (theOwner, theSecondPoint, aFlyoutEnd2));
1020 theSelection->Add (aSensitiveEntity);
a6eb515f 1021}
1022
1023//=======================================================================
60bf98ae 1024//function : CircleFromPlanarFace
a6eb515f 1025//purpose : if possible computes circle from planar face
1026//=======================================================================
60bf98ae 1027Standard_Boolean AIS_Dimension::CircleFromPlanarFace (const TopoDS_Face& theFace,
a6eb515f 1028 Handle(Geom_Curve)& theCurve,
60bf98ae 1029 gp_Pnt& theFirstPoint,
1030 gp_Pnt& theLastPoint)
a6eb515f 1031{
1032 TopExp_Explorer anIt (theFace, TopAbs_EDGE);
1033 for ( ; anIt.More(); anIt.Next())
1034 {
1035 TopoDS_Edge aCurEdge = TopoDS::Edge (anIt.Current());
1036 if (AIS::ComputeGeometry (aCurEdge, theCurve, theFirstPoint, theLastPoint))
1037 {
1038 if (theCurve->IsInstance (STANDARD_TYPE(Geom_Circle)))
1039 {
1040 return Standard_True;
1041 }
1042 }
1043 }
1044 return Standard_False;
1045}
1046
1047//=======================================================================
60bf98ae 1048//function : InitCircularDimension
1049//purpose :
a6eb515f 1050//=======================================================================
60bf98ae 1051Standard_Boolean AIS_Dimension::InitCircularDimension (const TopoDS_Shape& theShape,
a6eb515f 1052 gp_Circ& theCircle,
1053 gp_Pnt& theMiddleArcPoint,
60bf98ae 1054 Standard_Boolean& theIsClosed)
a6eb515f 1055{
1056 gp_Pln aPln;
1057 Handle(Geom_Surface) aBasisSurf;
1058 AIS_KindOfSurface aSurfType = AIS_KOS_OtherSurface;
1059 gp_Pnt aFirstPoint, aLastPoint;
1060 Standard_Real anOffset = 0.0;
1061 Standard_Real aFirstParam = 0.0;
1062 Standard_Real aLastParam = 0.0;
a6eb515f 1063
60bf98ae 1064 // discover circular geometry
a6eb515f 1065 if (theShape.ShapeType() == TopAbs_FACE)
1066 {
1067 AIS::GetPlaneFromFace (TopoDS::Face (theShape), aPln, aBasisSurf, aSurfType, anOffset);
1068
1069 if (aSurfType == AIS_KOS_Plane)
1070 {
1071 Handle(Geom_Curve) aCurve;
60bf98ae 1072 if (!CircleFromPlanarFace (TopoDS::Face (theShape), aCurve, aFirstPoint, aLastPoint))
a6eb515f 1073 {
a6eb515f 1074 return Standard_False;
1075 }
1076
1077 theCircle = Handle(Geom_Circle)::DownCast (aCurve)->Circ();
a6eb515f 1078 }
1079 else
1080 {
1081 gp_Pnt aCurPos;
1082 BRepAdaptor_Surface aSurf1 (TopoDS::Face (theShape));
1083 Standard_Real aFirstU = aSurf1.FirstUParameter();
1084 Standard_Real aLastU = aSurf1.LastUParameter();
1085 Standard_Real aFirstV = aSurf1.FirstVParameter();
1086 Standard_Real aLastV = aSurf1.LastVParameter();
1087 Standard_Real aMidU = (aFirstU + aLastU) * 0.5;
1088 Standard_Real aMidV = (aFirstV + aLastV) * 0.5;
60bf98ae 1089 aSurf1.D0 (aMidU, aMidV, aCurPos);
a6eb515f 1090 Handle (Adaptor3d_HCurve) aBasisCurve;
1091 Standard_Boolean isExpectedType = Standard_False;
1092 if (aSurfType == AIS_KOS_Cylinder)
1093 {
1094 isExpectedType = Standard_True;
1095 }
1096 else
1097 {
1098 if (aSurfType == AIS_KOS_Revolution)
1099 {
1100 aBasisCurve = aSurf1.BasisCurve();
1101 if (aBasisCurve->GetType() == GeomAbs_Line)
1102 {
1103 isExpectedType = Standard_True;
1104 }
1105 }
1106 else if (aSurfType == AIS_KOS_Extrusion)
1107 {
1108 aBasisCurve = aSurf1.BasisCurve();
1109 if (aBasisCurve->GetType() == GeomAbs_Circle)
1110 {
1111 isExpectedType = Standard_True;
1112 }
1113 }
1114 }
1115
1116 if (!isExpectedType)
1117 {
a6eb515f 1118 return Standard_False;
1119 }
60bf98ae 1120
a6eb515f 1121 Handle(Geom_Curve) aCurve;
1122 aCurve = aBasisSurf->VIso(aMidV);
1123 if (aCurve->DynamicType() == STANDARD_TYPE (Geom_Circle))
1124 {
1125 theCircle = Handle(Geom_Circle)::DownCast (aCurve)->Circ();
1126 }
1127 else if (aCurve->DynamicType() == STANDARD_TYPE (Geom_TrimmedCurve))
1128 {
1129 Handle(Geom_TrimmedCurve) aTrimmedCurve = Handle(Geom_TrimmedCurve)::DownCast (aCurve);
1130 aFirstU = aTrimmedCurve->FirstParameter();
1131 aLastU = aTrimmedCurve->LastParameter();
1132 if (aTrimmedCurve->DynamicType() == STANDARD_TYPE (Geom_Circle))
1133 {
1134 theCircle = Handle(Geom_Circle)::DownCast(aTrimmedCurve)->Circ();
1135 }
1136 }
1137 else
1138 {
1139 // Compute a circle from 3 points on "aCurve"
1140 gp_Pnt aP1, aP2;
1141 aSurf1.D0 (aFirstU, aMidV, aP1);
1142 aSurf1.D0 (aLastU, aMidV, aP2);
1143 GC_MakeCircle aMkCirc (aP1, aCurPos, aP2);
1144 theCircle = aMkCirc.Value()->Circ();
1145 }
1146
a6eb515f 1147 aFirstPoint = ElCLib::Value (aFirstU, theCircle);
1148 aLastPoint = ElCLib::Value (aLastU, theCircle);
1149 }
1150 }
1151 else // TopAbs_EDGE | TopAbs_WIRE
1152 {
1153 TopoDS_Edge anEdge;
1154 if (theShape.ShapeType() == TopAbs_WIRE)
1155 {
1156 TopExp_Explorer anIt (theShape, TopAbs_EDGE);
1157 if (anIt.More())
1158 {
1159 anEdge = TopoDS::Edge (anIt.Current());
1160 }
1161 }
1162 else if (theShape.ShapeType() == TopAbs_EDGE)
1163 {
1164 anEdge = TopoDS::Edge (theShape);
1165 }
1166 else // Unexpected type of shape
1167 {
a6eb515f 1168 return Standard_False;
1169 }
60bf98ae 1170
a6eb515f 1171 BRepAdaptor_Curve anAdaptedCurve (anEdge);
1172 if (!anAdaptedCurve.GetType() == GeomAbs_Circle)
1173 {
1174 return Standard_False;
1175 }
60bf98ae 1176
1177 theCircle = anAdaptedCurve.Circle();
a6eb515f 1178 aFirstPoint = anAdaptedCurve.Value (anAdaptedCurve.FirstParameter());
60bf98ae 1179 aLastPoint = anAdaptedCurve.Value (anAdaptedCurve.LastParameter());
a6eb515f 1180 }
60bf98ae 1181
1182 theIsClosed = aFirstPoint.IsEqual (aLastPoint, Precision::Confusion());
1183
a6eb515f 1184 gp_Pnt aCenter = theCircle.Location();
60bf98ae 1185
1186 if (theIsClosed) // Circle
a6eb515f 1187 {
a6eb515f 1188 gp_Dir anXDir = theCircle.XAxis().Direction();
1189 theMiddleArcPoint = aCenter.Translated (gp_Vec (anXDir) * theCircle.Radius());
a6eb515f 1190 }
60bf98ae 1191 else // Arc
a6eb515f 1192 {
a6eb515f 1193 aFirstParam = ElCLib::Parameter (theCircle, aFirstPoint);
1194 aLastParam = ElCLib::Parameter (theCircle, aLastPoint);
1195 if (aFirstParam > aLastParam)
1196 {
1197 aFirstParam -= 2.0 * M_PI;
1198 }
60bf98ae 1199
a6eb515f 1200 Standard_Real aParCurPos = (aFirstParam + aLastParam) * 0.5;
1201 gp_Vec aVec = gp_Vec (aCenter, ElCLib::Value (aParCurPos, theCircle)).Normalized () * theCircle.Radius ();
1202 theMiddleArcPoint = aCenter.Translated (aVec);
a6eb515f 1203 }
1204
1205 return Standard_True;
1206}
1207
1208//=======================================================================
a6eb515f 1209//function : ComputeSelection
1210//purpose :
1211//=======================================================================
a6eb515f 1212void AIS_Dimension::ComputeSelection (const Handle(SelectMgr_Selection)& theSelection,
1213 const Standard_Integer theMode)
1214{
60bf98ae 1215 if (!myIsComputed)
a6eb515f 1216 {
1217 return;
1218 }
1219
fe83e1ea 1220 AIS_DimensionSelectionMode aSelectionMode = (AIS_DimensionSelectionMode)theMode;
a6eb515f 1221
fe83e1ea 1222 // init appropriate entity owner
1223 Handle(SelectMgr_EntityOwner) aSensitiveOwner;
a6eb515f 1224
fe83e1ea 1225 switch (aSelectionMode)
a6eb515f 1226 {
fe83e1ea 1227 // neutral selection owner
1228 case AIS_DSM_All :
1229 aSensitiveOwner = new SelectMgr_EntityOwner (this, THE_NEUTRAL_SEL_PRIORITY);
1230 break;
1231
1232 // local selection owners
1233 case AIS_DSM_Line :
1234 case AIS_DSM_Text :
1235 aSensitiveOwner = new AIS_DimensionOwner (this, aSelectionMode, THE_LOCAL_SEL_PRIORITY);
1236 break;
a6eb515f 1237 }
fe83e1ea 1238
1239 if (aSelectionMode == AIS_DSM_All || aSelectionMode == AIS_DSM_Line)
a6eb515f 1240 {
fe83e1ea 1241 // sensitives for dimension line segments
1242 Handle(Select3D_SensitiveGroup) aGroupOfSensitives = new Select3D_SensitiveGroup (aSensitiveOwner);
1243
1244 SelectionGeometry::SeqOfCurves::Iterator aCurveIt (mySelectionGeom.DimensionLine);
1245 for (; aCurveIt.More(); aCurveIt.Next())
1246 {
1247 const SelectionGeometry::HCurve& aCurveData = aCurveIt.Value();
1248
1249 TColgp_Array1OfPnt aSensitivePnts (1, aCurveData->Length());
1250 for (Standard_Integer aPntIt = 1; aPntIt <= aCurveData->Length(); ++aPntIt)
1251 {
1252 aSensitivePnts.ChangeValue (aPntIt) = aCurveData->Value (aPntIt);
1253 }
1254
1255 aGroupOfSensitives->Add (new Select3D_SensitiveCurve (aSensitiveOwner, aSensitivePnts));
1256 }
1257
1258 Quantity_Length anArrowLength = myDrawer->DimensionAspect()->ArrowAspect()->Length();
1259 Standard_Real anArrowAngle = myDrawer->DimensionAspect()->ArrowAspect()->Angle();
1260
1261 // sensitives for arrows
1262 SelectionGeometry::SeqOfArrows::Iterator anArrowIt (mySelectionGeom.Arrows);
1263 for (; anArrowIt.More(); anArrowIt.Next())
1264 {
1265 const SelectionGeometry::HArrow& anArrow = anArrowIt.Value();
1266
1267 gp_Pnt aSidePnt1 (gp::Origin());
1268 gp_Pnt aSidePnt2 (gp::Origin());
60bf98ae 1269 const gp_Dir& aPlane = GetPlane().Axis().Direction();
fe83e1ea 1270 const gp_Pnt& aPeak = anArrow->Position;
1271 const gp_Dir& aDir = anArrow->Direction;
1272
1273 // compute points for arrow in plane
1274 PointsForArrow (aPeak, aDir, aPlane, anArrowLength, anArrowAngle, aSidePnt1, aSidePnt2);
1275
1276 aGroupOfSensitives->Add (new Select3D_SensitiveTriangle (aSensitiveOwner, aPeak, aSidePnt1, aSidePnt2));
1277
1278 if (!myDrawer->DimensionAspect()->IsArrows3d())
1279 {
1280 continue;
1281 }
1282
1283 // compute points for orthogonal sensitive plane
1284 gp_Dir anOrthoPlane = anArrow->Direction.Crossed (aPlane);
1285
1286 PointsForArrow (aPeak, aDir, anOrthoPlane, anArrowLength, anArrowAngle, aSidePnt1, aSidePnt2);
1287
1288 aGroupOfSensitives->Add (new Select3D_SensitiveTriangle (aSensitiveOwner, aPeak, aSidePnt1, aSidePnt2));
1289 }
1290
1291 theSelection->Add (aGroupOfSensitives);
a6eb515f 1292 }
fe83e1ea 1293
1294 // sensitives for text element
1295 if (aSelectionMode == AIS_DSM_All || aSelectionMode == AIS_DSM_Text)
a6eb515f 1296 {
fe83e1ea 1297 Handle(Select3D_SensitiveEntity) aTextSensitive;
1298
1299 gp_Ax2 aTextAxes (mySelectionGeom.TextPos,
60bf98ae 1300 GetPlane().Axis().Direction(),
fe83e1ea 1301 mySelectionGeom.TextDir);
1302
1303 if (myDrawer->DimensionAspect()->IsText3d())
1304 {
1305 // sensitive planar rectangle for text
1306 Standard_Real aDx = mySelectionGeom.TextWidth * 0.5;
1307 Standard_Real aDy = mySelectionGeom.TextHeight * 0.5;
1308
1309 gp_Trsf aLabelPlane;
1310 aLabelPlane.SetTransformation (aTextAxes, gp::XOY());
1311
51f8f60c 1312 TColgp_Array1OfPnt aRectanglePoints(1, 4);
1313 aRectanglePoints.ChangeValue(1) = gp_Pnt (-aDx, -aDy, 0.0).Transformed (aLabelPlane);
1314 aRectanglePoints.ChangeValue(2) = gp_Pnt (-aDx, aDy, 0.0).Transformed (aLabelPlane);
1315 aRectanglePoints.ChangeValue(3) = gp_Pnt ( aDx, aDy, 0.0).Transformed (aLabelPlane);
1316 aRectanglePoints.ChangeValue(4) = gp_Pnt ( aDx, -aDy, 0.0).Transformed (aLabelPlane);
fe83e1ea 1317
51f8f60c 1318 Poly_Array1OfTriangle aTriangles(1, 2);
1319 aTriangles.ChangeValue(1) = Poly_Triangle(1, 2, 3);
1320 aTriangles.ChangeValue(2) = Poly_Triangle(1, 3, 4);
1321
1322 Handle(Poly_Triangulation) aRectanglePoly =
1323 new Poly_Triangulation(aRectanglePoints, aTriangles);
1324
1325 aTextSensitive =
1326 new Select3D_SensitiveTriangulation (aSensitiveOwner, aRectanglePoly, TopLoc_Location(), Standard_True);
fe83e1ea 1327 }
1328 else
1329 {
1330 gp_Circ aTextGeom (aTextAxes, mySelToleranceForText2d != 0.0
1331 ? mySelToleranceForText2d : 1.0);
1332
1333 Handle(Geom_Circle) aSensGeom = new Geom_Circle (aTextGeom);
1334
1335 aTextSensitive = new Select3D_SensitiveCircle (aSensitiveOwner, aSensGeom, Standard_True);
1336 }
1337
1338 theSelection->Add (aTextSensitive);
a6eb515f 1339 }
fe83e1ea 1340
1341 // callback for flyout sensitive calculation
1342 if (aSelectionMode == AIS_DSM_All)
d7bffd44 1343 {
60bf98ae 1344 ComputeFlyoutSelection (theSelection, aSensitiveOwner);
d7bffd44 1345 }
fe83e1ea 1346}
1347
1348//=======================================================================
1349//function : PointsForArrow
1350//purpose :
1351//=======================================================================
1352void AIS_Dimension::PointsForArrow (const gp_Pnt& thePeakPnt,
1353 const gp_Dir& theDirection,
1354 const gp_Dir& thePlane,
1355 const Standard_Real theArrowLength,
1356 const Standard_Real theArrowAngle,
1357 gp_Pnt& theSidePnt1,
1358 gp_Pnt& theSidePnt2)
1359{
1360 gp_Lin anArrowLin (thePeakPnt, theDirection.Reversed());
1361 gp_Pnt anArrowEnd = ElCLib::Value (theArrowLength, anArrowLin);
1362 gp_Lin anEdgeLin (anArrowEnd, theDirection.Crossed (thePlane));
1363
1364 Standard_Real anEdgeLength = Tan (theArrowAngle) * theArrowLength;
a6eb515f 1365
fe83e1ea 1366 theSidePnt1 = ElCLib::Value ( anEdgeLength, anEdgeLin);
1367 theSidePnt2 = ElCLib::Value (-anEdgeLength, anEdgeLin);
a6eb515f 1368}