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