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