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