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