0029882: Visualization - AcceptDisplayMode() should be redefined in class AIS_Texture...
[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
973c2be1 4// Copyright (c) 1999-2014 OPEN CASCADE SAS
b311480e 5//
973c2be1 6// This file is part of Open CASCADE Technology software library.
b311480e 7//
d5f74e42 8// This library is free software; you can redistribute it and/or modify it under
9// the terms of the GNU Lesser General Public License version 2.1 as published
973c2be1 10// by the Free Software Foundation, with special exception defined in the file
11// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12// distribution for complete text of the license and disclaimer of any warranty.
b311480e 13//
973c2be1 14// Alternatively, this file may be used under the terms of Open CASCADE
15// commercial license or contractual agreement.
b311480e 16
a6eb515f 17#include <AIS_AngleDimension.hxx>
7fd59977 18
19#include <AIS.hxx>
7fd59977 20#include <BRepBuilderAPI_MakeFace.hxx>
21#include <BRepAdaptor_Curve.hxx>
22#include <BRepAdaptor_Surface.hxx>
60bf98ae 23#include <BRepLib_MakeVertex.hxx>
24#include <BRep_Tool.hxx>
7fd59977 25#include <ElCLib.hxx>
60bf98ae 26#include <GCPnts_UniformAbscissa.hxx>
27#include <GC_MakeArcOfCircle.hxx>
a6eb515f 28#include <gce_MakeLin2d.hxx>
60bf98ae 29#include <gce_MakeLin.hxx>
30#include <gce_MakeCirc.hxx>
a6eb515f 31#include <gce_MakeCone.hxx>
fe83e1ea 32#include <gce_MakePln.hxx>
fe83e1ea 33#include <gce_MakeDir.hxx>
7fd59977 34#include <Geom_Circle.hxx>
60bf98ae 35#include <Geom_TrimmedCurve.hxx>
7fd59977 36#include <Geom_ConicalSurface.hxx>
37#include <Geom_SurfaceOfRevolution.hxx>
7fd59977 38#include <Geom_OffsetSurface.hxx>
a6eb515f 39#include <Graphic3d_ArrayOfSegments.hxx>
a6eb515f 40#include <Graphic3d_Group.hxx>
a6eb515f 41#include <Graphic3d_ArrayOfPolylines.hxx>
7fd59977 42#include <IntAna2d_AnaIntersection.hxx>
7fd59977 43#include <ProjLib.hxx>
a6eb515f 44#include <Prs3d_Root.hxx>
d7bffd44 45#include <Prs3d_ShadingAspect.hxx>
a6eb515f 46#include <PrsMgr_PresentationManager3d.hxx>
62b6361a 47#include <Select3D_SensitiveGroup.hxx>
7fd59977 48#include <Select3D_SensitiveSegment.hxx>
a6eb515f 49#include <SelectMgr_Selection.hxx>
af203d54 50#include <Standard_ProgramError.hxx>
7fd59977 51#include <UnitsAPI.hxx>
ec357c5c 52#include <Geom_Line.hxx>
53#include <Geom_Plane.hxx>
7fd59977 54
7fd59977 55
92efcf78 56IMPLEMENT_STANDARD_RTTIEXT(AIS_AngleDimension,AIS_Dimension)
57
d7bffd44 58namespace
59{
fe83e1ea 60 static const TCollection_ExtendedString THE_EMPTY_LABEL_STRING;
61 static const Standard_Real THE_EMPTY_LABEL_WIDTH = 0.0;
62 static const Standard_ExtCharacter THE_DEGREE_SYMBOL (0x00B0);
63 static const Standard_Real THE_3D_TEXT_MARGIN = 0.1;
0f0f0c06 64
65 //! Returns true if the given points lie on a same line.
66 static Standard_Boolean isSameLine (const gp_Pnt& theFirstPoint,
67 const gp_Pnt& theCenterPoint,
68 const gp_Pnt& theSecondPoint)
69 {
70 gp_Vec aVec1 (theFirstPoint, theCenterPoint);
71 gp_Vec aVec2 (theCenterPoint, theSecondPoint);
72
73 return aVec1.IsParallel (aVec2, Precision::Angular());
74 }
a3f6f591 75}
d7bffd44 76
7fd59977 77//=======================================================================
78//function : Constructor
60bf98ae 79//purpose :
7fd59977 80//=======================================================================
a6eb515f 81AIS_AngleDimension::AIS_AngleDimension (const TopoDS_Edge& theFirstEdge,
82 const TopoDS_Edge& theSecondEdge)
60bf98ae 83: AIS_Dimension (AIS_KOD_PLANEANGLE)
7fd59977 84{
60bf98ae 85 Init();
86 SetMeasuredGeometry (theFirstEdge, theSecondEdge);
7fd59977 87}
88
7fd59977 89//=======================================================================
90//function : Constructor
60bf98ae 91//purpose :
7fd59977 92//=======================================================================
60bf98ae 93AIS_AngleDimension::AIS_AngleDimension (const gp_Pnt& theFirstPoint,
94 const gp_Pnt& theSecondPoint,
95 const gp_Pnt& theThirdPoint)
96: AIS_Dimension (AIS_KOD_PLANEANGLE)
7fd59977 97{
60bf98ae 98 Init();
99 SetMeasuredGeometry (theFirstPoint, theSecondPoint, theThirdPoint);
7fd59977 100}
101
102//=======================================================================
103//function : Constructor
60bf98ae 104//purpose :
7fd59977 105//=======================================================================
60bf98ae 106AIS_AngleDimension::AIS_AngleDimension (const TopoDS_Vertex& theFirstVertex,
107 const TopoDS_Vertex& theSecondVertex,
108 const TopoDS_Vertex& theThirdVertex)
109: AIS_Dimension (AIS_KOD_PLANEANGLE)
7fd59977 110{
60bf98ae 111 Init();
112 SetMeasuredGeometry (theFirstVertex, theSecondVertex, theThirdVertex);
7fd59977 113}
114
7fd59977 115//=======================================================================
a6eb515f 116//function : Constructor
60bf98ae 117//purpose :
7fd59977 118//=======================================================================
a6eb515f 119AIS_AngleDimension::AIS_AngleDimension (const TopoDS_Face& theCone)
60bf98ae 120: AIS_Dimension (AIS_KOD_PLANEANGLE)
7fd59977 121{
60bf98ae 122 Init();
123 SetMeasuredGeometry (theCone);
7fd59977 124}
125
126//=======================================================================
a6eb515f 127//function : Constructor
60bf98ae 128//purpose :
7fd59977 129//=======================================================================
a6eb515f 130AIS_AngleDimension::AIS_AngleDimension (const TopoDS_Face& theFirstFace,
60bf98ae 131 const TopoDS_Face& theSecondFace)
132: AIS_Dimension (AIS_KOD_PLANEANGLE)
7fd59977 133{
60bf98ae 134 Init();
135 SetMeasuredGeometry (theFirstFace, theSecondFace);
7fd59977 136}
137
7fd59977 138//=======================================================================
60bf98ae 139//function : Constructor
7fd59977 140//purpose :
141//=======================================================================
60bf98ae 142AIS_AngleDimension::AIS_AngleDimension (const TopoDS_Face& theFirstFace,
143 const TopoDS_Face& theSecondFace,
144 const gp_Pnt& thePoint)
145: AIS_Dimension (AIS_KOD_PLANEANGLE)
7fd59977 146{
60bf98ae 147 Init();
148 SetMeasuredGeometry (theFirstFace, theSecondFace, thePoint);
7fd59977 149}
150
7fd59977 151//=======================================================================
60bf98ae 152//function : SetMeasuredGeometry
153//purpose :
7fd59977 154//=======================================================================
60bf98ae 155void AIS_AngleDimension::SetMeasuredGeometry (const TopoDS_Edge& theFirstEdge,
156 const TopoDS_Edge& theSecondEdge)
7fd59977 157{
60bf98ae 158 gp_Pln aComputedPlane;
159
91b16a64 160 myFirstShape = theFirstEdge;
161 mySecondShape = theSecondEdge;
162 myThirdShape = TopoDS_Shape();
163 myGeometryType = GeometryType_Edges;
164 myIsGeometryValid = InitTwoEdgesAngle (aComputedPlane);
60bf98ae 165
91b16a64 166 if (myIsGeometryValid && !myIsPlaneCustom)
60bf98ae 167 {
4d147bf2 168 myPlane = aComputedPlane;
60bf98ae 169 }
170
60bf98ae 171 SetToUpdate();
7fd59977 172}
173
174//=======================================================================
60bf98ae 175//function : SetMeasuredGeometry
176//purpose :
7fd59977 177//=======================================================================
60bf98ae 178void AIS_AngleDimension::SetMeasuredGeometry (const gp_Pnt& theFirstPoint,
179 const gp_Pnt& theSecondPoint,
180 const gp_Pnt& theThirdPoint)
7fd59977 181{
60bf98ae 182 myFirstPoint = theFirstPoint;
183 myCenterPoint = theSecondPoint;
184 mySecondPoint = theThirdPoint;
185 myFirstShape = BRepLib_MakeVertex (myFirstPoint);
186 mySecondShape = BRepLib_MakeVertex (myCenterPoint);
187 myThirdShape = BRepLib_MakeVertex (mySecondPoint);
188 myGeometryType = GeometryType_Points;
91b16a64 189 myIsGeometryValid = IsValidPoints (myFirstPoint, myCenterPoint, mySecondPoint);
7fd59977 190
0f0f0c06 191 Standard_Boolean anIsSameLine = isSameLine (myFirstPoint, myCenterPoint, mySecondPoint);
192 if (myIsGeometryValid && !myIsPlaneCustom && !anIsSameLine)
a6eb515f 193 {
60bf98ae 194 ComputePlane();
195 }
a6eb515f 196
60bf98ae 197 SetToUpdate();
198}
a6eb515f 199
60bf98ae 200//=======================================================================
201//function : SetMeasuredGeometry
202//purpose :
203//=======================================================================
204void AIS_AngleDimension::SetMeasuredGeometry (const TopoDS_Vertex& theFirstVertex,
205 const TopoDS_Vertex& theSecondVertex,
206 const TopoDS_Vertex& theThirdVertex)
207{
91b16a64 208 myFirstShape = theFirstVertex;
209 mySecondShape = theSecondVertex;
210 myThirdShape = theThirdVertex;
211 myFirstPoint = BRep_Tool::Pnt (theFirstVertex);
212 myCenterPoint = BRep_Tool::Pnt (theSecondVertex);
213 mySecondPoint = BRep_Tool::Pnt (theThirdVertex);
214 myGeometryType = GeometryType_Points;
215 myIsGeometryValid = IsValidPoints (myFirstPoint, myCenterPoint, mySecondPoint);
216
0f0f0c06 217 Standard_Boolean anIsSameLine = isSameLine (myFirstPoint, myCenterPoint, mySecondPoint);
218 if (myIsGeometryValid && !myIsPlaneCustom && !anIsSameLine)
a6eb515f 219 {
60bf98ae 220 ComputePlane();
7fd59977 221 }
7fd59977 222
60bf98ae 223 SetToUpdate();
224}
7fd59977 225
60bf98ae 226//=======================================================================
227//function : SetMeasuredGeometry
228//purpose :
229//=======================================================================
230void AIS_AngleDimension::SetMeasuredGeometry (const TopoDS_Face& theCone)
231{
91b16a64 232 myFirstShape = theCone;
233 mySecondShape = TopoDS_Shape();
234 myThirdShape = TopoDS_Shape();
235 myGeometryType = GeometryType_Face;
236 myIsGeometryValid = InitConeAngle();
7fd59977 237
91b16a64 238 if (myIsGeometryValid && !myIsPlaneCustom)
a6eb515f 239 {
60bf98ae 240 ComputePlane();
a6eb515f 241 }
7fd59977 242
60bf98ae 243 SetToUpdate();
7fd59977 244}
245
246//=======================================================================
60bf98ae 247//function : SetMeasuredGeometry
248//purpose :
7fd59977 249//=======================================================================
60bf98ae 250void AIS_AngleDimension::SetMeasuredGeometry (const TopoDS_Face& theFirstFace,
251 const TopoDS_Face& theSecondFace)
7fd59977 252{
91b16a64 253 myFirstShape = theFirstFace;
254 mySecondShape = theSecondFace;
255 myThirdShape = TopoDS_Shape();
256 myGeometryType = GeometryType_Faces;
257 myIsGeometryValid = InitTwoFacesAngle();
a6eb515f 258
91b16a64 259 if (myIsGeometryValid && !myIsPlaneCustom)
a6eb515f 260 {
60bf98ae 261 ComputePlane();
7fd59977 262 }
60bf98ae 263
60bf98ae 264 SetToUpdate();
7fd59977 265}
266
7fd59977 267//=======================================================================
60bf98ae 268//function : SetMeasuredGeometry
7fd59977 269//purpose :
270//=======================================================================
60bf98ae 271void AIS_AngleDimension::SetMeasuredGeometry (const TopoDS_Face& theFirstFace,
272 const TopoDS_Face& theSecondFace,
273 const gp_Pnt& thePoint)
7fd59977 274{
91b16a64 275 myFirstShape = theFirstFace;
276 mySecondShape = theSecondFace;
277 myThirdShape = TopoDS_Shape();
278 myGeometryType = GeometryType_Faces;
279 myIsGeometryValid = InitTwoFacesAngle (thePoint);
60bf98ae 280
91b16a64 281 if (myIsGeometryValid && !myIsPlaneCustom)
60bf98ae 282 {
283 ComputePlane();
284 }
285
60bf98ae 286 SetToUpdate();
7fd59977 287}
288
289//=======================================================================
60bf98ae 290//function : Init
7fd59977 291//purpose :
292//=======================================================================
60bf98ae 293void AIS_AngleDimension::Init()
7fd59977 294{
ee905e84 295 SetType (AIS_TOA_Interior);
296 SetArrowsVisibility (AIS_TOAV_Both);
60bf98ae 297 SetSpecialSymbol (THE_DEGREE_SYMBOL);
298 SetDisplaySpecialSymbol (AIS_DSS_After);
299 SetFlyout (15.0);
7fd59977 300}
301
7fd59977 302//=======================================================================
60bf98ae 303//function: GetCenterOnArc
304//purpose :
7fd59977 305//=======================================================================
60bf98ae 306gp_Pnt AIS_AngleDimension::GetCenterOnArc (const gp_Pnt& theFirstAttach,
307 const gp_Pnt& theSecondAttach,
af203d54 308 const gp_Pnt& theCenter) const
7fd59977 309{
60bf98ae 310 // construct plane where the circle and the arc are located
311 gce_MakePln aConstructPlane (theFirstAttach, theSecondAttach, theCenter);
312 if (!aConstructPlane.IsDone())
a6eb515f 313 {
60bf98ae 314 return gp::Origin();
7fd59977 315 }
60bf98ae 316
317 gp_Pln aPlane = aConstructPlane.Value();
ee905e84 318 // to have an exterior angle presentation, a plane for further constructed circle should be reversed
319 if (myType == AIS_TOA_Exterior)
320 {
321 gp_Ax1 anAxis = aPlane.Axis();
322 gp_Dir aDir = anAxis.Direction();
323 aDir.Reverse();
324 aPlane.SetAxis(gp_Ax1(anAxis.Location(), aDir));
325 }
7fd59977 326
60bf98ae 327 Standard_Real aRadius = theFirstAttach.Distance (theCenter);
7fd59977 328
60bf98ae 329 // construct circle forming the arc
330 gce_MakeCirc aConstructCircle (theCenter, aPlane, aRadius);
331 if (!aConstructCircle.IsDone())
a6eb515f 332 {
60bf98ae 333 return gp::Origin();
7fd59977 334 }
335
60bf98ae 336 gp_Circ aCircle = aConstructCircle.Value();
337
338 // compute angle parameters of arc end-points on circle
339 Standard_Real aParamBeg = ElCLib::Parameter (aCircle, theFirstAttach);
340 Standard_Real aParamEnd = ElCLib::Parameter (aCircle, theSecondAttach);
341 ElCLib::AdjustPeriodic (0.0, M_PI * 2, Precision::PConfusion(), aParamBeg, aParamEnd);
7fd59977 342
60bf98ae 343 return ElCLib::Value ((aParamBeg + aParamEnd) * 0.5, aCircle);
344}
345
4d147bf2 346//=======================================================================
347//function : GetNormalForMinAngle
348//purpose :
349//=======================================================================
350gp_Dir AIS_AngleDimension::GetNormalForMinAngle() const
351{
352 const gp_Dir& aNormal = myPlane.Axis().Direction();
353 gp_Dir aFirst (gp_Vec (myCenterPoint, myFirstPoint) );
354 gp_Dir aSecond (gp_Vec (myCenterPoint, mySecondPoint) );
355
356 return aFirst.AngleWithRef (aSecond, aNormal) < 0.0
357 ? aNormal.Reversed()
358 : aNormal;
359}
360
60bf98ae 361//=======================================================================
362//function : DrawArc
363//purpose : draws the arc between two attach points
364//=======================================================================
365void AIS_AngleDimension::DrawArc (const Handle(Prs3d_Presentation)& thePresentation,
366 const gp_Pnt& theFirstAttach,
367 const gp_Pnt& theSecondAttach,
368 const gp_Pnt& theCenter,
369 const Standard_Real theRadius,
370 const Standard_Integer theMode)
371{
4d147bf2 372 gp_Pln aPlane (myCenterPoint, GetNormalForMinAngle());
60bf98ae 373
ee905e84 374 // to have an exterior angle presentation, a plane for further constructed circle should be reversed
375 if (myType == AIS_TOA_Exterior)
376 {
377 gp_Ax1 anAxis = aPlane.Axis();
378 gp_Dir aDir = anAxis.Direction();
379 aDir.Reverse();
380 aPlane.SetAxis(gp_Ax1(anAxis.Location(), aDir));
381 }
382
60bf98ae 383 // construct circle forming the arc
384 gce_MakeCirc aConstructCircle (theCenter, aPlane, theRadius);
385 if (!aConstructCircle.IsDone())
a6eb515f 386 {
60bf98ae 387 return;
7fd59977 388 }
389
60bf98ae 390 gp_Circ aCircle = aConstructCircle.Value();
391
392 // construct the arc
393 GC_MakeArcOfCircle aConstructArc (aCircle, theFirstAttach, theSecondAttach, Standard_True);
394 if (!aConstructArc.IsDone())
a6eb515f 395 {
60bf98ae 396 return;
7fd59977 397 }
398
60bf98ae 399 // generate points with specified deflection
400 const Handle(Geom_TrimmedCurve)& anArcCurve = aConstructArc.Value();
401
402 GeomAdaptor_Curve anArcAdaptor (anArcCurve, anArcCurve->FirstParameter(), anArcCurve->LastParameter());
7fd59977 403
60bf98ae 404 // compute number of discretization elements in old-fanshioned way
405 gp_Vec aCenterToFirstVec (theCenter, theFirstAttach);
406 gp_Vec aCenterToSecondVec (theCenter, theSecondAttach);
ee905e84 407 Standard_Real anAngle = aCenterToFirstVec.Angle (aCenterToSecondVec);
408 if (myType == AIS_TOA_Exterior)
409 anAngle = 2.0 * M_PI - anAngle;
410 // it sets 50 points on PI, and a part of points if angle is less
60bf98ae 411 const Standard_Integer aNbPoints = Max (4, Standard_Integer (50.0 * anAngle / M_PI));
a6eb515f 412
60bf98ae 413 GCPnts_UniformAbscissa aMakePnts (anArcAdaptor, aNbPoints);
414 if (!aMakePnts.IsDone())
415 {
416 return;
7fd59977 417 }
418
60bf98ae 419 // init data arrays for graphical and selection primitives
420 Handle(Graphic3d_ArrayOfPolylines) aPrimSegments = new Graphic3d_ArrayOfPolylines (aNbPoints);
7fd59977 421
60bf98ae 422 SelectionGeometry::Curve& aSensitiveCurve = mySelectionGeom.NewCurve();
a6eb515f 423
60bf98ae 424 // load data into arrays
425 for (Standard_Integer aPntIt = 1; aPntIt <= aMakePnts.NbPoints(); ++aPntIt)
a6eb515f 426 {
60bf98ae 427 gp_Pnt aPnt = anArcAdaptor.Value (aMakePnts.Parameter (aPntIt));
7fd59977 428
60bf98ae 429 aPrimSegments->AddVertex (aPnt);
7fd59977 430
60bf98ae 431 aSensitiveCurve.Append (aPnt);
a6eb515f 432 }
7fd59977 433
60bf98ae 434 // add display presentation
435 if (!myDrawer->DimensionAspect()->IsText3d() && theMode == ComputeMode_All)
436 {
437 Prs3d_Root::CurrentGroup (thePresentation)->SetStencilTestOptions (Standard_True);
438 }
439 Handle(Graphic3d_AspectLine3d) aDimensionLineStyle = myDrawer->DimensionAspect()->LineAspect()->Aspect();
440 Prs3d_Root::CurrentGroup (thePresentation)->SetPrimitivesAspect (aDimensionLineStyle);
441 Prs3d_Root::CurrentGroup (thePresentation)->AddPrimitiveArray (aPrimSegments);
442 if (!myDrawer->DimensionAspect()->IsText3d() && theMode == ComputeMode_All)
443 {
444 Prs3d_Root::CurrentGroup (thePresentation)->SetStencilTestOptions (Standard_False);
445 }
7fd59977 446}
a6eb515f 447
7fd59977 448//=======================================================================
60bf98ae 449//function: DrawArcWithText
a6eb515f 450//purpose :
7fd59977 451//=======================================================================
60bf98ae 452void AIS_AngleDimension::DrawArcWithText (const Handle(Prs3d_Presentation)& thePresentation,
a6eb515f 453 const gp_Pnt& theFirstAttach,
454 const gp_Pnt& theSecondAttach,
60bf98ae 455 const gp_Pnt& theCenter,
a6eb515f 456 const TCollection_ExtendedString& theText,
fe83e1ea 457 const Standard_Real theTextWidth,
458 const Standard_Integer theMode,
d7bffd44 459 const Standard_Integer theLabelPosition)
7fd59977 460{
4d147bf2 461 gp_Pln aPlane (myCenterPoint, GetNormalForMinAngle());
462
60bf98ae 463 Standard_Real aRadius = theFirstAttach.Distance (myCenterPoint);
a6eb515f 464
fe83e1ea 465 // construct circle forming the arc
60bf98ae 466 gce_MakeCirc aConstructCircle (theCenter, aPlane, aRadius);
fe83e1ea 467 if (!aConstructCircle.IsDone())
468 {
469 return;
470 }
a6eb515f 471
fe83e1ea 472 gp_Circ aCircle = aConstructCircle.Value();
a6eb515f 473
fe83e1ea 474 // compute angle parameters of arc end-points on circle
475 Standard_Real aParamBeg = ElCLib::Parameter (aCircle, theFirstAttach);
476 Standard_Real aParamEnd = ElCLib::Parameter (aCircle, theSecondAttach);
60bf98ae 477 ElCLib::AdjustPeriodic (0.0, M_PI * 2, Precision::PConfusion(), aParamBeg, aParamEnd);
a6eb515f 478
fe83e1ea 479 // middle point of arc parameter on circle
480 Standard_Real aParamMid = (aParamBeg + aParamEnd) * 0.5;
a6eb515f 481
fe83e1ea 482 // add text graphical primitives
483 if (theMode == ComputeMode_All || theMode == ComputeMode_Text)
484 {
485 gp_Pnt aTextPos = ElCLib::Value (aParamMid, aCircle);
60bf98ae 486 gp_Dir aTextDir = gce_MakeDir (theFirstAttach, theSecondAttach);
fe83e1ea 487
488 // Drawing text
7c65581d 489 drawText (thePresentation,
fe83e1ea 490 aTextPos,
491 aTextDir,
492 theText,
493 theLabelPosition);
494 }
a6eb515f 495
fe83e1ea 496 if (theMode != ComputeMode_All && theMode != ComputeMode_Line)
497 {
498 return;
499 }
a6eb515f 500
fe83e1ea 501 Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
a6eb515f 502
fe83e1ea 503 Standard_Boolean isLineBreak = aDimensionAspect->TextVerticalPosition() == Prs3d_DTVP_Center
504 && aDimensionAspect->IsText3d();
a6eb515f 505
fe83e1ea 506 if (isLineBreak)
a6eb515f 507 {
fe83e1ea 508 // compute gap for label as parameteric size of sector on circle segment
4d147bf2 509 Standard_Real aSectorOfText = theTextWidth / aRadius;
510 Standard_Real aTextBegin = aParamMid - aSectorOfText * 0.5;
511 Standard_Real aTextEnd = aParamMid + aSectorOfText * 0.5;
512 gp_Pnt aTextPntBeg = ElCLib::Value (aTextBegin, aCircle);
513 gp_Pnt aTextPntEnd = ElCLib::Value (aTextEnd, aCircle);
fe83e1ea 514
515 // Drawing arcs
4d147bf2 516 if (aTextBegin > aParamBeg)
517 {
518 DrawArc (thePresentation, theFirstAttach, aTextPntBeg, theCenter, aRadius, theMode);
519 }
520 if (aTextEnd < aParamEnd)
521 {
522 DrawArc (thePresentation, aTextPntEnd, theSecondAttach, theCenter, aRadius, theMode);
523 }
fe83e1ea 524 }
525 else
526 {
60bf98ae 527 DrawArc (thePresentation, theFirstAttach, theSecondAttach, theCenter, aRadius, theMode);
7fd59977 528 }
a6eb515f 529}
7fd59977 530
a6eb515f 531//=======================================================================
60bf98ae 532//function : CheckPlane
533//purpose :
a6eb515f 534//=======================================================================
60bf98ae 535Standard_Boolean AIS_AngleDimension::CheckPlane (const gp_Pln& thePlane)const
a6eb515f 536{
60bf98ae 537 if (!thePlane.Contains (myFirstPoint, Precision::Confusion()) &&
538 !thePlane.Contains (mySecondPoint, Precision::Confusion()) &&
539 !thePlane.Contains (myCenterPoint, Precision::Confusion()))
fe83e1ea 540 {
60bf98ae 541 return Standard_False;
fe83e1ea 542 }
543
60bf98ae 544 return Standard_True;
545}
a6eb515f 546
60bf98ae 547//=======================================================================
548//function : ComputePlane
549//purpose :
550//=======================================================================
551void AIS_AngleDimension::ComputePlane()
552{
91b16a64 553 if (!myIsGeometryValid)
a6eb515f 554 {
fe83e1ea 555 return;
7fd59977 556 }
7fd59977 557
4d147bf2 558 // Compute working plane so that Y axis is codirectional
559 // with Y axis of text coordinate system (necessary for text alignment)
560 gp_Vec aFirstVec = gp_Vec (myCenterPoint, myFirstPoint);
561 gp_Vec aSecondVec = gp_Vec (myCenterPoint, mySecondPoint);
562 gp_Vec aDirectionN = aSecondVec ^ aFirstVec;
563 gp_Vec aDirectionY = aFirstVec + aSecondVec;
564 gp_Vec aDirectionX = aDirectionY ^ aDirectionN;
fe83e1ea 565
60bf98ae 566 myPlane = gp_Pln (gp_Ax3 (myCenterPoint, gp_Dir (aDirectionN), gp_Dir (aDirectionX)));
567}
7fd59977 568
60bf98ae 569//=======================================================================
570//function : GetModelUnits
571//purpose :
572//=======================================================================
573const TCollection_AsciiString& AIS_AngleDimension::GetModelUnits() const
574{
575 return myDrawer->DimAngleModelUnits();
576}
fe83e1ea 577
60bf98ae 578//=======================================================================
579//function : GetDisplayUnits
580//purpose :
581//=======================================================================
582const TCollection_AsciiString& AIS_AngleDimension::GetDisplayUnits() const
583{
584 return myDrawer->DimAngleDisplayUnits();
585}
fe83e1ea 586
60bf98ae 587//=======================================================================
588//function : SetModelUnits
589//purpose :
590//=======================================================================
591void AIS_AngleDimension::SetModelUnits (const TCollection_AsciiString& theUnits)
592{
593 myDrawer->SetDimAngleModelUnits (theUnits);
594}
fe83e1ea 595
60bf98ae 596//=======================================================================
597//function : SetDisplayUnits
598//purpose :
599//=======================================================================
600void AIS_AngleDimension::SetDisplayUnits (const TCollection_AsciiString& theUnits)
601{
602 myDrawer->SetDimAngleDisplayUnits (theUnits);
603}
604
605//=======================================================================
606//function : ComputeValue
607//purpose :
608//=======================================================================
609Standard_Real AIS_AngleDimension::ComputeValue() const
610{
611 if (!IsValid())
a6eb515f 612 {
60bf98ae 613 return 0.0;
7fd59977 614 }
60bf98ae 615
616 gp_Vec aVec1 (myCenterPoint, myFirstPoint);
617 gp_Vec aVec2 (myCenterPoint, mySecondPoint);
618
4d147bf2 619 Standard_Real anAngle = aVec1.AngleWithRef (aVec2, GetNormalForMinAngle());
60bf98ae 620
af203d54 621 return anAngle > 0.0 ? anAngle : (2.0 * M_PI + anAngle);
7fd59977 622}
623
7fd59977 624//=======================================================================
a6eb515f 625//function : Compute
626//purpose : Having three gp_Pnt points compute presentation
7fd59977 627//=======================================================================
a6eb515f 628void AIS_AngleDimension::Compute (const Handle(PrsMgr_PresentationManager3d)& /*thePM*/,
629 const Handle(Prs3d_Presentation)& thePresentation,
630 const Standard_Integer theMode)
631{
fe83e1ea 632 mySelectionGeom.Clear (theMode);
7fd59977 633
60bf98ae 634 if (!IsValid())
a6eb515f 635 {
a6eb515f 636 return;
60bf98ae 637 }
7fd59977 638
a6eb515f 639 // Parameters for presentation
640 Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
d7bffd44 641
60bf98ae 642 Prs3d_Root::CurrentGroup(thePresentation)->SetPrimitivesAspect (aDimensionAspect->LineAspect()->Aspect());
d7bffd44 643
ee2be2a8 644 Standard_Real anArrowLength = aDimensionAspect->ArrowAspect()->Length();
d7bffd44 645
60bf98ae 646 // prepare label string and compute its geometrical width
647 Standard_Real aLabelWidth;
648 TCollection_ExtendedString aLabelString = GetValueString (aLabelWidth);
d7bffd44 649
fe83e1ea 650 // add margins to label width
651 if (aDimensionAspect->IsText3d())
652 {
60bf98ae 653 aLabelWidth += aDimensionAspect->TextAspect()->Height() * THE_3D_TEXT_MARGIN * 2.0;
d7bffd44 654 }
655
af203d54 656 // Get parameters from aspect or adjust it according with custom text position
657 Standard_Real anExtensionSize = aDimensionAspect->ExtensionSize();
658 Prs3d_DimensionTextHorizontalPosition aHorisontalTextPos = aDimensionAspect->TextHorizontalPosition();
7fd59977 659
af203d54 660 if (IsTextPositionCustom())
d7bffd44 661 {
91b16a64 662 AdjustParameters (myFixedTextPosition,anExtensionSize, aHorisontalTextPos, myFlyout);
af203d54 663 }
fe83e1ea 664
af203d54 665 // Handle user-defined and automatic arrow placement
666 Standard_Boolean isArrowsExternal = Standard_False;
667 Standard_Integer aLabelPosition = LabelPosition_None;
fe83e1ea 668
af203d54 669 FitTextAlignment (aHorisontalTextPos, aLabelPosition, isArrowsExternal);
d7bffd44 670
af203d54 671 gp_Pnt aFirstAttach = myCenterPoint.Translated (gp_Vec(myCenterPoint, myFirstPoint).Normalized() * GetFlyout());
672 gp_Pnt aSecondAttach = myCenterPoint.Translated (gp_Vec(myCenterPoint, mySecondPoint).Normalized() * GetFlyout());
7fd59977 673
a6eb515f 674 //Arrows positions and directions
4d147bf2 675 gp_Vec aWorkingPlaneDir (GetNormalForMinAngle());
d7bffd44 676
4d147bf2 677 gp_Dir aFirstExtensionDir = aWorkingPlaneDir.Reversed() ^ gp_Vec (myCenterPoint, aFirstAttach);
678 gp_Dir aSecondExtensionDir = aWorkingPlaneDir ^ gp_Vec (myCenterPoint, aSecondAttach);
7fd59977 679
d7bffd44 680 gp_Vec aFirstArrowVec = gp_Vec (aFirstExtensionDir) * anArrowLength;
681 gp_Vec aSecondArrowVec = gp_Vec (aSecondExtensionDir) * anArrowLength;
7fd59977 682
d7bffd44 683 if (isArrowsExternal)
a6eb515f 684 {
685 aFirstArrowVec.Reverse();
686 aSecondArrowVec.Reverse();
d7bffd44 687 }
688
4d147bf2 689 gp_Pnt aFirstArrowBegin (0.0, 0.0, 0.0);
690 gp_Pnt aFirstArrowEnd (0.0, 0.0, 0.0);
691 gp_Pnt aSecondArrowBegin (0.0, 0.0, 0.0);
692 gp_Pnt aSecondArrowEnd (0.0, 0.0, 0.0);
693
d7bffd44 694 aFirstArrowBegin = aFirstAttach;
695 aSecondArrowBegin = aSecondAttach;
696 aFirstArrowEnd = aFirstAttach.Translated (-aFirstArrowVec);
697 aSecondArrowEnd = aSecondAttach.Translated (-aSecondArrowVec);
698
d7bffd44 699 // Group1: stenciling text and the angle dimension arc
700 Prs3d_Root::NewGroup (thePresentation);
701
d7bffd44 702 Standard_Integer aHPosition = aLabelPosition & LabelPosition_HMask;
703
704 // draw text label
705 switch (aHPosition)
b8ddfc2f 706 {
d7bffd44 707 case LabelPosition_HCenter :
a6eb515f 708 {
d7bffd44 709 Standard_Boolean isLineBreak = aDimensionAspect->TextVerticalPosition() == Prs3d_DTVP_Center
710 && aDimensionAspect->IsText3d();
711
712 if (isLineBreak)
713 {
60bf98ae 714 DrawArcWithText (thePresentation,
d7bffd44 715 aFirstAttach,
716 aSecondAttach,
60bf98ae 717 myCenterPoint,
718 aLabelString,
719 aLabelWidth,
fe83e1ea 720 theMode,
d7bffd44 721 aLabelPosition);
722 break;
723 }
724
fe83e1ea 725 // compute text primitives
726 if (theMode == ComputeMode_All || theMode == ComputeMode_Text)
d7bffd44 727 {
60bf98ae 728 gp_Vec aDimensionDir (aFirstAttach, aSecondAttach);
af203d54 729 gp_Pnt aTextPos = IsTextPositionCustom() ? myFixedTextPosition
730 : GetCenterOnArc (aFirstAttach, aSecondAttach, myCenterPoint);
60bf98ae 731 gp_Dir aTextDir = aDimensionDir;
fe83e1ea 732
7c65581d 733 drawText (thePresentation,
fe83e1ea 734 aTextPos,
735 aTextDir,
60bf98ae 736 aLabelString,
fe83e1ea 737 aLabelPosition);
d7bffd44 738 }
739
fe83e1ea 740 if (theMode == ComputeMode_All || theMode == ComputeMode_Line)
741 {
60bf98ae 742 DrawArc (thePresentation,
ee905e84 743 (isArrowsExternal || !isArrowVisible(AIS_TOAV_First)) ? aFirstAttach : aFirstArrowEnd,
744 (isArrowsExternal || !isArrowVisible(AIS_TOAV_Second)) ? aSecondAttach : aSecondArrowEnd,
60bf98ae 745 myCenterPoint,
fe83e1ea 746 Abs (GetFlyout()),
747 theMode);
748 }
a6eb515f 749 }
d7bffd44 750 break;
751
752 case LabelPosition_Left :
a6eb515f 753 {
60bf98ae 754 DrawExtension (thePresentation,
d7bffd44 755 anExtensionSize,
ee905e84 756 (isArrowsExternal && isArrowVisible(AIS_TOAV_First)) ? aFirstArrowEnd : aFirstAttach,
d7bffd44 757 aFirstExtensionDir,
60bf98ae 758 aLabelString,
759 aLabelWidth,
fe83e1ea 760 theMode,
d7bffd44 761 aLabelPosition);
a6eb515f 762 }
d7bffd44 763 break;
764
765 case LabelPosition_Right :
a6eb515f 766 {
60bf98ae 767 DrawExtension (thePresentation,
d7bffd44 768 anExtensionSize,
ee905e84 769 (isArrowsExternal && isArrowVisible(AIS_TOAV_Second)) ? aSecondArrowEnd : aSecondAttach,
d7bffd44 770 aSecondExtensionDir,
60bf98ae 771 aLabelString,
772 aLabelWidth,
fe83e1ea 773 theMode,
d7bffd44 774 aLabelPosition);
a6eb515f 775 }
d7bffd44 776 break;
777 }
778
779 // dimension arc without text
fe83e1ea 780 if ((theMode == ComputeMode_All || theMode == ComputeMode_Line) && aHPosition != LabelPosition_HCenter)
d7bffd44 781 {
782 Prs3d_Root::NewGroup (thePresentation);
783
60bf98ae 784 DrawArc (thePresentation,
ee905e84 785 (isArrowsExternal || !isArrowVisible(AIS_TOAV_First)) ? aFirstAttach : aFirstArrowEnd,
786 (isArrowsExternal || !isArrowVisible(AIS_TOAV_Second)) ? aSecondAttach : aSecondArrowEnd,
60bf98ae 787 myCenterPoint,
d7bffd44 788 Abs(GetFlyout ()),
fe83e1ea 789 theMode);
d7bffd44 790 }
7fd59977 791
d7bffd44 792 // arrows and arrow extensions
fe83e1ea 793 if (theMode == ComputeMode_All || theMode == ComputeMode_Line)
d7bffd44 794 {
795 Prs3d_Root::NewGroup (thePresentation);
796
ee905e84 797 if (isArrowVisible(AIS_TOAV_First))
798 DrawArrow (thePresentation, aFirstArrowBegin, gp_Dir (aFirstArrowVec));
799 if (isArrowVisible(AIS_TOAV_Second))
800 DrawArrow (thePresentation, aSecondArrowBegin, gp_Dir (aSecondArrowVec));
d7bffd44 801 }
802
fe83e1ea 803 if ((theMode == ComputeMode_All || theMode == ComputeMode_Line) && isArrowsExternal)
d7bffd44 804 {
805 Prs3d_Root::NewGroup (thePresentation);
806
ee905e84 807 if (aHPosition != LabelPosition_Left && isArrowVisible(AIS_TOAV_First))
d7bffd44 808 {
60bf98ae 809 DrawExtension (thePresentation,
af203d54 810 aDimensionAspect->ArrowTailSize(),
d7bffd44 811 aFirstArrowEnd,
812 aFirstExtensionDir,
fe83e1ea 813 THE_EMPTY_LABEL_STRING,
814 THE_EMPTY_LABEL_WIDTH,
815 theMode,
d7bffd44 816 LabelPosition_None);
817 }
818
ee905e84 819 if (aHPosition != LabelPosition_Right && isArrowVisible(AIS_TOAV_Second))
a6eb515f 820 {
60bf98ae 821 DrawExtension (thePresentation,
af203d54 822 aDimensionAspect->ArrowTailSize(),
d7bffd44 823 aSecondArrowEnd,
824 aSecondExtensionDir,
fe83e1ea 825 THE_EMPTY_LABEL_STRING,
826 THE_EMPTY_LABEL_WIDTH,
827 theMode,
d7bffd44 828 LabelPosition_None);
a6eb515f 829 }
830 }
7fd59977 831
d7bffd44 832 // flyouts
60bf98ae 833 if (theMode == ComputeMode_All)
a6eb515f 834 {
d7bffd44 835 Prs3d_Root::NewGroup (thePresentation);
836
837 Handle(Graphic3d_ArrayOfSegments) aPrimSegments = new Graphic3d_ArrayOfSegments (4);
60bf98ae 838 aPrimSegments->AddVertex (myCenterPoint);
a6eb515f 839 aPrimSegments->AddVertex (aFirstAttach);
60bf98ae 840 aPrimSegments->AddVertex (myCenterPoint);
a6eb515f 841 aPrimSegments->AddVertex (aSecondAttach);
d7bffd44 842
843 Handle(Graphic3d_AspectLine3d) aFlyoutStyle = myDrawer->DimensionAspect()->LineAspect()->Aspect();
844 Prs3d_Root::CurrentGroup (thePresentation)->SetPrimitivesAspect (aFlyoutStyle);
a6eb515f 845 Prs3d_Root::CurrentGroup (thePresentation)->AddPrimitiveArray (aPrimSegments);
7fd59977 846 }
847
91b16a64 848 mySelectionGeom.IsComputed = Standard_True;
7fd59977 849}
62b6361a 850
851//=======================================================================
60bf98ae 852//function : ComputeFlyoutSelection
62b6361a 853//purpose : computes selection for flyouts
854//=======================================================================
60bf98ae 855void AIS_AngleDimension::ComputeFlyoutSelection (const Handle(SelectMgr_Selection)& theSelection,
fe83e1ea 856 const Handle(SelectMgr_EntityOwner)& theOwner)
62b6361a 857{
60bf98ae 858 gp_Pnt aFirstAttach = myCenterPoint.Translated (gp_Vec (myCenterPoint, myFirstPoint).Normalized() * GetFlyout());
859 gp_Pnt aSecondAttach = myCenterPoint.Translated (gp_Vec (myCenterPoint, mySecondPoint).Normalized() * GetFlyout());
860
861 Handle(Select3D_SensitiveGroup) aSensitiveEntity = new Select3D_SensitiveGroup (theOwner);
862 aSensitiveEntity->Add (new Select3D_SensitiveSegment (theOwner, myCenterPoint, aFirstAttach));
863 aSensitiveEntity->Add (new Select3D_SensitiveSegment (theOwner, myCenterPoint, aSecondAttach));
864
865 theSelection->Add (aSensitiveEntity);
866}
867
868//=======================================================================
869//function : InitTwoEdgesAngle
870//purpose :
871//=======================================================================
872Standard_Boolean AIS_AngleDimension::InitTwoEdgesAngle (gp_Pln& theComputedPlane)
873{
874 TopoDS_Edge aFirstEdge = TopoDS::Edge (myFirstShape);
875 TopoDS_Edge aSecondEdge = TopoDS::Edge (mySecondShape);
876
877 BRepAdaptor_Curve aMakeFirstLine (aFirstEdge);
878 BRepAdaptor_Curve aMakeSecondLine (aSecondEdge);
879
880 if (aMakeFirstLine.GetType() != GeomAbs_Line || aMakeSecondLine.GetType() != GeomAbs_Line)
fe83e1ea 881 {
60bf98ae 882 return Standard_False;
fe83e1ea 883 }
884
60bf98ae 885 Handle(Geom_Line) aFirstLine = new Geom_Line (aMakeFirstLine.Line());
886 Handle(Geom_Line) aSecondLine = new Geom_Line (aMakeSecondLine.Line());
fe83e1ea 887
60bf98ae 888 gp_Lin aFirstLin = aFirstLine->Lin();
889 gp_Lin aSecondLin = aSecondLine->Lin();
fe83e1ea 890
4d147bf2 891 Standard_Boolean isParallelLines = aFirstLin.Direction().IsParallel (aSecondLin.Direction(), Precision::Angular());
60bf98ae 892
4d147bf2 893 theComputedPlane = isParallelLines ? gp_Pln(gp::XOY())
894 : gp_Pln (aSecondLin.Location(), gp_Vec (aFirstLin.Direction()) ^ gp_Vec (aSecondLin.Direction()));
60bf98ae 895
4d147bf2 896 // Compute geometry for this plane and edges
60bf98ae 897 Standard_Boolean isInfinite1,isInfinite2;
898 gp_Pnt aFirstPoint1, aLastPoint1, aFirstPoint2, aLastPoint2;
aa00364d 899 Handle(Geom_Curve) aFirstCurve = aFirstLine, aSecondCurve = aSecondLine;
60bf98ae 900 if (!AIS::ComputeGeometry (aFirstEdge, aSecondEdge,
aa00364d 901 aFirstCurve, aSecondCurve,
60bf98ae 902 aFirstPoint1, aLastPoint1,
903 aFirstPoint2, aLastPoint2,
904 isInfinite1, isInfinite2))
905 {
906 return Standard_False;
907 }
908
4d147bf2 909 Standard_Boolean isSameLines = aFirstLin.Direction().IsEqual (aSecondLin.Direction(), Precision::Angular())
910 && aFirstLin.Location().IsEqual (aSecondLin.Location(),Precision::Confusion());
911
912 // It can be the same gp_Lin geometry but the different begin and end parameters
913 Standard_Boolean isSameEdges =
914 (aFirstPoint1.IsEqual (aFirstPoint2, Precision::Confusion()) && aLastPoint1.IsEqual (aLastPoint2, Precision::Confusion()))
915 || (aFirstPoint1.IsEqual (aLastPoint2, Precision::Confusion()) && aLastPoint1.IsEqual (aFirstPoint2, Precision::Confusion()));
60bf98ae 916
4d147bf2 917 if (isParallelLines)
918 {
919 // Zero angle, it could not handle this geometry
920 if (isSameLines && isSameEdges)
60bf98ae 921 {
4d147bf2 922 return Standard_False;
60bf98ae 923 }
924
4d147bf2 925 // Handle the case of Pi angle
926 const Standard_Real aParam11 = ElCLib::Parameter (aFirstLin, aFirstPoint1);
927 const Standard_Real aParam12 = ElCLib::Parameter (aFirstLin, aLastPoint1);
928 const Standard_Real aParam21 = ElCLib::Parameter (aFirstLin, aFirstPoint2);
929 const Standard_Real aParam22 = ElCLib::Parameter (aFirstLin, aLastPoint2);
930 myCenterPoint = ElCLib::Value ( (Min (aParam11, aParam12) + Max (aParam21, aParam22)) * 0.5, aFirstLin);
931 myFirstPoint = myCenterPoint.Translated (gp_Vec (aFirstLin.Direction()) * Abs (GetFlyout()));
932 mySecondPoint = myCenterPoint.XYZ() + (aFirstLin.Direction().IsEqual (aSecondLin.Direction(), Precision::Angular())
933 ? aFirstLin.Direction().Reversed().XYZ() * Abs (GetFlyout())
934 : aSecondLin.Direction().XYZ() * Abs (GetFlyout()));
60bf98ae 935 }
936 else
937 {
938 // Find intersection
939 gp_Lin2d aFirstLin2d = ProjLib::Project (theComputedPlane, aFirstLin);
940 gp_Lin2d aSecondLin2d = ProjLib::Project (theComputedPlane, aSecondLin);
941
942 IntAna2d_AnaIntersection anInt2d (aFirstLin2d, aSecondLin2d);
943 gp_Pnt2d anIntersectPoint;
944 if (!anInt2d.IsDone() || anInt2d.IsEmpty())
945 {
946 return Standard_False;
947 }
948
949 anIntersectPoint = gp_Pnt2d (anInt2d.Point(1).Value());
950 myCenterPoint = ElCLib::To3d (theComputedPlane.Position().Ax2(), anIntersectPoint);
951
952 if (isInfinite1 || isInfinite2)
953 {
954 myFirstPoint = myCenterPoint.Translated (gp_Vec (aFirstLin.Direction()) * Abs (GetFlyout()));
955 mySecondPoint = myCenterPoint.Translated (gp_Vec (aSecondLin.Direction()) * Abs (GetFlyout()));
956
957 return IsValidPoints (myFirstPoint, myCenterPoint, mySecondPoint);
958 }
959
960 // |
961 // | <- dimension should be here
962 // *----
963 myFirstPoint = myCenterPoint.Distance (aFirstPoint1) > myCenterPoint.Distance (aLastPoint1)
964 ? aFirstPoint1
965 : aLastPoint1;
966
967 mySecondPoint = myCenterPoint.Distance (aFirstPoint2) > myCenterPoint.Distance (aLastPoint2)
968 ? aFirstPoint2
969 : aLastPoint2;
970 }
971
972 return IsValidPoints (myFirstPoint, myCenterPoint, mySecondPoint);
973}
974
975//=======================================================================
976//function : InitTwoFacesAngle
977//purpose : initialization of angle dimension between two faces
978//=======================================================================
979Standard_Boolean AIS_AngleDimension::InitTwoFacesAngle()
980{
981 TopoDS_Face aFirstFace = TopoDS::Face (myFirstShape);
982 TopoDS_Face aSecondFace = TopoDS::Face (mySecondShape);
983
984 gp_Dir aFirstDir, aSecondDir;
51740958 985 gp_Pln aFirstPln, aSecondPln;
60bf98ae 986 Handle(Geom_Surface) aFirstBasisSurf, aSecondBasisSurf;
987 AIS_KindOfSurface aFirstSurfType, aSecondSurfType;
988 Standard_Real aFirstOffset, aSecondOffset;
989
51740958 990 AIS::GetPlaneFromFace (aFirstFace, aFirstPln,
60bf98ae 991 aFirstBasisSurf,aFirstSurfType,aFirstOffset);
992
51740958 993 AIS::GetPlaneFromFace (aSecondFace, aSecondPln,
60bf98ae 994 aSecondBasisSurf, aSecondSurfType, aSecondOffset);
995
996 if (aFirstSurfType == AIS_KOS_Plane && aSecondSurfType == AIS_KOS_Plane)
997 {
998 //Planar faces angle
999 Handle(Geom_Plane) aFirstPlane = Handle(Geom_Plane)::DownCast (aFirstBasisSurf);
1000 Handle(Geom_Plane) aSecondPlane = Handle(Geom_Plane)::DownCast (aSecondBasisSurf);
1001 return AIS::InitAngleBetweenPlanarFaces (aFirstFace,
1002 aSecondFace,
1003 myCenterPoint,
1004 myFirstPoint,
1005 mySecondPoint)
1006 && IsValidPoints (myFirstPoint,
1007 myCenterPoint,
1008 mySecondPoint);
1009 }
1010 else
1011 {
1012 // Curvilinear faces angle
1013 return AIS::InitAngleBetweenCurvilinearFaces (aFirstFace,
1014 aSecondFace,
1015 aFirstSurfType,
1016 aSecondSurfType,
1017 myCenterPoint,
1018 myFirstPoint,
1019 mySecondPoint)
1020 && IsValidPoints (myFirstPoint,
1021 myCenterPoint,
1022 mySecondPoint);
1023 }
1024}
1025
1026//=======================================================================
1027//function : InitTwoFacesAngle
1028//purpose : initialization of angle dimension between two faces
1029//=======================================================================
1030Standard_Boolean AIS_AngleDimension::InitTwoFacesAngle (const gp_Pnt thePointOnFirstFace)
1031{
1032 TopoDS_Face aFirstFace = TopoDS::Face (myFirstShape);
1033 TopoDS_Face aSecondFace = TopoDS::Face (mySecondShape);
1034
1035 gp_Dir aFirstDir, aSecondDir;
51740958 1036 gp_Pln aFirstPln, aSecondPln;
60bf98ae 1037 Handle(Geom_Surface) aFirstBasisSurf, aSecondBasisSurf;
1038 AIS_KindOfSurface aFirstSurfType, aSecondSurfType;
1039 Standard_Real aFirstOffset, aSecondOffset;
1040
51740958 1041 AIS::GetPlaneFromFace (aFirstFace, aFirstPln,
60bf98ae 1042 aFirstBasisSurf,aFirstSurfType,aFirstOffset);
1043
51740958 1044 AIS::GetPlaneFromFace (aSecondFace, aSecondPln,
60bf98ae 1045 aSecondBasisSurf, aSecondSurfType, aSecondOffset);
1046
1047 myFirstPoint = thePointOnFirstFace;
1048 if (aFirstSurfType == AIS_KOS_Plane && aSecondSurfType == AIS_KOS_Plane)
1049 {
1050 //Planar faces angle
1051 Handle(Geom_Plane) aFirstPlane = Handle(Geom_Plane)::DownCast (aFirstBasisSurf);
1052 Handle(Geom_Plane) aSecondPlane = Handle(Geom_Plane)::DownCast (aSecondBasisSurf);
1053 return AIS::InitAngleBetweenPlanarFaces (aFirstFace,
1054 aSecondFace,
1055 myCenterPoint,
1056 myFirstPoint,
1057 mySecondPoint,
1058 Standard_True)
1059 && IsValidPoints (myFirstPoint,
1060 myCenterPoint,
1061 mySecondPoint);
1062 }
1063 else
1064 {
1065 // Curvilinear faces angle
1066 return AIS::InitAngleBetweenCurvilinearFaces (aFirstFace,
1067 aSecondFace,
1068 aFirstSurfType,
1069 aSecondSurfType,
1070 myCenterPoint,
1071 myFirstPoint,
1072 mySecondPoint,
1073 Standard_True)
1074 && IsValidPoints (myFirstPoint,
1075 myCenterPoint,
1076 mySecondPoint);
1077 }
1078}
1079
1080//=======================================================================
1081//function : InitConeAngle
1082//purpose : initialization of the cone angle
1083//=======================================================================
1084Standard_Boolean AIS_AngleDimension::InitConeAngle()
1085{
1086 if (myFirstShape.IsNull())
1087 {
1088 return Standard_False;
1089 }
1090
1091 TopoDS_Face aConeShape = TopoDS::Face (myFirstShape);
1092 gp_Pln aPln;
1093 gp_Cone aCone;
1094 gp_Circ aCircle;
1095 // A surface from the Face
1096 Handle(Geom_Surface) aSurf;
1097 Handle(Geom_OffsetSurface) aOffsetSurf;
1098 Handle(Geom_ConicalSurface) aConicalSurf;
1099 Handle(Geom_SurfaceOfRevolution) aRevSurf;
1100 Handle(Geom_Line) aLine;
1101 BRepAdaptor_Surface aConeAdaptor (aConeShape);
1102 TopoDS_Face aFace;
1103 AIS_KindOfSurface aSurfType;
1104 Standard_Real anOffset = 0.;
1105 Handle(Standard_Type) aType;
1106
1107 Standard_Real aMaxV = aConeAdaptor.FirstVParameter();
1108 Standard_Real aMinV = aConeAdaptor.LastVParameter();
1109
1110 AIS::GetPlaneFromFace (aConeShape, aPln, aSurf, aSurfType, anOffset);
1111
1112 if (aSurfType == AIS_KOS_Revolution)
1113 {
1114 // Surface of revolution
1115 aRevSurf = Handle(Geom_SurfaceOfRevolution)::DownCast(aSurf);
1116 gp_Lin aLin (aRevSurf->Axis());
1117 Handle(Geom_Curve) aBasisCurve = aRevSurf->BasisCurve();
1118 //Must be a part of line (basis curve should be linear)
1119 if (aBasisCurve ->DynamicType() != STANDARD_TYPE(Geom_Line))
1120 return Standard_False;
1121
1122 gp_Pnt aFirst1 = aConeAdaptor.Value (0., aMinV);
1123 gp_Pnt aLast1 = aConeAdaptor.Value (0., aMaxV);
1124 gp_Vec aVec1 (aFirst1, aLast1);
1125
1126 //Projection <aFirst> on <aLin>
1127 gp_Pnt aFirst2 = ElCLib::Value (ElCLib::Parameter (aLin, aFirst1), aLin);
1128 // Projection <aLast> on <aLin>
1129 gp_Pnt aLast2 = ElCLib::Value (ElCLib::Parameter (aLin, aLast1), aLin);
1130
1131 gp_Vec aVec2 (aFirst2, aLast2);
1132
1133 // Check if two parts of revolution are parallel (it's a cylinder) or normal (it's a circle).
1134 if (aVec1.IsParallel (aVec2, Precision::Angular())
1135 || aVec1.IsNormal (aVec2,Precision::Angular()))
1136 return Standard_False;
1137
1138 gce_MakeCone aMkCone (aRevSurf->Axis(), aFirst1, aLast1);
1139 aCone = aMkCone.Value();
1140 myCenterPoint = aCone.Apex();
1141 }
1142 else
1143 {
1144 aType = aSurf->DynamicType();
1145 if (aType == STANDARD_TYPE(Geom_OffsetSurface) || anOffset > 0.01)
1146 {
1147 // Offset surface
1148 aOffsetSurf = new Geom_OffsetSurface (aSurf, anOffset);
1149 aSurf = aOffsetSurf->Surface();
1150 BRepBuilderAPI_MakeFace aMkFace(aSurf, Precision::Confusion());
1151 aMkFace.Build();
1152 if (!aMkFace.IsDone())
1153 return Standard_False;
1154 aConeAdaptor.Initialize (aMkFace.Face());
1155 }
1156 aCone = aConeAdaptor.Cone();
1157 aConicalSurf = Handle(Geom_ConicalSurface)::DownCast (aSurf);
1158 myCenterPoint = aConicalSurf->Apex();
1159 }
1160
1161 // A circle where the angle is drawn
1162 Handle(Geom_Curve) aCurve;
1163 Standard_Real aMidV = ( aMinV + aMaxV ) / 2.5;
1164 aCurve = aSurf->VIso (aMidV);
1165 aCircle = Handle(Geom_Circle)::DownCast (aCurve)->Circ();
1166
1167 aCurve = aSurf->VIso(aMaxV);
1168 gp_Circ aCircVmax = Handle(Geom_Circle)::DownCast(aCurve)->Circ();
1169 aCurve = aSurf->VIso(aMinV);
1170 gp_Circ aCircVmin = Handle(Geom_Circle)::DownCast(aCurve)->Circ();
1171
1172 if (aCircVmax.Radius() < aCircVmin.Radius())
1173 {
1174 gp_Circ aTmpCirc = aCircVmax;
1175 aCircVmax = aCircVmin;
1176 aCircVmin = aTmpCirc;
1177 }
1178
1179 myFirstPoint = ElCLib::Value (0, aCircle);
1180 mySecondPoint = ElCLib::Value (M_PI, aCircle);
1181 return Standard_True;
1182}
1183
1184//=======================================================================
1185//function : IsValidPoints
1186//purpose :
1187//=======================================================================
1188Standard_Boolean AIS_AngleDimension::IsValidPoints (const gp_Pnt& theFirstPoint,
1189 const gp_Pnt& theCenterPoint,
1190 const gp_Pnt& theSecondPoint) const
1191{
1192 return theFirstPoint.Distance (theCenterPoint) > Precision::Confusion()
1193 && theSecondPoint.Distance (theCenterPoint) > Precision::Confusion()
1194 && gp_Vec (theCenterPoint, theFirstPoint).Angle (
1195 gp_Vec (theCenterPoint, theSecondPoint)) > Precision::Angular();
d7bffd44 1196}
af203d54 1197
ee905e84 1198//=======================================================================
1199//function : isArrowVisible
1200//purpose : compares given and internal arrows types, returns true if the the type should be shown
1201//=======================================================================
1202Standard_Boolean AIS_AngleDimension::isArrowVisible(const AIS_TypeOfAngleArrowVisibility& theArrowType) const
1203{
1204 switch (theArrowType)
1205 {
1206 case AIS_TOAV_Both:
1207 return myArrowsVisibility == AIS_TOAV_Both;
1208 case AIS_TOAV_First:
1209 return myArrowsVisibility == AIS_TOAV_Both || myArrowsVisibility == AIS_TOAV_First;
1210 case AIS_TOAV_Second:
1211 return myArrowsVisibility == AIS_TOAV_Both || myArrowsVisibility == AIS_TOAV_Second;
1212 case AIS_TOAV_None:
1213 return false;
1214 }
1215 return false;
1216}
1217
af203d54 1218//=======================================================================
1219//function : GetTextPosition
1220//purpose :
1221//=======================================================================
1222const gp_Pnt AIS_AngleDimension::GetTextPosition() const
1223{
1224 if (!IsValid())
1225 {
1226 return gp::Origin();
1227 }
1228
1229 if (IsTextPositionCustom())
1230 {
1231 return myFixedTextPosition;
1232 }
1233
1234 // Counts text position according to the dimension parameters
1235 gp_Pnt aTextPosition (gp::Origin());
1236
1237 Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
1238
1239 // Prepare label string and compute its geometrical width
1240 Standard_Real aLabelWidth;
1241 TCollection_ExtendedString aLabelString = GetValueString (aLabelWidth);
1242
1243 gp_Pnt aFirstAttach = myCenterPoint.Translated (gp_Vec(myCenterPoint, myFirstPoint).Normalized() * GetFlyout());
1244 gp_Pnt aSecondAttach = myCenterPoint.Translated (gp_Vec(myCenterPoint, mySecondPoint).Normalized() * GetFlyout());
1245
1246 // Handle user-defined and automatic arrow placement
1247 Standard_Boolean isArrowsExternal = Standard_False;
1248 Standard_Integer aLabelPosition = LabelPosition_None;
1249 FitTextAlignment (aDimensionAspect->TextHorizontalPosition(),
1250 aLabelPosition, isArrowsExternal);
1251
1252 // Get text position
1253 switch (aLabelPosition & LabelPosition_HMask)
1254 {
1255 case LabelPosition_HCenter:
1256 {
1257 aTextPosition = GetCenterOnArc (aFirstAttach, aSecondAttach, myCenterPoint);
1258 }
1259 break;
1260 case LabelPosition_Left:
1261 {
1262 gp_Dir aPlaneNormal = gp_Vec (aFirstAttach, aSecondAttach) ^ gp_Vec (myCenterPoint, aFirstAttach);
1263 gp_Dir anExtensionDir = aPlaneNormal ^ gp_Vec (myCenterPoint, aFirstAttach);
1264 Standard_Real anExtensionSize = aDimensionAspect->ExtensionSize();
1265 Standard_Real anOffset = isArrowsExternal
1266 ? anExtensionSize + aDimensionAspect->ArrowAspect()->Length()
1267 : anExtensionSize;
1268 gp_Vec anExtensionVec = gp_Vec (anExtensionDir) * -anOffset;
1269 aTextPosition = aFirstAttach.Translated (anExtensionVec);
1270 }
1271 break;
1272 case LabelPosition_Right:
1273 {
1274 gp_Dir aPlaneNormal = gp_Vec (aFirstAttach, aSecondAttach) ^ gp_Vec (myCenterPoint, aFirstAttach);
1275 gp_Dir anExtensionDir = aPlaneNormal ^ gp_Vec (myCenterPoint, aSecondAttach);
1276 Standard_Real anExtensionSize = aDimensionAspect->ExtensionSize();
1277 Standard_Real anOffset = isArrowsExternal
1278 ? anExtensionSize + aDimensionAspect->ArrowAspect()->Length()
1279 : anExtensionSize;
1280 gp_Vec anExtensionVec = gp_Vec (anExtensionDir) * anOffset;
1281 aTextPosition = aSecondAttach.Translated (anExtensionVec);
1282 }
1283 break;
1284 }
1285
1286 return aTextPosition;
1287}
1288
1289//=======================================================================
1290//function : SetTextPosition
1291//purpose :
1292//=======================================================================
1293void AIS_AngleDimension::SetTextPosition (const gp_Pnt& theTextPos)
1294{
1295 if (!IsValid())
1296 {
1297 return;
1298 }
1299
1300 // The text position point for angle dimension should belong to the working plane.
1301 if (!GetPlane().Contains (theTextPos, Precision::Confusion()))
1302 {
9775fa61 1303 throw Standard_ProgramError("The text position point for angle dimension doesn't belong to the working plane.");
af203d54 1304 }
1305
1306 myIsTextPositionFixed = Standard_True;
1307 myFixedTextPosition = theTextPos;
1308}
1309
1310//=======================================================================
91b16a64 1311//function : AdjustParameters
af203d54 1312//purpose :
1313//=======================================================================
1314void AIS_AngleDimension::AdjustParameters (const gp_Pnt& theTextPos,
1315 Standard_Real& theExtensionSize,
91b16a64 1316 Prs3d_DimensionTextHorizontalPosition& theAlignment,
1317 Standard_Real& theFlyout) const
af203d54 1318{
1319 Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
1320 Standard_Real anArrowLength = aDimensionAspect->ArrowAspect()->Length();
1321
af203d54 1322 // Build circle with radius that is equal to distance from text position to the center point.
1323 Standard_Real aRadius = gp_Vec (myCenterPoint, theTextPos).Magnitude();
1324
1325 // Set attach points in positive direction of the flyout.
1326 gp_Pnt aFirstAttach = myCenterPoint.Translated (gp_Vec (myCenterPoint, myFirstPoint).Normalized() * aRadius);
1327 gp_Pnt aSecondAttach = myCenterPoint.Translated (gp_Vec (myCenterPoint, mySecondPoint).Normalized() * aRadius);
1328
1329 gce_MakeCirc aConstructCircle (myCenterPoint, GetPlane(), aRadius);
1330 if (!aConstructCircle.IsDone())
1331 {
1332 return;
1333 }
1334 gp_Circ aCircle = aConstructCircle.Value();
1335
1336 // Default values
1337 theExtensionSize = aDimensionAspect->ArrowAspect()->Length();
1338 theAlignment = Prs3d_DTHP_Center;
1339
1340 Standard_Real aParamBeg = ElCLib::Parameter (aCircle, aFirstAttach);
1341 Standard_Real aParamEnd = ElCLib::Parameter (aCircle, aSecondAttach);
1342 if (aParamEnd < aParamBeg)
1343 {
1344 Standard_Real aParam = aParamEnd;
1345 aParamEnd = aParamBeg;
1346 aParamBeg = aParam;
1347 }
1348
1349 ElCLib::AdjustPeriodic (0.0, M_PI * 2, Precision::PConfusion(), aParamBeg, aParamEnd);
1350 Standard_Real aTextPar = ElCLib::Parameter (aCircle , theTextPos);
1351
1352 // Horizontal center
1353 if (aTextPar > aParamBeg && aTextPar < aParamEnd)
1354 {
91b16a64 1355 theFlyout = aRadius;
af203d54 1356 return;
1357 }
1358
1359 aParamBeg += M_PI;
1360 aParamEnd += M_PI;
1361 ElCLib::AdjustPeriodic (0.0, M_PI * 2, Precision::PConfusion(), aParamBeg, aParamEnd);
1362
1363 if (aTextPar > aParamBeg && aTextPar < aParamEnd)
1364 {
91b16a64 1365 theFlyout = -aRadius;
af203d54 1366 return;
1367 }
1368
1369 // Text on the extensions
1370 gp_Lin aFirstLine = gce_MakeLin (myCenterPoint, myFirstPoint);
1371 gp_Lin aSecondLine = gce_MakeLin (myCenterPoint, mySecondPoint);
1372 gp_Pnt aFirstTextProj = AIS::Nearest (aFirstLine, theTextPos);
1373 gp_Pnt aSecondTextProj = AIS::Nearest (aSecondLine, theTextPos);
1374 Standard_Real aFirstDist = aFirstTextProj.Distance (theTextPos);
1375 Standard_Real aSecondDist = aSecondTextProj.Distance (theTextPos);
1376
1377 if (aFirstDist <= aSecondDist)
1378 {
1379 aRadius = myCenterPoint.Distance (aFirstTextProj);
1380 Standard_Real aNewExtensionSize = aFirstDist - anArrowLength;
1381 theExtensionSize = aNewExtensionSize < 0.0 ? 0.0 : aNewExtensionSize;
1382
1383 theAlignment = Prs3d_DTHP_Left;
1384
1385 gp_Vec aPosFlyoutDir = gp_Vec (myCenterPoint, myFirstPoint).Normalized().Scaled (aRadius);
1386
91b16a64 1387 theFlyout = aFirstTextProj.Distance (myCenterPoint.Translated (aPosFlyoutDir)) > Precision::Confusion()
af203d54 1388 ? -aRadius : aRadius;
1389 }
1390 else
1391 {
1392 aRadius = myCenterPoint.Distance (aSecondTextProj);
1393
1394 Standard_Real aNewExtensionSize = aSecondDist - anArrowLength;
1395
1396 theExtensionSize = aNewExtensionSize < 0.0 ? 0.0 : aNewExtensionSize;
1397
1398 theAlignment = Prs3d_DTHP_Right;
1399
1400 gp_Vec aPosFlyoutDir = gp_Vec (myCenterPoint, mySecondPoint).Normalized().Scaled (aRadius);
1401
91b16a64 1402 theFlyout = aSecondTextProj.Distance (myCenterPoint.Translated (aPosFlyoutDir)) > Precision::Confusion()
af203d54 1403 ? -aRadius : aRadius;
1404 }
1405}
1406
1407//=======================================================================
1408//function : FitTextAlignment
1409//purpose :
1410//=======================================================================
1411void AIS_AngleDimension::FitTextAlignment (const Prs3d_DimensionTextHorizontalPosition& theHorizontalTextPos,
1412 Standard_Integer& theLabelPosition,
1413 Standard_Boolean& theIsArrowsExternal) const
1414{
1415 Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
1416
ee2be2a8 1417 Standard_Real anArrowLength = aDimensionAspect->ArrowAspect()->Length();
af203d54 1418
1419 // Prepare label string and compute its geometrical width
1420 Standard_Real aLabelWidth;
1421 TCollection_ExtendedString aLabelString = GetValueString (aLabelWidth);
1422
1423 // add margins to label width
1424 if (aDimensionAspect->IsText3d())
1425 {
1426 aLabelWidth += aDimensionAspect->TextAspect()->Height() * THE_3D_TEXT_MARGIN * 2.0;
1427 }
1428
1429 gp_Pnt aFirstAttach = myCenterPoint.Translated (gp_Vec (myCenterPoint, myFirstPoint).Normalized() * GetFlyout());
1430 gp_Pnt aSecondAttach = myCenterPoint.Translated (gp_Vec (myCenterPoint, mySecondPoint).Normalized() * GetFlyout());
1431
1432 // Handle user-defined and automatic arrow placement
1433 switch (aDimensionAspect->ArrowOrientation())
1434 {
1435 case Prs3d_DAO_External: theIsArrowsExternal = true; break;
1436 case Prs3d_DAO_Internal: theIsArrowsExternal = false; break;
1437 case Prs3d_DAO_Fit:
1438 {
1439 gp_Vec anAttachVector (aFirstAttach, aSecondAttach);
1440 Standard_Real aDimensionWidth = anAttachVector.Magnitude();
1441
1442 // Add margin to ensure a small tail between text and arrow
1443 Standard_Real anArrowMargin = aDimensionAspect->IsText3d()
1444 ? aDimensionAspect->TextAspect()->Height() * THE_3D_TEXT_MARGIN
1445 : 0.0;
1446
1447 Standard_Real anArrowsWidth = (anArrowLength + anArrowMargin) * 2.0;
1448
1449 theIsArrowsExternal = aDimensionWidth < aLabelWidth + anArrowsWidth;
1450 break;
1451 }
1452 }
1453
1454 // Handle user-defined and automatic text placement
1455 switch (theHorizontalTextPos)
1456 {
1457 case Prs3d_DTHP_Left : theLabelPosition |= LabelPosition_Left; break;
1458 case Prs3d_DTHP_Right : theLabelPosition |= LabelPosition_Right; break;
1459 case Prs3d_DTHP_Center: theLabelPosition |= LabelPosition_HCenter; break;
1460 case Prs3d_DTHP_Fit:
1461 {
1462 gp_Vec anAttachVector (aFirstAttach, aSecondAttach);
1463 Standard_Real aDimensionWidth = anAttachVector.Magnitude();
1464 Standard_Real anArrowsWidth = anArrowLength * 2.0;
1465 Standard_Real aContentWidth = theIsArrowsExternal ? aLabelWidth : aLabelWidth + anArrowsWidth;
1466
1467 theLabelPosition |= aDimensionWidth < aContentWidth ? LabelPosition_Left : LabelPosition_HCenter;
1468 break;
1469 }
1470 }
1471
1472 switch (aDimensionAspect->TextVerticalPosition())
1473 {
1474 case Prs3d_DTVP_Above : theLabelPosition |= LabelPosition_Above; break;
1475 case Prs3d_DTVP_Below : theLabelPosition |= LabelPosition_Below; break;
1476 case Prs3d_DTVP_Center : theLabelPosition |= LabelPosition_VCenter; break;
1477 }
1478}