0024422: Wrong result done by FaceClassifier algorithm
[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
4// Copyright (c) 1999-2012 OPEN CASCADE SAS
5//
6// The content of this file is subject to the Open CASCADE Technology Public
7// License Version 6.5 (the "License"). You may not use the content of this file
8// except in compliance with the License. Please obtain a copy of the License
9// at http://www.opencascade.org and read it completely before using this file.
10//
11// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
12// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
13//
14// The Original Code and all software distributed under the License is
15// distributed on an "AS IS" basis, without warranty of any kind, and the
16// Initial Developer hereby disclaims all such warranties, including without
17// limitation, any warranties of merchantability, fitness for a particular
18// purpose or non-infringement. Please see the License for the specific terms
19// and conditions governing the rights and limitations under the License.
20
a6eb515f 21#include <AIS_AngleDimension.hxx>
7fd59977 22
23#include <AIS.hxx>
7fd59977 24#include <AIS_Drawer.hxx>
7fd59977 25#include <BRepBuilderAPI_MakeFace.hxx>
26#include <BRepAdaptor_Curve.hxx>
27#include <BRepAdaptor_Surface.hxx>
7fd59977 28#include <ElCLib.hxx>
a6eb515f 29#include <gce_MakeLin2d.hxx>
a6eb515f 30#include <gce_MakeCone.hxx>
7fd59977 31#include <Geom_Circle.hxx>
7fd59977 32#include <Geom_ConicalSurface.hxx>
33#include <Geom_SurfaceOfRevolution.hxx>
7fd59977 34#include <Geom_OffsetSurface.hxx>
a6eb515f 35#include <Graphic3d_ArrayOfSegments.hxx>
a6eb515f 36#include <Graphic3d_Group.hxx>
a6eb515f 37#include <Graphic3d_ArrayOfPolylines.hxx>
7fd59977 38#include <IntAna2d_AnaIntersection.hxx>
39#include <IntAna2d_IntPoint.hxx>
7fd59977 40#include <IntAna_ResultType.hxx>
7fd59977 41#include <ProjLib.hxx>
a6eb515f 42#include <Prs3d_Root.hxx>
d7bffd44 43#include <Prs3d_ShadingAspect.hxx>
a6eb515f 44#include <PrsMgr_PresentationManager3d.hxx>
7fd59977 45#include <Select3D_SensitiveCurve.hxx>
62b6361a 46#include <Select3D_SensitiveGroup.hxx>
7fd59977 47#include <Select3D_SensitiveSegment.hxx>
a6eb515f 48#include <SelectMgr_Selection.hxx>
7fd59977 49#include <UnitsAPI.hxx>
50
a6eb515f 51IMPLEMENT_STANDARD_HANDLE (AIS_AngleDimension, AIS_Dimension)
52IMPLEMENT_STANDARD_RTTIEXT (AIS_AngleDimension, AIS_Dimension)
7fd59977 53
d7bffd44 54namespace
55{
56 static const TCollection_ExtendedString THE_EMPTY_LABEL;
57 static const Standard_ExtCharacter THE_DEGREE_SYMBOL (0x00B0);
58};
59
7fd59977 60//=======================================================================
a6eb515f 61//function : init
62//purpose : Private constructor for default initialization
7fd59977 63//=======================================================================
a6eb515f 64void AIS_AngleDimension::init()
7fd59977 65{
a6eb515f 66 // Default values of units
67 UnitsAPI::SetLocalSystem (UnitsAPI_SI);
68 SetUnitsQuantity ("PLANE ANGLE");
69 SetModelUnits ("rad");
70 SetDisplayUnits ("deg");
d7bffd44 71 SetSpecialSymbol (THE_DEGREE_SYMBOL);
a6eb515f 72 SetDisplaySpecialSymbol (AIS_DSS_After);
d7bffd44 73 SetFlyout (15.0);
74 SetKindOfDimension (AIS_KOD_PLANEANGLE);
a6eb515f 75 MakeUnitsDisplayed (Standard_False);
7fd59977 76}
77
78//=======================================================================
79//function : Constructor
a6eb515f 80//purpose : Two edges dimension
7fd59977 81//=======================================================================
a6eb515f 82AIS_AngleDimension::AIS_AngleDimension (const TopoDS_Edge& theFirstEdge,
83 const TopoDS_Edge& theSecondEdge)
84: AIS_Dimension(),
62b6361a 85 myIsFlyoutLines (Standard_True)
7fd59977 86{
a6eb515f 87 init();
88 myShapesNumber = 2;
d7bffd44 89 myFirstShape = theFirstEdge;
90 mySecondShape = theSecondEdge;
7fd59977 91}
92
7fd59977 93//=======================================================================
94//function : Constructor
a6eb515f 95//purpose : Two edges dimension
96// <thePlane> is used in case of Angle=PI
7fd59977 97//=======================================================================
a6eb515f 98AIS_AngleDimension::AIS_AngleDimension (const TopoDS_Edge& theFirstEdge,
99 const TopoDS_Edge& theSecondEdge,
100 const gp_Pln& thePlane)
101: AIS_Dimension(),
62b6361a 102 myIsFlyoutLines (Standard_True)
7fd59977 103{
a6eb515f 104 init();
105 myShapesNumber = 2;
d7bffd44 106 myFirstShape = theFirstEdge;
107 mySecondShape = theSecondEdge;
a6eb515f 108 SetWorkingPlane (thePlane);
7fd59977 109}
110
111//=======================================================================
112//function : Constructor
a6eb515f 113//purpose : Three points dimension
7fd59977 114//=======================================================================
a6eb515f 115AIS_AngleDimension::AIS_AngleDimension (const gp_Pnt& theFirstPoint,
116 const gp_Pnt& theSecondPoint,
117 const gp_Pnt& theThirdPoint)
118: AIS_Dimension(),
62b6361a 119 myIsFlyoutLines (Standard_True)
7fd59977 120{
a6eb515f 121 init();
122 myIsInitialized = Standard_True;
d7bffd44 123 myFirstPoint = theFirstPoint;
124 myCenter = theSecondPoint;
125 mySecondPoint = theThirdPoint;
126 myShapesNumber = 3;
7fd59977 127}
128
7fd59977 129//=======================================================================
a6eb515f 130//function : Constructor
131//purpose : Cone dimension
7fd59977 132//=======================================================================
a6eb515f 133AIS_AngleDimension::AIS_AngleDimension (const TopoDS_Face& theCone)
134: AIS_Dimension(),
62b6361a 135 myIsFlyoutLines (Standard_True)
7fd59977 136{
a6eb515f 137 init();
138 myIsInitialized = Standard_False;
d7bffd44 139 myFirstShape = theCone;
140 myShapesNumber = 1;
7fd59977 141}
142
143//=======================================================================
a6eb515f 144//function : Constructor
145//purpose : Two faces dimension
7fd59977 146//=======================================================================
a6eb515f 147AIS_AngleDimension::AIS_AngleDimension (const TopoDS_Face& theFirstFace,
148 const TopoDS_Face& theSecondFace,
149 const gp_Ax1& theAxis)
150: AIS_Dimension(),
62b6361a 151 myIsFlyoutLines (Standard_True)
7fd59977 152{
a6eb515f 153 init();
154 myIsInitialized = Standard_False;
d7bffd44 155 myFirstShape = theFirstFace;
156 mySecondShape = theSecondFace;
157 myShapesNumber = 2;
a6eb515f 158 gp_Pln aPlane;
159 aPlane.SetAxis (theAxis);
160 SetWorkingPlane (aPlane);
7fd59977 161}
162
7fd59977 163//=======================================================================
a6eb515f 164//function : SetFirstShape
7fd59977 165//purpose :
166//=======================================================================
a6eb515f 167void AIS_AngleDimension::SetFirstShape (const TopoDS_Shape& theShape,
168 const Standard_Boolean isSingleShape /*= Standard_False*/)
7fd59977 169{
a6eb515f 170 AIS_Dimension::SetFirstShape (theShape);
171 if (isSingleShape)
172 myShapesNumber = 1;
7fd59977 173}
174
7fd59977 175//=======================================================================
a6eb515f 176//function : aboveInBelowCone
177//purpose : Returns 1 if <theC> center is above of <theCMin> center;
178// 0 if <theC> center is between <theCMin> and
179// <theCMax> centers;
180// -1 if <theC> center is below <theCMax> center.
7fd59977 181//=======================================================================
a6eb515f 182Standard_Integer AIS_AngleDimension::aboveInBelowCone (const gp_Circ &theCMax,
183 const gp_Circ &theCMin,
184 const gp_Circ &theC)
7fd59977 185{
a6eb515f 186 const Standard_Real aD = theCMax.Location().Distance (theCMin.Location());
187 const Standard_Real aD1 = theCMax.Location().Distance (theC.Location());
188 const Standard_Real aD2 = theCMin.Location().Distance (theC.Location());
189
190 if (aD >= aD1 && aD >= aD2) return 0;
191 if (aD < aD2 && aD1 < aD2) return -1;
192 if (aD < aD1 && aD2 < aD1) return 1;
193 return 0;
7fd59977 194}
195
196//=======================================================================
a6eb515f 197//function : initConeAngle
198//purpose : initialization of the cone angle
7fd59977 199//=======================================================================
a6eb515f 200Standard_Boolean AIS_AngleDimension::initConeAngle (const TopoDS_Face& theCone)
7fd59977 201{
a6eb515f 202 if (theCone.IsNull ())
203 return Standard_False;
7fd59977 204
a6eb515f 205 gp_Pln aPln;
206 gp_Cone aCone;
207 gp_Circ aCircle;
208 // A surface from the Face
209 Handle(Geom_Surface) aSurf;
210 Handle(Geom_OffsetSurface) aOffsetSurf;
211 Handle(Geom_ConicalSurface) aConicalSurf;
212 Handle(Geom_SurfaceOfRevolution) aRevSurf;
213 Handle(Geom_Line) aLine;
214 BRepAdaptor_Surface aConeAdaptor (theCone);
215 TopoDS_Face aFace;
216 AIS_KindOfSurface aSurfType;
217 Standard_Real anOffset = 0.;
218 Handle(Standard_Type) aType;
7fd59977 219
a6eb515f 220 Standard_Real aMaxV = aConeAdaptor.FirstVParameter();
221 Standard_Real aMinV = aConeAdaptor.LastVParameter();
7fd59977 222
a6eb515f 223 AIS::GetPlaneFromFace(theCone, aPln, aSurf, aSurfType, anOffset);
7fd59977 224
a6eb515f 225 if (aSurfType == AIS_KOS_Revolution)
226 {
227 // Surface of revolution
228 aRevSurf = Handle(Geom_SurfaceOfRevolution)::DownCast(aSurf);
229 gp_Lin aLin (aRevSurf->Axis());
230 Handle(Geom_Curve) aBasisCurve = aRevSurf->BasisCurve();
231 //Must be a part of line (basis curve should be linear)
232 if (aBasisCurve ->DynamicType() != STANDARD_TYPE(Geom_Line))
233 return Standard_False;
234
235 gp_Pnt aFirst1 = aConeAdaptor.Value (0., aMinV);
236 gp_Pnt aLast1 = aConeAdaptor.Value (0., aMaxV);
237 gp_Vec aVec1 (aFirst1, aLast1);
238
239 //Projection <aFirst> on <aLin>
240 gp_Pnt aFirst2 = ElCLib::Value (ElCLib::Parameter (aLin, aFirst1), aLin);
241 // Projection <aLast> on <aLin>
242 gp_Pnt aLast2 = ElCLib::Value (ElCLib::Parameter (aLin, aLast1), aLin);
243
244 gp_Vec aVec2 (aFirst2, aLast2);
245
246 // Check if two parts of revolution are parallel (it's a cylinder) or normal (it's a circle).
247 if (aVec1.IsParallel (aVec2, Precision::Angular())
248 || aVec1.IsNormal (aVec2,Precision::Angular()))
249 return Standard_False;
250
251 gce_MakeCone aMkCone (aRevSurf->Axis(), aFirst1, aLast1);
252 aCone = aMkCone.Value();
253 myCenter = aCone.Apex();
254 }
255 else
256 {
257 aType = aSurf->DynamicType();
258 if (aType == STANDARD_TYPE(Geom_OffsetSurface) || anOffset > 0.01)
7fd59977 259 {
a6eb515f 260 // Offset surface
261 aOffsetSurf = new Geom_OffsetSurface (aSurf, anOffset);
262 aSurf = aOffsetSurf->Surface();
263 BRepBuilderAPI_MakeFace aMkFace(aSurf, Precision::Confusion());
264 aMkFace.Build();
265 if (!aMkFace.IsDone())
266 return Standard_False;
267 aConeAdaptor.Initialize (aMkFace.Face());
7fd59977 268 }
a6eb515f 269 aCone = aConeAdaptor.Cone();
270 aConicalSurf = Handle(Geom_ConicalSurface)::DownCast (aSurf);
271 myCenter = aConicalSurf->Apex();
7fd59977 272 }
7fd59977 273
a6eb515f 274 // A circle where the angle is drawn
275 Handle(Geom_Curve) aCurve;
276 Standard_Real aMidV = ( aMinV + aMaxV ) / 2.5;
277 aCurve = aSurf->VIso (aMidV);
278 aCircle = Handle(Geom_Circle)::DownCast (aCurve)->Circ();
7fd59977 279
a6eb515f 280 aCurve = aSurf->VIso(aMaxV);
281 gp_Circ aCircVmax = Handle(Geom_Circle)::DownCast(aCurve)->Circ();
282 aCurve = aSurf->VIso(aMinV);
283 gp_Circ aCircVmin = Handle(Geom_Circle)::DownCast(aCurve)->Circ();
7fd59977 284
7fd59977 285
a6eb515f 286 if (aCircVmax.Radius() < aCircVmin.Radius())
287 {
288 gp_Circ aTmpCirc = aCircVmax;
289 aCircVmax = aCircVmin;
290 aCircVmin = aTmpCirc;
291 }
7fd59977 292
a6eb515f 293 myFirstPoint = ElCLib::Value (0, aCircle);
294 mySecondPoint = ElCLib::Value (M_PI, aCircle);
295 return Standard_True;
7fd59977 296}
297
298//=======================================================================
a6eb515f 299//function : initTwoFacesAngle
300//purpose : initialization of angle dimension between two faces
7fd59977 301//=======================================================================
a6eb515f 302Standard_Boolean AIS_AngleDimension::initTwoFacesAngle ()
7fd59977 303{
a6eb515f 304 TopoDS_Face aFirstFace = TopoDS::Face (myFirstShape);
305 TopoDS_Face aSecondFace = TopoDS::Face (mySecondShape);
306 gp_Dir aFirstDir, aSecondDir;
307 gp_Pln aFirstPlane, aSecondPlane;
308 Handle(Geom_Surface) aFirstBasisSurf, aSecondBasisSurf;
309 AIS_KindOfSurface aFirstSurfType, aSecondSurfType;
310 Standard_Real aFirstOffset, aSecondOffset;
7fd59977 311
a6eb515f 312 AIS::GetPlaneFromFace (aFirstFace, aFirstPlane,
313 aFirstBasisSurf,aFirstSurfType,aFirstOffset);
314 AIS::GetPlaneFromFace (aSecondFace, aSecondPlane,
315 aSecondBasisSurf, aSecondSurfType, aSecondOffset);
316
317 if (aFirstSurfType == AIS_KOS_Plane)
318 {
319 //Planar faces angle
320 AIS::ComputeAngleBetweenPlanarFaces (aFirstFace,
321 aSecondFace,
322 aSecondBasisSurf,
323 GetWorkingPlane().Axis(),
324 myValue,
325 Standard_True,
326 myGeom.myTextPosition,
327 myCenter,
328 myFirstPoint,
329 mySecondPoint,
330 aFirstDir,
331 aSecondDir);
7fd59977 332 }
a6eb515f 333 else
334 {
335 // Curvilinear faces angle
336 Handle(Geom_Plane) aPlane = new Geom_Plane (GetWorkingPlane());
337 AIS::ComputeAngleBetweenCurvilinearFaces (aFirstFace,
338 aSecondFace,
339 aFirstBasisSurf,
340 aSecondBasisSurf,
341 aFirstSurfType,
342 aSecondSurfType,
343 GetWorkingPlane().Axis(),
344 myValue,
345 Standard_True,
346 myGeom.myTextPosition,
347 myCenter,
348 myFirstPoint,
349 mySecondPoint,
350 aFirstDir,
351 aSecondDir,
352 aPlane);
353 SetWorkingPlane (aPlane->Pln());
7fd59977 354 }
a6eb515f 355 return Standard_True;
7fd59977 356}
357
7fd59977 358//=======================================================================
a6eb515f 359//function : countDefaultPlane
7fd59977 360//purpose :
361//=======================================================================
a6eb515f 362void AIS_AngleDimension::countDefaultPlane ()
7fd59977 363{
a6eb515f 364 if (!myIsInitialized)
365 return;
366 // Compute normal of the default plane.
367 gp_Vec aVec1(myCenter, myFirstPoint),
368 aVec2(myCenter, mySecondPoint);
369 myDefaultPlane = gp_Pln(myCenter, aVec1^aVec2);
370 // Set computed value to <myWorkingPlane>
371 ResetWorkingPlane ();
7fd59977 372}
373
374//=======================================================================
a6eb515f 375//function : computeValue
7fd59977 376//purpose :
377//=======================================================================
a6eb515f 378void AIS_AngleDimension::computeValue ()
7fd59977 379{
a6eb515f 380 gp_Vec aVec1 (myCenter, myFirstPoint),
381 aVec2 (myCenter, mySecondPoint);
382 myValue = aVec1.Angle (aVec2);
383 // To model units
384 AIS_Dimension::computeValue();
7fd59977 385}
386
7fd59977 387//=======================================================================
a6eb515f 388//function : initTwoEdgesAngle
389//purpose : Fill gp_Pnt fields for further presentation computation
390// If intersection between two edges doesn't exist
391// <myIsInitialized> is set to false
7fd59977 392//=======================================================================
a6eb515f 393Standard_Boolean AIS_AngleDimension::initTwoEdgesAngle ()
7fd59977 394{
a6eb515f 395 // Data initialization
396 TopoDS_Edge aFirstEdge = TopoDS::Edge (myFirstShape);
397 TopoDS_Edge aSecondEdge = TopoDS::Edge (mySecondShape);
398 BRepAdaptor_Curve aMakeFirstLine (aFirstEdge);
399 BRepAdaptor_Curve aMakeSecondLine (aSecondEdge);
7fd59977 400
a6eb515f 401 if (aMakeFirstLine.GetType() != GeomAbs_Line || aMakeSecondLine.GetType() != GeomAbs_Line)
402 {
403 return Standard_False;
7fd59977 404 }
405
a6eb515f 406 Handle(Geom_Line) aFirstLine = new Geom_Line (aMakeFirstLine.Line());
407 Handle(Geom_Line) aSecondLine = new Geom_Line (aMakeSecondLine.Line());
7fd59977 408
a6eb515f 409 gp_Lin aFirstLin = aFirstLine->Lin ();
410 gp_Lin aSecondLin = aSecondLine->Lin ();
411 gp_Lin2d aFirstLin2d, aSecondLin2d;
412 Standard_Boolean isParallelLines = aFirstLin.Direction().IsParallel (aSecondLin.Direction(), Precision::Angular());
413 Standard_Boolean isSameLines = isParallelLines && aFirstLin.Distance (aSecondLin.Location()) <= Precision::Confusion();
414 // In case where we can't compute plane automatically
415 if ((isParallelLines || isSameLines) && !myIsWorkingPlaneCustom)
416 {
417 return Standard_False;
7fd59977 418 }
419
a6eb515f 420 gp_Pln aPlane;
7fd59977 421
a6eb515f 422 /// PART 1 is for automatic plane computation from two edges if it is possible
423 // Build plane
424 if (!myIsWorkingPlaneCustom)
425 {
426 gp_Pnt aPoint = aFirstLine->Value (0.);
427 gp_Dir aNormal = isParallelLines
428 ? gp_Vec(aSecondLin.Normal (aPoint).Direction()) ^ gp_Vec (aSecondLin.Direction())
429 : gp_Vec (aFirstLin.Direction()) ^ gp_Vec (aSecondLin.Direction());
430 aPlane = gp_Pln (aPoint, aNormal);
431 resetWorkingPlane (aPlane);
7fd59977 432 }
a6eb515f 433 else
434 {
435 aPlane = GetWorkingPlane();
7fd59977 436 }
437
a6eb515f 438 // Compute geometry for this plane and edges
439 Standard_Boolean isInfinite1,isInfinite2;
440 gp_Pnt aFirstPoint1, aLastPoint1, aFirstPoint2, aLastPoint2;
441 Standard_Integer anExtIndex = -1;
442 Handle(Geom_Curve) anExtCurve;
443 Handle(Geom_Plane) aGeomPlane = new Geom_Plane (aPlane);
444 if (!AIS::ComputeGeometry (aFirstEdge, aSecondEdge,
445 anExtIndex,
446 aFirstLine, aSecondLine,
447 aFirstPoint1, aLastPoint1,
448 aFirstPoint2, aLastPoint2,
449 anExtCurve,
450 isInfinite1, isInfinite2,
451 aGeomPlane))
452 {
453 return Standard_False;
7fd59977 454 }
455
a6eb515f 456 // Check if both edges are on this plane
457 if (!anExtCurve.IsNull())
458 {
459 if (anExtIndex == 1) // First curve is out of the plane
460 {
461 // Project curve on the plane
462 if (myIsWorkingPlaneCustom)
463 {
464 aFirstLin2d = ProjLib::Project (aPlane, aFirstLin);
465 aFirstLin = ElCLib::To3d (aPlane.Position().Ax2(), aFirstLin2d);
7fd59977 466 }
a6eb515f 467 else
468 {
469 aFirstLin.Translate (gp_Vec (aFirstLin.Location(), aSecondLin.Location()));
7fd59977 470 }
7fd59977 471
a6eb515f 472 aFirstLine = new Geom_Line (aFirstLin);
7fd59977 473 }
a6eb515f 474 else if (anExtIndex == 2) // Second curve is out of the plane
475 {
476 if (myIsWorkingPlaneCustom)
477 {
478 aSecondLin2d = ProjLib::Project (aPlane, aSecondLin);
479 aSecondLin = ElCLib::To3d (aPlane.Position().Ax2(), aSecondLin2d);
7fd59977 480 }
a6eb515f 481 else
482 {
483 aSecondLin.Translate (gp_Vec (aSecondLin.Location(), aFirstLin.Location()));
7fd59977 484 }
a6eb515f 485
486 aSecondLine = new Geom_Line (aSecondLin);
7fd59977 487 }
488 }
489
a6eb515f 490 /// PART 2 is for dimension computation using the working plane
7fd59977 491
a6eb515f 492 if (aFirstLin.Direction ().IsParallel (aSecondLin.Direction (), Precision::Angular ()))
493 {
494 // Parallel lines
495 isSameLines = aFirstLin.Distance(aSecondLin.Location()) <= Precision::Confusion();
496 if (!isSameLines)
497 return Standard_False;
498
499 myFirstPoint = aFirstLin.Location();
500 mySecondPoint = ElCLib::Value (ElCLib::Parameter (aFirstLin, myFirstPoint), aSecondLin);
501 if (mySecondPoint.Distance (mySecondPoint) <= Precision::Confusion ())
502 mySecondPoint.Translate (gp_Vec (aSecondLin.Direction ())*Abs(GetFlyout()));
503 myCenter.SetXYZ( (myFirstPoint.XYZ() + mySecondPoint.XYZ()) / 2. );
504 }
505 else
506 {
507 // Find intersection
508 aFirstLin2d = ProjLib::Project (aPlane, aFirstLin);
509 aSecondLin2d = ProjLib::Project (aPlane, aSecondLin);
7fd59977 510
a6eb515f 511 IntAna2d_AnaIntersection anInt2d (aFirstLin2d, aSecondLin2d);
512 gp_Pnt2d anIntersectPoint;
513 if (!anInt2d.IsDone() || anInt2d.IsEmpty())
7fd59977 514 {
a6eb515f 515 return Standard_False;
7fd59977 516 }
517
a6eb515f 518 anIntersectPoint = gp_Pnt2d (anInt2d.Point(1).Value());
519 myCenter = ElCLib::To3d(aPlane.Position().Ax2(), anIntersectPoint);
7fd59977 520
a6eb515f 521 if (isInfinite1 || isInfinite2)
7fd59977 522 {
a6eb515f 523 myFirstPoint = myCenter.Translated (gp_Vec (aFirstLin.Direction())*Abs (GetFlyout()));
524 mySecondPoint = myCenter.Translated (gp_Vec (aSecondLin.Direction())*Abs (GetFlyout()));
525 return Standard_True;
7fd59977 526 }
527
a6eb515f 528 // |
529 // | <- dimension should be here
530 // *----
531 myFirstPoint = myCenter.Distance (aFirstPoint1) > myCenter.Distance (aLastPoint1) ? aFirstPoint1 : aLastPoint1;
532 mySecondPoint = myCenter.Distance (aFirstPoint2) > myCenter.Distance (aLastPoint2) ? aFirstPoint2 : aLastPoint2;
533 }
534 return Standard_True;
7fd59977 535}
536
537//=======================================================================
a6eb515f 538//function: getCenterOnArc
539//purpose :
540//=======================================================================
541gp_Pnt AIS_AngleDimension::getCenterOnArc (const gp_Pnt& theFirstAttach,
542 const gp_Pnt& theSecondAttach)
543{
544 gp_Pnt2d aCenter2d = ProjLib::Project (GetWorkingPlane(), myCenter),
545 aFirstAttach2d = ProjLib::Project (GetWorkingPlane(), theFirstAttach),
546 aSecondAttach2d = ProjLib::Project (GetWorkingPlane(), theSecondAttach);
547 gp_Lin2d anAttachLine2d = gce_MakeLin2d (aFirstAttach2d, aSecondAttach2d);
548
549 // Getting text center
550 gp_Pnt2d aTextCenterPnt = ElCLib::Value ((ElCLib::Parameter (anAttachLine2d, aFirstAttach2d) + ElCLib::Parameter (anAttachLine2d, aSecondAttach2d)) / 2., anAttachLine2d);
551 gp_Lin2d aCenterToTextCenterLin = gce_MakeLin2d (aCenter2d, aTextCenterPnt);
552
553 // Drawing circle
554 Standard_Real aRadius = theFirstAttach.Distance (myCenter);
555 gp_Circ2d aCircle (gp_Ax22d (aCenter2d, gp_Dir2d (1, 0)), aRadius);
556
557 // Getting text position in the center of arc
558 IntAna2d_AnaIntersection anInt2d (aCenterToTextCenterLin, aCircle);
559 gp_Pnt2d aTextCenterOnArc2d;
560 if (anInt2d.IsDone())
561 if (!anInt2d.IsEmpty())
562 aTextCenterOnArc2d = gp_Pnt2d (anInt2d.Point (1).Value());
563 gp_Pnt aCenterOnArc = ElCLib::To3d (GetWorkingPlane().Position().Ax2(), aTextCenterOnArc2d);
564 return aCenterOnArc;
7fd59977 565}
a6eb515f 566
7fd59977 567//=======================================================================
a6eb515f 568//function: drawArcWithText
569//purpose :
7fd59977 570//=======================================================================
a6eb515f 571void AIS_AngleDimension::drawArcWithText (const Handle(Prs3d_Presentation)& thePresentation,
572 const gp_Pnt& theFirstAttach,
573 const gp_Pnt& theSecondAttach,
574 const TCollection_ExtendedString& theText,
d7bffd44 575 const AIS_DimensionDisplayMode theMode,
576 const Standard_Integer theLabelPosition)
7fd59977 577{
a6eb515f 578 gp_Pnt2d aCenter2d = ProjLib::Project (GetWorkingPlane(), myCenter),
579 aFirstAttach2d = ProjLib::Project (GetWorkingPlane(), theFirstAttach),
580 aSecondAttach2d = ProjLib::Project (GetWorkingPlane(), theSecondAttach);
581 gp_Lin2d anAttachLine2d = gce_MakeLin2d (aFirstAttach2d, aSecondAttach2d);
582
583 // Getting text center
584 gp_Pnt2d aTextCenterPnt = ElCLib::Value ((ElCLib::Parameter (anAttachLine2d, aFirstAttach2d) + ElCLib::Parameter (anAttachLine2d, aSecondAttach2d)) / 2., anAttachLine2d);
585 gp_Lin2d aCenterToTextCenterLin = gce_MakeLin2d (aCenter2d, aTextCenterPnt);
586
587 // Drawing circle
588 Standard_Real aRadius = theFirstAttach.Distance (myCenter);
589 gp_Circ2d aCircle (gp_Ax22d (aCenter2d, gp_Dir2d (1, 0)), aRadius);
590
591 // Getting text position in the center of arc
592 IntAna2d_AnaIntersection anInt2d (aCenterToTextCenterLin, aCircle);
593 gp_Pnt2d aTextCenterOnArc2d;
594 if (anInt2d.IsDone())
595 if (!anInt2d.IsEmpty())
596 aTextCenterOnArc2d = gp_Pnt2d (anInt2d.Point (1).Value());
597 myGeom.myTextPosition = ElCLib::To3d (GetWorkingPlane().Position().Ax2(), aTextCenterOnArc2d);
598
599 // Drawing text
600 gp_Vec aVec (theFirstAttach, theSecondAttach);
601 Standard_Real aTextWidth = drawText (thePresentation,
602 myIsTextReversed ? aVec.Reversed() : aVec,
d7bffd44 603 theText, theMode,
604 theLabelPosition);
a6eb515f 605
606 // Getting text begin and end points
607 gp_Pnt2d aTextBeginPnt = ElCLib::Value ((ElCLib::Parameter (anAttachLine2d, aFirstAttach2d) +
608 ElCLib::Parameter (anAttachLine2d, aSecondAttach2d) -
609 aTextWidth) / 2., anAttachLine2d),
610 aTextEndPnt = ElCLib::Value (ElCLib::Parameter (anAttachLine2d,aTextBeginPnt) + aTextWidth, anAttachLine2d);
611
612
613 gp_Lin2d aCenterToTextBeginLin = gce_MakeLin2d (aCenter2d, aTextBeginPnt),
614 aCenterToTextEndLin = gce_MakeLin2d (aCenter2d, aTextEndPnt);
615
616 // Text begin and end on the dimension arc
617 gp_Pnt2d aTextBeginOnArc2d, aTextEndOnArc2d;
618 anInt2d.Perform (aCenterToTextBeginLin, aCircle);
619 if (anInt2d.IsDone())
620 if (!anInt2d.IsEmpty())
621 aTextBeginOnArc2d = gp_Pnt2d (anInt2d.Point (1).Value());
622
623 anInt2d.Perform (aCenterToTextEndLin, aCircle);
624 if (anInt2d.IsDone())
625 if (!anInt2d.IsEmpty())
626 aTextEndOnArc2d = gp_Pnt2d (anInt2d.Point (1).Value());
627
628 gp_Pnt aTextBeginOnArc = ElCLib::To3d (GetWorkingPlane().Position().Ax2(), aTextBeginOnArc2d);
629 gp_Pnt aTextEndOnArc = ElCLib::To3d (GetWorkingPlane().Position().Ax2(), aTextEndOnArc2d);
630
631 // Drawing arcs
632 if (theMode != AIS_DDM_Text)
633 {
634 drawArc (thePresentation, theFirstAttach, aTextBeginOnArc, myCenter, aRadius, theMode);
635 drawArc (thePresentation, aTextEndOnArc, theSecondAttach, myCenter, aRadius, theMode);
7fd59977 636 }
a6eb515f 637}
7fd59977 638
a6eb515f 639//=======================================================================
640//function : drawArc
641//purpose : draws the arc between two attach points
642//=======================================================================
a6eb515f 643void AIS_AngleDimension::drawArc (const Handle(Prs3d_Presentation)& thePresentation,
644 const gp_Pnt& theFirstAttach,
645 const gp_Pnt& theSecondAttach,
646 const gp_Pnt& theCenter,
647 const Standard_Real theRadius,
648 const AIS_DimensionDisplayMode theMode)
649{
650 Handle(SelectMgr_EntityOwner) anEmptyOwner;
a6eb515f 651
652 gp_Vec aCenterToFirstVec (theCenter,theFirstAttach);
653 gp_Vec aCenterToSecondVec (theCenter,theSecondAttach);
654 gp_Dir aCenterToFirstDir (aCenterToFirstVec);
655 gp_Dir aPlaneNormal = GetWorkingPlane().Axis().Direction();
656 gp_Dir aCenterToSecondDir = aPlaneNormal.Crossed (aCenterToFirstDir);
657
658 const Standard_Real anAngle = aCenterToFirstVec.Angle(aCenterToSecondVec);
659 const Standard_Integer aPointsOnArc = Max (4 , Standard_Integer (50. * anAngle / M_PI));
660 const Standard_Real anAngleStep = anAngle / (aPointsOnArc - 1);
661 TColgp_Array1OfPnt aPointArray (0,aPointsOnArc-1);
662 Handle(Graphic3d_ArrayOfPolylines) aPrimSegments = new Graphic3d_ArrayOfPolylines (aPointsOnArc,2);
663 aPrimSegments->AddVertex (theFirstAttach);
664 aPointArray.SetValue(0, theFirstAttach);
665 gp_Pnt aPoint = theFirstAttach;
666 gp_Vec aVector;
667
668 for (Standard_Integer anI = 1; anI < aPointsOnArc - 1; ++anI)
669 {
670 aVector = (gp_Vec(aCenterToFirstDir) * Cos ( (anI - 1) * anAngleStep) + gp_Vec(aCenterToSecondDir) * Sin ( (anI - 1) * anAngleStep)) * theRadius;
671 aPoint = theCenter.Translated(aVector);
672 aPrimSegments->AddVertex(aPoint);
673 aPointArray.SetValue (anI,aPoint);
7fd59977 674 }
a6eb515f 675 aPrimSegments->AddVertex (theSecondAttach);
676 aPointArray.SetValue (aPointsOnArc - 1,theSecondAttach);
7fd59977 677
a6eb515f 678 // Fill sensitive list
679 myGeom.mySensitiveSegments.Append(new Select3D_SensitiveCurve(anEmptyOwner,aPointArray));
7fd59977 680
a6eb515f 681 // Fill display presentation
682 if (!myDrawer->DimensionAspect()->IsText3d() && theMode == AIS_DDM_All)
683 {
684 Prs3d_Root::CurrentGroup (thePresentation)->SetStencilTestOptions (Standard_True);
7fd59977 685 }
d7bffd44 686 Handle(Graphic3d_AspectLine3d) aDimensionLineStyle = myDrawer->DimensionAspect()->LineAspect()->Aspect();
687 Prs3d_Root::CurrentGroup (thePresentation)->SetPrimitivesAspect (aDimensionLineStyle);
a6eb515f 688 Prs3d_Root::CurrentGroup (thePresentation)->AddPrimitiveArray (aPrimSegments);
689 if (!myDrawer->DimensionAspect()->IsText3d() && theMode == AIS_DDM_All)
690 {
691 Prs3d_Root::CurrentGroup (thePresentation)->SetStencilTestOptions (Standard_False);
7fd59977 692 }
693}
694
7fd59977 695//=======================================================================
a6eb515f 696//function : Compute
697//purpose : Having three gp_Pnt points compute presentation
7fd59977 698//=======================================================================
a6eb515f 699void AIS_AngleDimension::Compute (const Handle(PrsMgr_PresentationManager3d)& /*thePM*/,
700 const Handle(Prs3d_Presentation)& thePresentation,
701 const Standard_Integer theMode)
702{
703 thePresentation->Clear();
704 myGeom.mySensitiveSegments.Clear();
705 Handle(SelectMgr_EntityOwner) anEmptyOwner;
7fd59977 706
a6eb515f 707 if (!myIsInitialized)
708 {
709 if (myShapesNumber == 1)
710 {
711 myIsInitialized = initConeAngle (TopoDS::Face (myFirstShape));
712 }
713 else if (myShapesNumber == 2)
714 {
715 switch (myFirstShape.ShapeType())
716 {
717 case TopAbs_FACE:
718 {
719 myIsInitialized = initTwoFacesAngle ();
720 }
721 break;
722 case TopAbs_EDGE:
723 {
724 myIsInitialized = initTwoEdgesAngle ();
725 }
726 break;
727 default:
728 return;
729 }
730 }
731 else
732 return;
7fd59977 733 }
734
a6eb515f 735 // If initialization failed
736 if (!myIsInitialized)
737 return;
7fd59977 738
a6eb515f 739 // Parameters for presentation
740 Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
d7bffd44 741
742 Prs3d_Root::CurrentGroup(thePresentation)->SetPrimitivesAspect(aDimensionAspect->LineAspect()->Aspect());
743
a6eb515f 744 Quantity_Length anArrowLength = aDimensionAspect->ArrowAspect()->Length();
d7bffd44 745
a6eb515f 746 if (!myIsValueCustom)
d7bffd44 747 {
748 computeValue();
749 }
750
a6eb515f 751 TCollection_ExtendedString aValueString;
752 Standard_Real aTextLength;
753 getTextWidthAndString (aTextLength, aValueString);
d7bffd44 754
a6eb515f 755 if (!myIsWorkingPlaneCustom)
d7bffd44 756 {
a6eb515f 757 countDefaultPlane();
d7bffd44 758 }
759
a6eb515f 760 gp_Pnt aFirstAttach = myCenter.Translated (gp_Vec(myCenter, myFirstPoint).Normalized() * GetFlyout());
761 gp_Pnt aSecondAttach = myCenter.Translated (gp_Vec(myCenter, mySecondPoint).Normalized() * GetFlyout());
7fd59977 762
d7bffd44 763 // Handle user-defined and automatic arrow placement
764 bool isArrowsExternal = false;
765 switch (aDimensionAspect->ArrowOrientation())
766 {
767 case Prs3d_DAO_External: isArrowsExternal = true; break;
768 case Prs3d_DAO_Internal: isArrowsExternal = false; break;
769 case Prs3d_DAO_Fit:
a6eb515f 770 {
d7bffd44 771 gp_Vec anAttachVector (aFirstAttach, aSecondAttach);
772 Standard_Real aDimensionWidth = anAttachVector.Magnitude();
773 Standard_Real anArrowsWidth = anArrowLength * 2.0;
774
775 isArrowsExternal = aDimensionWidth < aTextLength + anArrowsWidth;
776 break;
a6eb515f 777 }
7fd59977 778 }
7fd59977 779
a6eb515f 780 //Arrows positions and directions
d7bffd44 781 gp_Vec aWPDir = gp_Vec (GetWorkingPlane().Axis().Direction());
782
783 gp_Dir aFirstExtensionDir = gp_Vec (myCenter, aFirstAttach) ^ aWPDir;
784 gp_Dir aSecondExtensionDir = gp_Vec (myCenter, aSecondAttach)^ aWPDir.Reversed();
7fd59977 785
d7bffd44 786 gp_Vec aFirstArrowVec = gp_Vec (aFirstExtensionDir) * anArrowLength;
787 gp_Vec aSecondArrowVec = gp_Vec (aSecondExtensionDir) * anArrowLength;
7fd59977 788
d7bffd44 789 gp_Pnt aFirstArrowBegin (0.0, 0.0, 0.0);
790 gp_Pnt aFirstArrowEnd (0.0, 0.0, 0.0);
791 gp_Pnt aSecondArrowBegin (0.0, 0.0, 0.0);
792 gp_Pnt aSecondArrowEnd (0.0, 0.0, 0.0);
793
794 if (isArrowsExternal)
a6eb515f 795 {
796 aFirstArrowVec.Reverse();
797 aSecondArrowVec.Reverse();
d7bffd44 798 }
799
800 aFirstArrowBegin = aFirstAttach;
801 aSecondArrowBegin = aSecondAttach;
802 aFirstArrowEnd = aFirstAttach.Translated (-aFirstArrowVec);
803 aSecondArrowEnd = aSecondAttach.Translated (-aSecondArrowVec);
804
805 Standard_Integer aLabelPosition = LabelPosition_None;
806
807 // Handle user-defined and automatic text placement
808 switch (aDimensionAspect->TextHorizontalPosition())
809 {
810 case Prs3d_DTHP_Left : aLabelPosition |= LabelPosition_Left; break;
811 case Prs3d_DTHP_Right : aLabelPosition |= LabelPosition_Right; break;
812 case Prs3d_DTHP_Center: aLabelPosition |= LabelPosition_HCenter; break;
813 case Prs3d_DTHP_Fit:
814 {
815 gp_Vec anAttachVector (aFirstAttach, aSecondAttach);
816 Standard_Real aDimensionWidth = anAttachVector.Magnitude();
817 Standard_Real anArrowsWidth = anArrowLength * 2.0;
818 Standard_Real aContentWidth = isArrowsExternal ? aTextLength : aTextLength + anArrowsWidth;
7fd59977 819
d7bffd44 820 aLabelPosition |= aDimensionWidth < aContentWidth ? LabelPosition_Left : LabelPosition_HCenter;
821 break;
822 }
7fd59977 823 }
d7bffd44 824
825 switch (aDimensionAspect->TextVerticalPosition())
a6eb515f 826 {
d7bffd44 827 case Prs3d_DTVP_Above : aLabelPosition |= LabelPosition_Above; break;
828 case Prs3d_DTVP_Below : aLabelPosition |= LabelPosition_Below; break;
829 case Prs3d_DTVP_Center : aLabelPosition |= LabelPosition_VCenter; break;
7fd59977 830 }
b8ddfc2f 831
d7bffd44 832 // Group1: stenciling text and the angle dimension arc
833 Prs3d_Root::NewGroup (thePresentation);
834
835 Standard_Real anExtensionSize = aDimensionAspect->ExtensionSize();
836
837 Standard_Integer aHPosition = aLabelPosition & LabelPosition_HMask;
838
839 // draw text label
840 switch (aHPosition)
b8ddfc2f 841 {
d7bffd44 842 case LabelPosition_HCenter :
a6eb515f 843 {
d7bffd44 844 Standard_Boolean isLineBreak = aDimensionAspect->TextVerticalPosition() == Prs3d_DTVP_Center
845 && aDimensionAspect->IsText3d();
846
847 if (isLineBreak)
848 {
849 drawArcWithText (thePresentation,
850 aFirstAttach,
851 aSecondAttach,
852 aValueString,
853 (AIS_DimensionDisplayMode)theMode,
854 aLabelPosition);
855 break;
856 }
857
a6eb515f 858 gp_Vec aTextDir (aFirstArrowEnd, aSecondArrowBegin);
859 myGeom.myTextPosition = getCenterOnArc (aFirstArrowEnd, aSecondArrowBegin);
d7bffd44 860
a6eb515f 861 drawText (thePresentation,
862 myIsTextReversed ? aTextDir.Reversed() : aTextDir,
d7bffd44 863 aValueString,
864 (AIS_DimensionDisplayMode)theMode,
865 aLabelPosition);
866
867 if (theMode == AIS_DDM_Text)
868 {
869 break;
870 }
871
872 drawArc (thePresentation,
873 isArrowsExternal ? aFirstAttach : aFirstArrowEnd,
874 isArrowsExternal ? aSecondAttach : aSecondArrowEnd,
875 myCenter,
876 Abs (GetFlyout()),
877 (AIS_DimensionDisplayMode)theMode);
a6eb515f 878 }
d7bffd44 879 break;
880
881 case LabelPosition_Left :
a6eb515f 882 {
d7bffd44 883 drawExtension (thePresentation,
884 anExtensionSize,
885 isArrowsExternal ? aFirstArrowEnd : aFirstAttach,
886 aFirstExtensionDir,
887 aValueString,
888 (AIS_DimensionDisplayMode)theMode,
889 aLabelPosition);
a6eb515f 890 }
d7bffd44 891 break;
892
893 case LabelPosition_Right :
a6eb515f 894 {
d7bffd44 895 drawExtension (thePresentation,
896 anExtensionSize,
897 isArrowsExternal ? aSecondArrowEnd : aSecondAttach,
898 aSecondExtensionDir,
899 aValueString,
900 (AIS_DimensionDisplayMode)theMode,
901 aLabelPosition);
a6eb515f 902 }
d7bffd44 903 break;
904 }
905
906 // dimension arc without text
907 if (theMode != AIS_DDM_Text && aHPosition != LabelPosition_HCenter)
908 {
909 Prs3d_Root::NewGroup (thePresentation);
910
911 drawArc (thePresentation,
912 isArrowsExternal ? aFirstAttach : aFirstArrowEnd,
913 isArrowsExternal ? aSecondAttach : aSecondArrowEnd,
914 myCenter,
915 Abs(GetFlyout ()),
916 (AIS_DimensionDisplayMode)theMode);
917 }
7fd59977 918
d7bffd44 919 // arrows and arrow extensions
920 if (theMode != AIS_DDM_Text)
921 {
922 Prs3d_Root::NewGroup (thePresentation);
923
924 drawArrow (thePresentation, aFirstArrowBegin, gp_Dir (aFirstArrowVec));
925 drawArrow (thePresentation, aSecondArrowBegin, gp_Dir (aSecondArrowVec));
926 }
927
928 if (theMode != AIS_DDM_Text && isArrowsExternal)
929 {
930 Prs3d_Root::NewGroup (thePresentation);
931
932 if (aHPosition != LabelPosition_Left)
933 {
934 drawExtension (thePresentation,
935 anExtensionSize,
936 aFirstArrowEnd,
937 aFirstExtensionDir,
938 THE_EMPTY_LABEL,
939 (AIS_DimensionDisplayMode)theMode,
940 LabelPosition_None);
941 }
942
943 if (aHPosition != LabelPosition_Right)
a6eb515f 944 {
d7bffd44 945 drawExtension (thePresentation,
946 anExtensionSize,
947 aSecondArrowEnd,
948 aSecondExtensionDir,
949 THE_EMPTY_LABEL,
950 (AIS_DimensionDisplayMode)theMode,
951 LabelPosition_None);
a6eb515f 952 }
953 }
7fd59977 954
d7bffd44 955 // flyouts
a6eb515f 956 if (theMode == AIS_DDM_All && myIsFlyoutLines)
957 {
d7bffd44 958 Prs3d_Root::NewGroup (thePresentation);
959
960 Handle(Graphic3d_ArrayOfSegments) aPrimSegments = new Graphic3d_ArrayOfSegments (4);
a6eb515f 961 aPrimSegments->AddVertex (myCenter);
962 aPrimSegments->AddVertex (aFirstAttach);
963 aPrimSegments->AddVertex (myCenter);
964 aPrimSegments->AddVertex (aSecondAttach);
d7bffd44 965
966 Handle(Graphic3d_AspectLine3d) aFlyoutStyle = myDrawer->DimensionAspect()->LineAspect()->Aspect();
967 Prs3d_Root::CurrentGroup (thePresentation)->SetPrimitivesAspect (aFlyoutStyle);
a6eb515f 968 Prs3d_Root::CurrentGroup (thePresentation)->AddPrimitiveArray (aPrimSegments);
7fd59977 969 }
970
a6eb515f 971 setComputed (Standard_True);
7fd59977 972}
62b6361a 973
974//=======================================================================
975//function : computeFlyoutSelection
976//purpose : computes selection for flyouts
977//=======================================================================
62b6361a 978void AIS_AngleDimension::computeFlyoutSelection (const Handle(SelectMgr_Selection)& theSelection,
979 const Handle(AIS_DimensionOwner)& theOwner)
980{
981 if (!myIsFlyoutLines)
d7bffd44 982 {
62b6361a 983 return;
d7bffd44 984 }
62b6361a 985
986 gp_Pnt aFirstAttach = myCenter.Translated (gp_Vec (myCenter, myFirstPoint).Normalized() * GetFlyout());
987 gp_Pnt aSecondAttach = myCenter.Translated (gp_Vec (myCenter, mySecondPoint).Normalized() * GetFlyout());
988 Handle(Select3D_SensitiveGroup) aSensitiveEntity = new Select3D_SensitiveGroup (theOwner);
989 aSensitiveEntity->Add (new Select3D_SensitiveSegment (theOwner, myCenter, aFirstAttach));
990 aSensitiveEntity->Add (new Select3D_SensitiveSegment (theOwner, myCenter, aSecondAttach));
991 theSelection->Add (aSensitiveEntity);
d7bffd44 992}