0024448: Possible copy-paste bug in IGESGeom_SplineCurve.cxx
[occt.git] / src / AIS / AIS_AngleDimension.cxx
CommitLineData
b311480e 1// Created on: 1996-12-05
2// Created by: Arnaud BOUZY/Odile Olivier
3// Copyright (c) 1996-1999 Matra Datavision
4// Copyright (c) 1999-2012 OPEN CASCADE SAS
5//
6// The content of this file is subject to the Open CASCADE Technology Public
7// License Version 6.5 (the "License"). You may not use the content of this file
8// except in compliance with the License. Please obtain a copy of the License
9// at http://www.opencascade.org and read it completely before using this file.
10//
11// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
12// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
13//
14// The Original Code and all software distributed under the License is
15// distributed on an "AS IS" basis, without warranty of any kind, and the
16// Initial Developer hereby disclaims all such warranties, including without
17// limitation, any warranties of merchantability, fitness for a particular
18// purpose or non-infringement. Please see the License for the specific terms
19// and conditions governing the rights and limitations under the License.
20
a6eb515f 21#include <AIS_AngleDimension.hxx>
7fd59977 22
23#include <AIS.hxx>
7fd59977 24#include <AIS_Drawer.hxx>
7fd59977 25#include <BRepBuilderAPI_MakeFace.hxx>
26#include <BRepAdaptor_Curve.hxx>
27#include <BRepAdaptor_Surface.hxx>
7fd59977 28#include <ElCLib.hxx>
a6eb515f 29#include <gce_MakeLin2d.hxx>
a6eb515f 30#include <gce_MakeCone.hxx>
fe83e1ea 31#include <gce_MakePln.hxx>
32#include <gce_MakeCirc.hxx>
33#include <gce_MakeDir.hxx>
34#include <GC_MakeArcOfCircle.hxx>
35#include <GCPnts_UniformAbscissa.hxx>
36#include <Geom_TrimmedCurve.hxx>
7fd59977 37#include <Geom_Circle.hxx>
7fd59977 38#include <Geom_ConicalSurface.hxx>
39#include <Geom_SurfaceOfRevolution.hxx>
7fd59977 40#include <Geom_OffsetSurface.hxx>
a6eb515f 41#include <Graphic3d_ArrayOfSegments.hxx>
a6eb515f 42#include <Graphic3d_Group.hxx>
a6eb515f 43#include <Graphic3d_ArrayOfPolylines.hxx>
7fd59977 44#include <IntAna2d_AnaIntersection.hxx>
45#include <IntAna2d_IntPoint.hxx>
7fd59977 46#include <IntAna_ResultType.hxx>
7fd59977 47#include <ProjLib.hxx>
a6eb515f 48#include <Prs3d_Root.hxx>
d7bffd44 49#include <Prs3d_ShadingAspect.hxx>
a6eb515f 50#include <PrsMgr_PresentationManager3d.hxx>
7fd59977 51#include <Select3D_SensitiveCurve.hxx>
62b6361a 52#include <Select3D_SensitiveGroup.hxx>
7fd59977 53#include <Select3D_SensitiveSegment.hxx>
a6eb515f 54#include <SelectMgr_Selection.hxx>
7fd59977 55#include <UnitsAPI.hxx>
56
a6eb515f 57IMPLEMENT_STANDARD_HANDLE (AIS_AngleDimension, AIS_Dimension)
58IMPLEMENT_STANDARD_RTTIEXT (AIS_AngleDimension, AIS_Dimension)
7fd59977 59
d7bffd44 60namespace
61{
fe83e1ea 62 static const TCollection_ExtendedString THE_EMPTY_LABEL_STRING;
63 static const Standard_Real THE_EMPTY_LABEL_WIDTH = 0.0;
64 static const Standard_ExtCharacter THE_DEGREE_SYMBOL (0x00B0);
65 static const Standard_Real THE_3D_TEXT_MARGIN = 0.1;
d7bffd44 66};
67
7fd59977 68//=======================================================================
a6eb515f 69//function : init
70//purpose : Private constructor for default initialization
7fd59977 71//=======================================================================
a6eb515f 72void AIS_AngleDimension::init()
7fd59977 73{
a6eb515f 74 // Default values of units
75 UnitsAPI::SetLocalSystem (UnitsAPI_SI);
76 SetUnitsQuantity ("PLANE ANGLE");
77 SetModelUnits ("rad");
78 SetDisplayUnits ("deg");
d7bffd44 79 SetSpecialSymbol (THE_DEGREE_SYMBOL);
a6eb515f 80 SetDisplaySpecialSymbol (AIS_DSS_After);
d7bffd44 81 SetFlyout (15.0);
82 SetKindOfDimension (AIS_KOD_PLANEANGLE);
a6eb515f 83 MakeUnitsDisplayed (Standard_False);
7fd59977 84}
85
86//=======================================================================
87//function : Constructor
a6eb515f 88//purpose : Two edges dimension
7fd59977 89//=======================================================================
a6eb515f 90AIS_AngleDimension::AIS_AngleDimension (const TopoDS_Edge& theFirstEdge,
91 const TopoDS_Edge& theSecondEdge)
92: AIS_Dimension(),
62b6361a 93 myIsFlyoutLines (Standard_True)
7fd59977 94{
a6eb515f 95 init();
96 myShapesNumber = 2;
d7bffd44 97 myFirstShape = theFirstEdge;
98 mySecondShape = theSecondEdge;
7fd59977 99}
100
7fd59977 101//=======================================================================
102//function : Constructor
a6eb515f 103//purpose : Two edges dimension
104// <thePlane> is used in case of Angle=PI
7fd59977 105//=======================================================================
a6eb515f 106AIS_AngleDimension::AIS_AngleDimension (const TopoDS_Edge& theFirstEdge,
107 const TopoDS_Edge& theSecondEdge,
108 const gp_Pln& thePlane)
109: AIS_Dimension(),
62b6361a 110 myIsFlyoutLines (Standard_True)
7fd59977 111{
a6eb515f 112 init();
113 myShapesNumber = 2;
d7bffd44 114 myFirstShape = theFirstEdge;
115 mySecondShape = theSecondEdge;
a6eb515f 116 SetWorkingPlane (thePlane);
7fd59977 117}
118
119//=======================================================================
120//function : Constructor
a6eb515f 121//purpose : Three points dimension
7fd59977 122//=======================================================================
a6eb515f 123AIS_AngleDimension::AIS_AngleDimension (const gp_Pnt& theFirstPoint,
124 const gp_Pnt& theSecondPoint,
125 const gp_Pnt& theThirdPoint)
126: AIS_Dimension(),
62b6361a 127 myIsFlyoutLines (Standard_True)
7fd59977 128{
a6eb515f 129 init();
130 myIsInitialized = Standard_True;
d7bffd44 131 myFirstPoint = theFirstPoint;
132 myCenter = theSecondPoint;
133 mySecondPoint = theThirdPoint;
134 myShapesNumber = 3;
7fd59977 135}
136
7fd59977 137//=======================================================================
a6eb515f 138//function : Constructor
139//purpose : Cone dimension
7fd59977 140//=======================================================================
a6eb515f 141AIS_AngleDimension::AIS_AngleDimension (const TopoDS_Face& theCone)
142: AIS_Dimension(),
62b6361a 143 myIsFlyoutLines (Standard_True)
7fd59977 144{
a6eb515f 145 init();
146 myIsInitialized = Standard_False;
d7bffd44 147 myFirstShape = theCone;
148 myShapesNumber = 1;
7fd59977 149}
150
151//=======================================================================
a6eb515f 152//function : Constructor
153//purpose : Two faces dimension
7fd59977 154//=======================================================================
a6eb515f 155AIS_AngleDimension::AIS_AngleDimension (const TopoDS_Face& theFirstFace,
156 const TopoDS_Face& theSecondFace,
157 const gp_Ax1& theAxis)
158: AIS_Dimension(),
62b6361a 159 myIsFlyoutLines (Standard_True)
7fd59977 160{
a6eb515f 161 init();
162 myIsInitialized = Standard_False;
d7bffd44 163 myFirstShape = theFirstFace;
164 mySecondShape = theSecondFace;
165 myShapesNumber = 2;
a6eb515f 166 gp_Pln aPlane;
167 aPlane.SetAxis (theAxis);
168 SetWorkingPlane (aPlane);
7fd59977 169}
170
7fd59977 171//=======================================================================
a6eb515f 172//function : SetFirstShape
7fd59977 173//purpose :
174//=======================================================================
a6eb515f 175void AIS_AngleDimension::SetFirstShape (const TopoDS_Shape& theShape,
176 const Standard_Boolean isSingleShape /*= Standard_False*/)
7fd59977 177{
a6eb515f 178 AIS_Dimension::SetFirstShape (theShape);
179 if (isSingleShape)
180 myShapesNumber = 1;
7fd59977 181}
182
7fd59977 183//=======================================================================
a6eb515f 184//function : aboveInBelowCone
185//purpose : Returns 1 if <theC> center is above of <theCMin> center;
186// 0 if <theC> center is between <theCMin> and
187// <theCMax> centers;
188// -1 if <theC> center is below <theCMax> center.
7fd59977 189//=======================================================================
a6eb515f 190Standard_Integer AIS_AngleDimension::aboveInBelowCone (const gp_Circ &theCMax,
191 const gp_Circ &theCMin,
192 const gp_Circ &theC)
7fd59977 193{
a6eb515f 194 const Standard_Real aD = theCMax.Location().Distance (theCMin.Location());
195 const Standard_Real aD1 = theCMax.Location().Distance (theC.Location());
196 const Standard_Real aD2 = theCMin.Location().Distance (theC.Location());
197
198 if (aD >= aD1 && aD >= aD2) return 0;
199 if (aD < aD2 && aD1 < aD2) return -1;
200 if (aD < aD1 && aD2 < aD1) return 1;
201 return 0;
7fd59977 202}
203
204//=======================================================================
a6eb515f 205//function : initConeAngle
206//purpose : initialization of the cone angle
7fd59977 207//=======================================================================
a6eb515f 208Standard_Boolean AIS_AngleDimension::initConeAngle (const TopoDS_Face& theCone)
7fd59977 209{
a6eb515f 210 if (theCone.IsNull ())
211 return Standard_False;
7fd59977 212
a6eb515f 213 gp_Pln aPln;
214 gp_Cone aCone;
215 gp_Circ aCircle;
216 // A surface from the Face
217 Handle(Geom_Surface) aSurf;
218 Handle(Geom_OffsetSurface) aOffsetSurf;
219 Handle(Geom_ConicalSurface) aConicalSurf;
220 Handle(Geom_SurfaceOfRevolution) aRevSurf;
221 Handle(Geom_Line) aLine;
222 BRepAdaptor_Surface aConeAdaptor (theCone);
223 TopoDS_Face aFace;
224 AIS_KindOfSurface aSurfType;
225 Standard_Real anOffset = 0.;
226 Handle(Standard_Type) aType;
7fd59977 227
a6eb515f 228 Standard_Real aMaxV = aConeAdaptor.FirstVParameter();
229 Standard_Real aMinV = aConeAdaptor.LastVParameter();
7fd59977 230
a6eb515f 231 AIS::GetPlaneFromFace(theCone, aPln, aSurf, aSurfType, anOffset);
7fd59977 232
a6eb515f 233 if (aSurfType == AIS_KOS_Revolution)
234 {
235 // Surface of revolution
236 aRevSurf = Handle(Geom_SurfaceOfRevolution)::DownCast(aSurf);
237 gp_Lin aLin (aRevSurf->Axis());
238 Handle(Geom_Curve) aBasisCurve = aRevSurf->BasisCurve();
239 //Must be a part of line (basis curve should be linear)
240 if (aBasisCurve ->DynamicType() != STANDARD_TYPE(Geom_Line))
241 return Standard_False;
242
243 gp_Pnt aFirst1 = aConeAdaptor.Value (0., aMinV);
244 gp_Pnt aLast1 = aConeAdaptor.Value (0., aMaxV);
245 gp_Vec aVec1 (aFirst1, aLast1);
246
247 //Projection <aFirst> on <aLin>
248 gp_Pnt aFirst2 = ElCLib::Value (ElCLib::Parameter (aLin, aFirst1), aLin);
249 // Projection <aLast> on <aLin>
250 gp_Pnt aLast2 = ElCLib::Value (ElCLib::Parameter (aLin, aLast1), aLin);
251
252 gp_Vec aVec2 (aFirst2, aLast2);
253
254 // Check if two parts of revolution are parallel (it's a cylinder) or normal (it's a circle).
255 if (aVec1.IsParallel (aVec2, Precision::Angular())
256 || aVec1.IsNormal (aVec2,Precision::Angular()))
257 return Standard_False;
258
259 gce_MakeCone aMkCone (aRevSurf->Axis(), aFirst1, aLast1);
260 aCone = aMkCone.Value();
261 myCenter = aCone.Apex();
262 }
263 else
264 {
265 aType = aSurf->DynamicType();
266 if (aType == STANDARD_TYPE(Geom_OffsetSurface) || anOffset > 0.01)
7fd59977 267 {
a6eb515f 268 // Offset surface
269 aOffsetSurf = new Geom_OffsetSurface (aSurf, anOffset);
270 aSurf = aOffsetSurf->Surface();
271 BRepBuilderAPI_MakeFace aMkFace(aSurf, Precision::Confusion());
272 aMkFace.Build();
273 if (!aMkFace.IsDone())
274 return Standard_False;
275 aConeAdaptor.Initialize (aMkFace.Face());
7fd59977 276 }
a6eb515f 277 aCone = aConeAdaptor.Cone();
278 aConicalSurf = Handle(Geom_ConicalSurface)::DownCast (aSurf);
279 myCenter = aConicalSurf->Apex();
7fd59977 280 }
7fd59977 281
a6eb515f 282 // A circle where the angle is drawn
283 Handle(Geom_Curve) aCurve;
284 Standard_Real aMidV = ( aMinV + aMaxV ) / 2.5;
285 aCurve = aSurf->VIso (aMidV);
286 aCircle = Handle(Geom_Circle)::DownCast (aCurve)->Circ();
7fd59977 287
a6eb515f 288 aCurve = aSurf->VIso(aMaxV);
289 gp_Circ aCircVmax = Handle(Geom_Circle)::DownCast(aCurve)->Circ();
290 aCurve = aSurf->VIso(aMinV);
291 gp_Circ aCircVmin = Handle(Geom_Circle)::DownCast(aCurve)->Circ();
7fd59977 292
7fd59977 293
a6eb515f 294 if (aCircVmax.Radius() < aCircVmin.Radius())
295 {
296 gp_Circ aTmpCirc = aCircVmax;
297 aCircVmax = aCircVmin;
298 aCircVmin = aTmpCirc;
299 }
7fd59977 300
a6eb515f 301 myFirstPoint = ElCLib::Value (0, aCircle);
302 mySecondPoint = ElCLib::Value (M_PI, aCircle);
303 return Standard_True;
7fd59977 304}
305
306//=======================================================================
a6eb515f 307//function : initTwoFacesAngle
308//purpose : initialization of angle dimension between two faces
7fd59977 309//=======================================================================
a6eb515f 310Standard_Boolean AIS_AngleDimension::initTwoFacesAngle ()
7fd59977 311{
a6eb515f 312 TopoDS_Face aFirstFace = TopoDS::Face (myFirstShape);
313 TopoDS_Face aSecondFace = TopoDS::Face (mySecondShape);
314 gp_Dir aFirstDir, aSecondDir;
315 gp_Pln aFirstPlane, aSecondPlane;
fe83e1ea 316 gp_Pnt aTextPos;
a6eb515f 317 Handle(Geom_Surface) aFirstBasisSurf, aSecondBasisSurf;
318 AIS_KindOfSurface aFirstSurfType, aSecondSurfType;
319 Standard_Real aFirstOffset, aSecondOffset;
7fd59977 320
a6eb515f 321 AIS::GetPlaneFromFace (aFirstFace, aFirstPlane,
322 aFirstBasisSurf,aFirstSurfType,aFirstOffset);
323 AIS::GetPlaneFromFace (aSecondFace, aSecondPlane,
324 aSecondBasisSurf, aSecondSurfType, aSecondOffset);
325
326 if (aFirstSurfType == AIS_KOS_Plane)
327 {
328 //Planar faces angle
329 AIS::ComputeAngleBetweenPlanarFaces (aFirstFace,
330 aSecondFace,
331 aSecondBasisSurf,
332 GetWorkingPlane().Axis(),
333 myValue,
334 Standard_True,
fe83e1ea 335 aTextPos,
a6eb515f 336 myCenter,
337 myFirstPoint,
338 mySecondPoint,
339 aFirstDir,
340 aSecondDir);
7fd59977 341 }
a6eb515f 342 else
343 {
344 // Curvilinear faces angle
345 Handle(Geom_Plane) aPlane = new Geom_Plane (GetWorkingPlane());
346 AIS::ComputeAngleBetweenCurvilinearFaces (aFirstFace,
347 aSecondFace,
348 aFirstBasisSurf,
349 aSecondBasisSurf,
350 aFirstSurfType,
351 aSecondSurfType,
352 GetWorkingPlane().Axis(),
353 myValue,
354 Standard_True,
fe83e1ea 355 aTextPos,
a6eb515f 356 myCenter,
357 myFirstPoint,
358 mySecondPoint,
359 aFirstDir,
360 aSecondDir,
361 aPlane);
362 SetWorkingPlane (aPlane->Pln());
7fd59977 363 }
a6eb515f 364 return Standard_True;
7fd59977 365}
366
7fd59977 367//=======================================================================
a6eb515f 368//function : countDefaultPlane
7fd59977 369//purpose :
370//=======================================================================
a6eb515f 371void AIS_AngleDimension::countDefaultPlane ()
7fd59977 372{
a6eb515f 373 if (!myIsInitialized)
374 return;
375 // Compute normal of the default plane.
376 gp_Vec aVec1(myCenter, myFirstPoint),
377 aVec2(myCenter, mySecondPoint);
378 myDefaultPlane = gp_Pln(myCenter, aVec1^aVec2);
379 // Set computed value to <myWorkingPlane>
380 ResetWorkingPlane ();
7fd59977 381}
382
383//=======================================================================
a6eb515f 384//function : computeValue
7fd59977 385//purpose :
386//=======================================================================
a6eb515f 387void AIS_AngleDimension::computeValue ()
7fd59977 388{
a6eb515f 389 gp_Vec aVec1 (myCenter, myFirstPoint),
390 aVec2 (myCenter, mySecondPoint);
391 myValue = aVec1.Angle (aVec2);
392 // To model units
393 AIS_Dimension::computeValue();
7fd59977 394}
395
7fd59977 396//=======================================================================
a6eb515f 397//function : initTwoEdgesAngle
398//purpose : Fill gp_Pnt fields for further presentation computation
399// If intersection between two edges doesn't exist
400// <myIsInitialized> is set to false
7fd59977 401//=======================================================================
a6eb515f 402Standard_Boolean AIS_AngleDimension::initTwoEdgesAngle ()
7fd59977 403{
a6eb515f 404 // Data initialization
405 TopoDS_Edge aFirstEdge = TopoDS::Edge (myFirstShape);
406 TopoDS_Edge aSecondEdge = TopoDS::Edge (mySecondShape);
407 BRepAdaptor_Curve aMakeFirstLine (aFirstEdge);
408 BRepAdaptor_Curve aMakeSecondLine (aSecondEdge);
7fd59977 409
a6eb515f 410 if (aMakeFirstLine.GetType() != GeomAbs_Line || aMakeSecondLine.GetType() != GeomAbs_Line)
411 {
412 return Standard_False;
7fd59977 413 }
414
a6eb515f 415 Handle(Geom_Line) aFirstLine = new Geom_Line (aMakeFirstLine.Line());
416 Handle(Geom_Line) aSecondLine = new Geom_Line (aMakeSecondLine.Line());
7fd59977 417
a6eb515f 418 gp_Lin aFirstLin = aFirstLine->Lin ();
419 gp_Lin aSecondLin = aSecondLine->Lin ();
420 gp_Lin2d aFirstLin2d, aSecondLin2d;
421 Standard_Boolean isParallelLines = aFirstLin.Direction().IsParallel (aSecondLin.Direction(), Precision::Angular());
422 Standard_Boolean isSameLines = isParallelLines && aFirstLin.Distance (aSecondLin.Location()) <= Precision::Confusion();
423 // In case where we can't compute plane automatically
424 if ((isParallelLines || isSameLines) && !myIsWorkingPlaneCustom)
425 {
426 return Standard_False;
7fd59977 427 }
428
a6eb515f 429 gp_Pln aPlane;
7fd59977 430
a6eb515f 431 /// PART 1 is for automatic plane computation from two edges if it is possible
432 // Build plane
433 if (!myIsWorkingPlaneCustom)
434 {
435 gp_Pnt aPoint = aFirstLine->Value (0.);
436 gp_Dir aNormal = isParallelLines
437 ? gp_Vec(aSecondLin.Normal (aPoint).Direction()) ^ gp_Vec (aSecondLin.Direction())
438 : gp_Vec (aFirstLin.Direction()) ^ gp_Vec (aSecondLin.Direction());
439 aPlane = gp_Pln (aPoint, aNormal);
440 resetWorkingPlane (aPlane);
7fd59977 441 }
a6eb515f 442 else
443 {
444 aPlane = GetWorkingPlane();
7fd59977 445 }
446
a6eb515f 447 // Compute geometry for this plane and edges
448 Standard_Boolean isInfinite1,isInfinite2;
449 gp_Pnt aFirstPoint1, aLastPoint1, aFirstPoint2, aLastPoint2;
450 Standard_Integer anExtIndex = -1;
451 Handle(Geom_Curve) anExtCurve;
452 Handle(Geom_Plane) aGeomPlane = new Geom_Plane (aPlane);
453 if (!AIS::ComputeGeometry (aFirstEdge, aSecondEdge,
454 anExtIndex,
455 aFirstLine, aSecondLine,
456 aFirstPoint1, aLastPoint1,
457 aFirstPoint2, aLastPoint2,
458 anExtCurve,
459 isInfinite1, isInfinite2,
460 aGeomPlane))
461 {
462 return Standard_False;
7fd59977 463 }
464
a6eb515f 465 // Check if both edges are on this plane
466 if (!anExtCurve.IsNull())
467 {
468 if (anExtIndex == 1) // First curve is out of the plane
469 {
470 // Project curve on the plane
471 if (myIsWorkingPlaneCustom)
472 {
473 aFirstLin2d = ProjLib::Project (aPlane, aFirstLin);
474 aFirstLin = ElCLib::To3d (aPlane.Position().Ax2(), aFirstLin2d);
7fd59977 475 }
a6eb515f 476 else
477 {
478 aFirstLin.Translate (gp_Vec (aFirstLin.Location(), aSecondLin.Location()));
7fd59977 479 }
7fd59977 480
a6eb515f 481 aFirstLine = new Geom_Line (aFirstLin);
7fd59977 482 }
a6eb515f 483 else if (anExtIndex == 2) // Second curve is out of the plane
484 {
485 if (myIsWorkingPlaneCustom)
486 {
487 aSecondLin2d = ProjLib::Project (aPlane, aSecondLin);
488 aSecondLin = ElCLib::To3d (aPlane.Position().Ax2(), aSecondLin2d);
7fd59977 489 }
a6eb515f 490 else
491 {
492 aSecondLin.Translate (gp_Vec (aSecondLin.Location(), aFirstLin.Location()));
7fd59977 493 }
a6eb515f 494
495 aSecondLine = new Geom_Line (aSecondLin);
7fd59977 496 }
497 }
498
a6eb515f 499 /// PART 2 is for dimension computation using the working plane
7fd59977 500
a6eb515f 501 if (aFirstLin.Direction ().IsParallel (aSecondLin.Direction (), Precision::Angular ()))
502 {
503 // Parallel lines
504 isSameLines = aFirstLin.Distance(aSecondLin.Location()) <= Precision::Confusion();
505 if (!isSameLines)
506 return Standard_False;
507
508 myFirstPoint = aFirstLin.Location();
509 mySecondPoint = ElCLib::Value (ElCLib::Parameter (aFirstLin, myFirstPoint), aSecondLin);
510 if (mySecondPoint.Distance (mySecondPoint) <= Precision::Confusion ())
511 mySecondPoint.Translate (gp_Vec (aSecondLin.Direction ())*Abs(GetFlyout()));
512 myCenter.SetXYZ( (myFirstPoint.XYZ() + mySecondPoint.XYZ()) / 2. );
513 }
514 else
515 {
516 // Find intersection
517 aFirstLin2d = ProjLib::Project (aPlane, aFirstLin);
518 aSecondLin2d = ProjLib::Project (aPlane, aSecondLin);
7fd59977 519
a6eb515f 520 IntAna2d_AnaIntersection anInt2d (aFirstLin2d, aSecondLin2d);
521 gp_Pnt2d anIntersectPoint;
522 if (!anInt2d.IsDone() || anInt2d.IsEmpty())
7fd59977 523 {
a6eb515f 524 return Standard_False;
7fd59977 525 }
526
a6eb515f 527 anIntersectPoint = gp_Pnt2d (anInt2d.Point(1).Value());
528 myCenter = ElCLib::To3d(aPlane.Position().Ax2(), anIntersectPoint);
7fd59977 529
a6eb515f 530 if (isInfinite1 || isInfinite2)
7fd59977 531 {
a6eb515f 532 myFirstPoint = myCenter.Translated (gp_Vec (aFirstLin.Direction())*Abs (GetFlyout()));
533 mySecondPoint = myCenter.Translated (gp_Vec (aSecondLin.Direction())*Abs (GetFlyout()));
534 return Standard_True;
7fd59977 535 }
536
a6eb515f 537 // |
538 // | <- dimension should be here
539 // *----
540 myFirstPoint = myCenter.Distance (aFirstPoint1) > myCenter.Distance (aLastPoint1) ? aFirstPoint1 : aLastPoint1;
541 mySecondPoint = myCenter.Distance (aFirstPoint2) > myCenter.Distance (aLastPoint2) ? aFirstPoint2 : aLastPoint2;
542 }
543 return Standard_True;
7fd59977 544}
545
546//=======================================================================
a6eb515f 547//function: getCenterOnArc
548//purpose :
549//=======================================================================
550gp_Pnt AIS_AngleDimension::getCenterOnArc (const gp_Pnt& theFirstAttach,
551 const gp_Pnt& theSecondAttach)
552{
553 gp_Pnt2d aCenter2d = ProjLib::Project (GetWorkingPlane(), myCenter),
554 aFirstAttach2d = ProjLib::Project (GetWorkingPlane(), theFirstAttach),
555 aSecondAttach2d = ProjLib::Project (GetWorkingPlane(), theSecondAttach);
556 gp_Lin2d anAttachLine2d = gce_MakeLin2d (aFirstAttach2d, aSecondAttach2d);
557
558 // Getting text center
559 gp_Pnt2d aTextCenterPnt = ElCLib::Value ((ElCLib::Parameter (anAttachLine2d, aFirstAttach2d) + ElCLib::Parameter (anAttachLine2d, aSecondAttach2d)) / 2., anAttachLine2d);
560 gp_Lin2d aCenterToTextCenterLin = gce_MakeLin2d (aCenter2d, aTextCenterPnt);
561
562 // Drawing circle
563 Standard_Real aRadius = theFirstAttach.Distance (myCenter);
564 gp_Circ2d aCircle (gp_Ax22d (aCenter2d, gp_Dir2d (1, 0)), aRadius);
565
566 // Getting text position in the center of arc
567 IntAna2d_AnaIntersection anInt2d (aCenterToTextCenterLin, aCircle);
568 gp_Pnt2d aTextCenterOnArc2d;
569 if (anInt2d.IsDone())
570 if (!anInt2d.IsEmpty())
571 aTextCenterOnArc2d = gp_Pnt2d (anInt2d.Point (1).Value());
572 gp_Pnt aCenterOnArc = ElCLib::To3d (GetWorkingPlane().Position().Ax2(), aTextCenterOnArc2d);
573 return aCenterOnArc;
7fd59977 574}
a6eb515f 575
7fd59977 576//=======================================================================
a6eb515f 577//function: drawArcWithText
578//purpose :
7fd59977 579//=======================================================================
a6eb515f 580void AIS_AngleDimension::drawArcWithText (const Handle(Prs3d_Presentation)& thePresentation,
581 const gp_Pnt& theFirstAttach,
582 const gp_Pnt& theSecondAttach,
583 const TCollection_ExtendedString& theText,
fe83e1ea 584 const Standard_Real theTextWidth,
585 const Standard_Integer theMode,
d7bffd44 586 const Standard_Integer theLabelPosition)
7fd59977 587{
fe83e1ea 588 // construct plane where the circle and the arc are located
589 gce_MakePln aConstructPlane (theFirstAttach, theSecondAttach, myCenter);
590 if (!aConstructPlane.IsDone())
591 {
592 return;
593 }
594
595 gp_Pln aPlane = aConstructPlane.Value();
a6eb515f 596
a6eb515f 597 Standard_Real aRadius = theFirstAttach.Distance (myCenter);
a6eb515f 598
fe83e1ea 599 // construct circle forming the arc
600 gce_MakeCirc aConstructCircle (myCenter, aPlane, aRadius);
601 if (!aConstructCircle.IsDone())
602 {
603 return;
604 }
a6eb515f 605
fe83e1ea 606 gp_Circ aCircle = aConstructCircle.Value();
a6eb515f 607
fe83e1ea 608 // compute angle parameters of arc end-points on circle
609 Standard_Real aParamBeg = ElCLib::Parameter (aCircle, theFirstAttach);
610 Standard_Real aParamEnd = ElCLib::Parameter (aCircle, theSecondAttach);
611 ElCLib::AdjustPeriodic (aParamBeg, aParamEnd,
612 Precision::PConfusion(),
613 aParamBeg, aParamEnd);
a6eb515f 614
fe83e1ea 615 // middle point of arc parameter on circle
616 Standard_Real aParamMid = (aParamBeg + aParamEnd) * 0.5;
a6eb515f 617
fe83e1ea 618 // add text graphical primitives
619 if (theMode == ComputeMode_All || theMode == ComputeMode_Text)
620 {
621 gp_Pnt aTextPos = ElCLib::Value (aParamMid, aCircle);
622 gp_Dir aTextDir = IsTextReversed()
623 ? gce_MakeDir (theSecondAttach, theFirstAttach)
624 : gce_MakeDir (theFirstAttach, theSecondAttach);
625
626 // Drawing text
627 drawText (thePresentation,
628 aTextPos,
629 aTextDir,
630 theText,
631 theLabelPosition);
632 }
a6eb515f 633
fe83e1ea 634 if (theMode != ComputeMode_All && theMode != ComputeMode_Line)
635 {
636 return;
637 }
a6eb515f 638
fe83e1ea 639 Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
a6eb515f 640
fe83e1ea 641 Standard_Boolean isLineBreak = aDimensionAspect->TextVerticalPosition() == Prs3d_DTVP_Center
642 && aDimensionAspect->IsText3d();
a6eb515f 643
fe83e1ea 644 if (isLineBreak)
a6eb515f 645 {
fe83e1ea 646 // compute gap for label as parameteric size of sector on circle segment
647 Standard_Real aSectorOnCircle = theTextWidth / aRadius;
648
649 gp_Pnt aTextPntBeg = ElCLib::Value (aParamMid - aSectorOnCircle * 0.5, aCircle);
650 gp_Pnt aTextPntEnd = ElCLib::Value (aParamMid + aSectorOnCircle * 0.5, aCircle);
651
652 // Drawing arcs
653 drawArc (thePresentation, theFirstAttach, aTextPntBeg, myCenter, aRadius, theMode);
654 drawArc (thePresentation, theSecondAttach, aTextPntEnd, myCenter, aRadius, theMode);
655 }
656 else
657 {
658 drawArc (thePresentation, theFirstAttach, theSecondAttach, myCenter, aRadius, theMode);
7fd59977 659 }
a6eb515f 660}
7fd59977 661
a6eb515f 662//=======================================================================
663//function : drawArc
664//purpose : draws the arc between two attach points
665//=======================================================================
a6eb515f 666void AIS_AngleDimension::drawArc (const Handle(Prs3d_Presentation)& thePresentation,
667 const gp_Pnt& theFirstAttach,
668 const gp_Pnt& theSecondAttach,
669 const gp_Pnt& theCenter,
670 const Standard_Real theRadius,
fe83e1ea 671 const Standard_Integer theMode)
a6eb515f 672{
fe83e1ea 673 // construct plane where the circle and the arc are located
674 gce_MakePln aConstructPlane (theFirstAttach, theSecondAttach, theCenter);
675 if (!aConstructPlane.IsDone())
676 {
677 return;
678 }
679
680 gp_Pln aPlane = aConstructPlane.Value();
681
682 // construct circle forming the arc
683 gce_MakeCirc aConstructCircle (theCenter, aPlane, theRadius);
684 if (!aConstructCircle.IsDone())
685 {
686 return;
687 }
688
689 gp_Circ aCircle = aConstructCircle.Value();
a6eb515f 690
fe83e1ea 691 // construct the arc
692 GC_MakeArcOfCircle aConstructArc (aCircle, theFirstAttach, theSecondAttach, Standard_True);
693 if (!aConstructArc.IsDone())
694 {
695 return;
696 }
697
698 // generate points with specified deflection
699 const Handle(Geom_TrimmedCurve)& anArcCurve = aConstructArc.Value();
700
701 GeomAdaptor_Curve anArcAdaptor (anArcCurve, anArcCurve->FirstParameter(), anArcCurve->LastParameter());
a6eb515f 702
fe83e1ea 703 // compute number of discretization elements in old-fanshioned way
704 gp_Vec aCenterToFirstVec (theCenter, theFirstAttach);
705 gp_Vec aCenterToSecondVec (theCenter, theSecondAttach);
706 const Standard_Real anAngle = aCenterToFirstVec.Angle (aCenterToSecondVec);
707 const Standard_Integer aNbPoints = Max (4, Standard_Integer (50.0 * anAngle / M_PI));
a6eb515f 708
fe83e1ea 709 GCPnts_UniformAbscissa aMakePnts (anArcAdaptor, aNbPoints);
710 if (!aMakePnts.IsDone())
a6eb515f 711 {
fe83e1ea 712 return;
7fd59977 713 }
7fd59977 714
fe83e1ea 715 // init data arrays for graphical and selection primitives
716 Handle(Graphic3d_ArrayOfPolylines) aPrimSegments = new Graphic3d_ArrayOfPolylines (aNbPoints);
717
718 SelectionGeometry::Curve& aSensitiveCurve = mySelectionGeom.NewCurve();
7fd59977 719
fe83e1ea 720 // load data into arrays
721 for (Standard_Integer aPntIt = 1; aPntIt <= aMakePnts.NbPoints(); ++aPntIt)
722 {
723 gp_Pnt aPnt = anArcAdaptor.Value (aMakePnts.Parameter (aPntIt));
724
725 aPrimSegments->AddVertex (aPnt);
726
727 aSensitiveCurve.Append (aPnt);
728 }
729
730 // add display presentation
731 if (!myDrawer->DimensionAspect()->IsText3d() && theMode == ComputeMode_All)
a6eb515f 732 {
733 Prs3d_Root::CurrentGroup (thePresentation)->SetStencilTestOptions (Standard_True);
7fd59977 734 }
d7bffd44 735 Handle(Graphic3d_AspectLine3d) aDimensionLineStyle = myDrawer->DimensionAspect()->LineAspect()->Aspect();
736 Prs3d_Root::CurrentGroup (thePresentation)->SetPrimitivesAspect (aDimensionLineStyle);
a6eb515f 737 Prs3d_Root::CurrentGroup (thePresentation)->AddPrimitiveArray (aPrimSegments);
fe83e1ea 738 if (!myDrawer->DimensionAspect()->IsText3d() && theMode == ComputeMode_All)
a6eb515f 739 {
740 Prs3d_Root::CurrentGroup (thePresentation)->SetStencilTestOptions (Standard_False);
7fd59977 741 }
742}
743
7fd59977 744//=======================================================================
a6eb515f 745//function : Compute
746//purpose : Having three gp_Pnt points compute presentation
7fd59977 747//=======================================================================
a6eb515f 748void AIS_AngleDimension::Compute (const Handle(PrsMgr_PresentationManager3d)& /*thePM*/,
749 const Handle(Prs3d_Presentation)& thePresentation,
750 const Standard_Integer theMode)
751{
752 thePresentation->Clear();
fe83e1ea 753 mySelectionGeom.Clear (theMode);
a6eb515f 754 Handle(SelectMgr_EntityOwner) anEmptyOwner;
7fd59977 755
a6eb515f 756 if (!myIsInitialized)
757 {
758 if (myShapesNumber == 1)
759 {
760 myIsInitialized = initConeAngle (TopoDS::Face (myFirstShape));
761 }
762 else if (myShapesNumber == 2)
763 {
764 switch (myFirstShape.ShapeType())
765 {
766 case TopAbs_FACE:
767 {
768 myIsInitialized = initTwoFacesAngle ();
769 }
770 break;
771 case TopAbs_EDGE:
772 {
773 myIsInitialized = initTwoEdgesAngle ();
774 }
775 break;
776 default:
777 return;
778 }
779 }
780 else
781 return;
7fd59977 782 }
783
a6eb515f 784 // If initialization failed
785 if (!myIsInitialized)
786 return;
7fd59977 787
a6eb515f 788 // Parameters for presentation
789 Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
d7bffd44 790
791 Prs3d_Root::CurrentGroup(thePresentation)->SetPrimitivesAspect(aDimensionAspect->LineAspect()->Aspect());
792
a6eb515f 793 Quantity_Length anArrowLength = aDimensionAspect->ArrowAspect()->Length();
d7bffd44 794
a6eb515f 795 if (!myIsValueCustom)
d7bffd44 796 {
797 computeValue();
798 }
799
a6eb515f 800 TCollection_ExtendedString aValueString;
801 Standard_Real aTextLength;
802 getTextWidthAndString (aTextLength, aValueString);
d7bffd44 803
fe83e1ea 804 // add margins to label width
805 if (aDimensionAspect->IsText3d())
806 {
807 aTextLength += aDimensionAspect->TextAspect()->Height() * THE_3D_TEXT_MARGIN * 2.0;
808 }
809
a6eb515f 810 if (!myIsWorkingPlaneCustom)
d7bffd44 811 {
a6eb515f 812 countDefaultPlane();
d7bffd44 813 }
814
a6eb515f 815 gp_Pnt aFirstAttach = myCenter.Translated (gp_Vec(myCenter, myFirstPoint).Normalized() * GetFlyout());
816 gp_Pnt aSecondAttach = myCenter.Translated (gp_Vec(myCenter, mySecondPoint).Normalized() * GetFlyout());
7fd59977 817
d7bffd44 818 // Handle user-defined and automatic arrow placement
819 bool isArrowsExternal = false;
820 switch (aDimensionAspect->ArrowOrientation())
821 {
822 case Prs3d_DAO_External: isArrowsExternal = true; break;
823 case Prs3d_DAO_Internal: isArrowsExternal = false; break;
824 case Prs3d_DAO_Fit:
a6eb515f 825 {
d7bffd44 826 gp_Vec anAttachVector (aFirstAttach, aSecondAttach);
827 Standard_Real aDimensionWidth = anAttachVector.Magnitude();
fe83e1ea 828
829 // add margin to ensure a small tail between text and arrow
830 Standard_Real anArrowMargin = aDimensionAspect->IsText3d()
831 ? aDimensionAspect->TextAspect()->Height() * THE_3D_TEXT_MARGIN
832 : 0.0;
833
834 Standard_Real anArrowsWidth = (anArrowLength + anArrowMargin) * 2.0;
d7bffd44 835
836 isArrowsExternal = aDimensionWidth < aTextLength + anArrowsWidth;
837 break;
a6eb515f 838 }
7fd59977 839 }
7fd59977 840
a6eb515f 841 //Arrows positions and directions
d7bffd44 842 gp_Vec aWPDir = gp_Vec (GetWorkingPlane().Axis().Direction());
843
844 gp_Dir aFirstExtensionDir = gp_Vec (myCenter, aFirstAttach) ^ aWPDir;
845 gp_Dir aSecondExtensionDir = gp_Vec (myCenter, aSecondAttach)^ aWPDir.Reversed();
7fd59977 846
d7bffd44 847 gp_Vec aFirstArrowVec = gp_Vec (aFirstExtensionDir) * anArrowLength;
848 gp_Vec aSecondArrowVec = gp_Vec (aSecondExtensionDir) * anArrowLength;
7fd59977 849
d7bffd44 850 gp_Pnt aFirstArrowBegin (0.0, 0.0, 0.0);
851 gp_Pnt aFirstArrowEnd (0.0, 0.0, 0.0);
852 gp_Pnt aSecondArrowBegin (0.0, 0.0, 0.0);
853 gp_Pnt aSecondArrowEnd (0.0, 0.0, 0.0);
854
855 if (isArrowsExternal)
a6eb515f 856 {
857 aFirstArrowVec.Reverse();
858 aSecondArrowVec.Reverse();
d7bffd44 859 }
860
861 aFirstArrowBegin = aFirstAttach;
862 aSecondArrowBegin = aSecondAttach;
863 aFirstArrowEnd = aFirstAttach.Translated (-aFirstArrowVec);
864 aSecondArrowEnd = aSecondAttach.Translated (-aSecondArrowVec);
865
866 Standard_Integer aLabelPosition = LabelPosition_None;
867
868 // Handle user-defined and automatic text placement
869 switch (aDimensionAspect->TextHorizontalPosition())
870 {
871 case Prs3d_DTHP_Left : aLabelPosition |= LabelPosition_Left; break;
872 case Prs3d_DTHP_Right : aLabelPosition |= LabelPosition_Right; break;
873 case Prs3d_DTHP_Center: aLabelPosition |= LabelPosition_HCenter; break;
874 case Prs3d_DTHP_Fit:
875 {
876 gp_Vec anAttachVector (aFirstAttach, aSecondAttach);
877 Standard_Real aDimensionWidth = anAttachVector.Magnitude();
878 Standard_Real anArrowsWidth = anArrowLength * 2.0;
879 Standard_Real aContentWidth = isArrowsExternal ? aTextLength : aTextLength + anArrowsWidth;
7fd59977 880
d7bffd44 881 aLabelPosition |= aDimensionWidth < aContentWidth ? LabelPosition_Left : LabelPosition_HCenter;
882 break;
883 }
7fd59977 884 }
d7bffd44 885
886 switch (aDimensionAspect->TextVerticalPosition())
a6eb515f 887 {
d7bffd44 888 case Prs3d_DTVP_Above : aLabelPosition |= LabelPosition_Above; break;
889 case Prs3d_DTVP_Below : aLabelPosition |= LabelPosition_Below; break;
890 case Prs3d_DTVP_Center : aLabelPosition |= LabelPosition_VCenter; break;
7fd59977 891 }
b8ddfc2f 892
d7bffd44 893 // Group1: stenciling text and the angle dimension arc
894 Prs3d_Root::NewGroup (thePresentation);
895
896 Standard_Real anExtensionSize = aDimensionAspect->ExtensionSize();
897
898 Standard_Integer aHPosition = aLabelPosition & LabelPosition_HMask;
899
900 // draw text label
901 switch (aHPosition)
b8ddfc2f 902 {
d7bffd44 903 case LabelPosition_HCenter :
a6eb515f 904 {
d7bffd44 905 Standard_Boolean isLineBreak = aDimensionAspect->TextVerticalPosition() == Prs3d_DTVP_Center
906 && aDimensionAspect->IsText3d();
907
908 if (isLineBreak)
909 {
910 drawArcWithText (thePresentation,
911 aFirstAttach,
912 aSecondAttach,
913 aValueString,
fe83e1ea 914 aTextLength,
915 theMode,
d7bffd44 916 aLabelPosition);
917 break;
918 }
919
fe83e1ea 920 // compute text primitives
921 if (theMode == ComputeMode_All || theMode == ComputeMode_Text)
d7bffd44 922 {
fe83e1ea 923 gp_Vec aDimensionDir (aFirstArrowEnd, aSecondArrowBegin);
924 gp_Pnt aTextPos = getCenterOnArc (aFirstArrowEnd, aSecondArrowBegin);
925 gp_Dir aTextDir = myIsTextReversed ? aDimensionDir.Reversed() : aDimensionDir;
926
927 drawText (thePresentation,
928 aTextPos,
929 aTextDir,
930 aValueString,
931 aLabelPosition);
d7bffd44 932 }
933
fe83e1ea 934 if (theMode == ComputeMode_All || theMode == ComputeMode_Line)
935 {
936 drawArc (thePresentation,
937 isArrowsExternal ? aFirstAttach : aFirstArrowEnd,
938 isArrowsExternal ? aSecondAttach : aSecondArrowEnd,
939 myCenter,
940 Abs (GetFlyout()),
941 theMode);
942 }
a6eb515f 943 }
d7bffd44 944 break;
945
946 case LabelPosition_Left :
a6eb515f 947 {
d7bffd44 948 drawExtension (thePresentation,
949 anExtensionSize,
950 isArrowsExternal ? aFirstArrowEnd : aFirstAttach,
951 aFirstExtensionDir,
952 aValueString,
fe83e1ea 953 aTextLength,
954 theMode,
d7bffd44 955 aLabelPosition);
a6eb515f 956 }
d7bffd44 957 break;
958
959 case LabelPosition_Right :
a6eb515f 960 {
d7bffd44 961 drawExtension (thePresentation,
962 anExtensionSize,
963 isArrowsExternal ? aSecondArrowEnd : aSecondAttach,
964 aSecondExtensionDir,
965 aValueString,
fe83e1ea 966 aTextLength,
967 theMode,
d7bffd44 968 aLabelPosition);
a6eb515f 969 }
d7bffd44 970 break;
971 }
972
973 // dimension arc without text
fe83e1ea 974 if ((theMode == ComputeMode_All || theMode == ComputeMode_Line) && aHPosition != LabelPosition_HCenter)
d7bffd44 975 {
976 Prs3d_Root::NewGroup (thePresentation);
977
978 drawArc (thePresentation,
979 isArrowsExternal ? aFirstAttach : aFirstArrowEnd,
980 isArrowsExternal ? aSecondAttach : aSecondArrowEnd,
981 myCenter,
982 Abs(GetFlyout ()),
fe83e1ea 983 theMode);
d7bffd44 984 }
7fd59977 985
d7bffd44 986 // arrows and arrow extensions
fe83e1ea 987 if (theMode == ComputeMode_All || theMode == ComputeMode_Line)
d7bffd44 988 {
989 Prs3d_Root::NewGroup (thePresentation);
990
991 drawArrow (thePresentation, aFirstArrowBegin, gp_Dir (aFirstArrowVec));
992 drawArrow (thePresentation, aSecondArrowBegin, gp_Dir (aSecondArrowVec));
993 }
994
fe83e1ea 995 if ((theMode == ComputeMode_All || theMode == ComputeMode_Line) && isArrowsExternal)
d7bffd44 996 {
997 Prs3d_Root::NewGroup (thePresentation);
998
999 if (aHPosition != LabelPosition_Left)
1000 {
1001 drawExtension (thePresentation,
1002 anExtensionSize,
1003 aFirstArrowEnd,
1004 aFirstExtensionDir,
fe83e1ea 1005 THE_EMPTY_LABEL_STRING,
1006 THE_EMPTY_LABEL_WIDTH,
1007 theMode,
d7bffd44 1008 LabelPosition_None);
1009 }
1010
1011 if (aHPosition != LabelPosition_Right)
a6eb515f 1012 {
d7bffd44 1013 drawExtension (thePresentation,
1014 anExtensionSize,
1015 aSecondArrowEnd,
1016 aSecondExtensionDir,
fe83e1ea 1017 THE_EMPTY_LABEL_STRING,
1018 THE_EMPTY_LABEL_WIDTH,
1019 theMode,
d7bffd44 1020 LabelPosition_None);
a6eb515f 1021 }
1022 }
7fd59977 1023
d7bffd44 1024 // flyouts
fe83e1ea 1025 if (theMode == ComputeMode_All && myIsFlyoutLines)
a6eb515f 1026 {
d7bffd44 1027 Prs3d_Root::NewGroup (thePresentation);
1028
1029 Handle(Graphic3d_ArrayOfSegments) aPrimSegments = new Graphic3d_ArrayOfSegments (4);
a6eb515f 1030 aPrimSegments->AddVertex (myCenter);
1031 aPrimSegments->AddVertex (aFirstAttach);
1032 aPrimSegments->AddVertex (myCenter);
1033 aPrimSegments->AddVertex (aSecondAttach);
d7bffd44 1034
1035 Handle(Graphic3d_AspectLine3d) aFlyoutStyle = myDrawer->DimensionAspect()->LineAspect()->Aspect();
1036 Prs3d_Root::CurrentGroup (thePresentation)->SetPrimitivesAspect (aFlyoutStyle);
a6eb515f 1037 Prs3d_Root::CurrentGroup (thePresentation)->AddPrimitiveArray (aPrimSegments);
7fd59977 1038 }
1039
a6eb515f 1040 setComputed (Standard_True);
7fd59977 1041}
62b6361a 1042
1043//=======================================================================
1044//function : computeFlyoutSelection
1045//purpose : computes selection for flyouts
1046//=======================================================================
62b6361a 1047void AIS_AngleDimension::computeFlyoutSelection (const Handle(SelectMgr_Selection)& theSelection,
fe83e1ea 1048 const Handle(SelectMgr_EntityOwner)& theOwner)
62b6361a 1049{
fe83e1ea 1050 if (!myIsFlyoutLines)
1051 {
1052 return;
1053 }
1054
1055 gp_Pnt aFirstAttach = myCenter.Translated (gp_Vec (myCenter, myFirstPoint).Normalized() * GetFlyout());
1056 gp_Pnt aSecondAttach = myCenter.Translated (gp_Vec (myCenter, mySecondPoint).Normalized() * GetFlyout());
1057
1058 Handle(Select3D_SensitiveGroup) aSensitiveEntity = new Select3D_SensitiveGroup (theOwner);
1059 aSensitiveEntity->Add (new Select3D_SensitiveSegment (theOwner, myCenter, aFirstAttach));
1060 aSensitiveEntity->Add (new Select3D_SensitiveSegment (theOwner, myCenter, aSecondAttach));
1061
1062 theSelection->Add (aSensitiveEntity);
d7bffd44 1063}