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
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.
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.
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.
22 #define BUC60655 //GG 22/03/00 Enable to compute correctly
23 // the arrow size at object creation time.
25 #define BUC60915 //GG 05/06/01 Enable to compute the requested arrow size
26 // if any in all dimensions.
28 #include <Standard_NotImplemented.hxx>
30 #include <AIS_AngleDimension.ixx>
33 #include <AIS_DimensionOwner.hxx>
34 #include <AIS_Drawer.hxx>
36 #include <BRepBuilderAPI_MakeFace.hxx>
37 #include <BRepAdaptor_Curve.hxx>
38 #include <BRepAdaptor_Surface.hxx>
39 #include <BRep_Tool.hxx>
42 #include <DsgPrs_AnglePresentation.hxx>
47 #include <Geom2d_Circle.hxx>
48 #include <Geom2d_Curve.hxx>
49 #include <Geom2d_Line.hxx>
50 #include <GeomAPI.hxx>
51 #include <Geom_Circle.hxx>
52 #include <Geom_Line.hxx>
53 #include <Geom_Plane.hxx>
54 #include <Geom_TrimmedCurve.hxx>
55 #include <Geom_Surface.hxx>
56 #include <Geom_CylindricalSurface.hxx>
57 #include <Geom_ConicalSurface.hxx>
58 #include <Geom_SurfaceOfRevolution.hxx>
59 #include <Geom_SurfaceOfLinearExtrusion.hxx>
60 #include <Geom_OffsetSurface.hxx>
62 #include <IntAna2d_AnaIntersection.hxx>
63 #include <IntAna2d_IntPoint.hxx>
64 #include <IntAna_QuadQuadGeo.hxx>
65 #include <IntAna_ResultType.hxx>
67 #include <Precision.hxx>
69 #include <ProjLib.hxx>
71 #include <Prs3d_AngleAspect.hxx>
72 #include <Prs3d_ArrowAspect.hxx>
73 #include <Prs3d_Drawer.hxx>
75 #include <Select3D_SensitiveCurve.hxx>
76 #include <Select3D_SensitiveSegment.hxx>
77 #include <Select3D_SensitiveBox.hxx>
78 #include <SelectMgr_EntityOwner.hxx>
80 #include <TColStd_Array1OfReal.hxx>
83 #include <TopExp_Explorer.hxx>
85 #include <TopoDS_Shape.hxx>
86 #include <TopoDS_Vertex.hxx>
88 #include <UnitsAPI.hxx>
93 #include <gp_Cone.hxx>
96 #include <gp_Pnt2d.hxx>
100 #include <GC_MakeCircle.hxx>
101 #include <GC_MakeConicalSurface.hxx>
102 #include <gce_MakePln.hxx>
103 #include <gce_MakeCone.hxx>
106 //=======================================================================
107 //function : Constructor
108 //purpose : ConeAngle dimension
109 //=======================================================================
111 AIS_AngleDimension::AIS_AngleDimension( const TopoDS_Face& aCone,
112 const Standard_Real aVal,
113 const TCollection_ExtendedString& aText,
114 const gp_Pnt& aPosition,
115 const DsgPrs_ArrowSide /*aSymbolPrs*/,
116 const Standard_Real anArrowSize):
122 myPosition = aPosition;
123 mySymbolPrs = DsgPrs_AS_BOTHAR;
124 myAutomaticPosition = Standard_True;
126 SetArrowSize( anArrowSize );
128 myArrowSize = anArrowSize;
132 //=======================================================================
133 //function : Constructor
134 //purpose : ConeAngle dimension
135 //=======================================================================
137 AIS_AngleDimension::AIS_AngleDimension( const TopoDS_Face& aCone,
138 const Standard_Real aVal,
139 const TCollection_ExtendedString& aText):
143 cout << "Call new AngleDimension for cone's angle" << endl;
146 gp_Pnt tmpPnt(0., 0., 0.);
152 mySymbolPrs = DsgPrs_AS_BOTHAR;
153 myAutomaticPosition = Standard_True;
160 //=======================================================================
161 //function : Constructor
162 //purpose : TwoEdgesAngle dimension
163 //=======================================================================
166 AIS_AngleDimension::AIS_AngleDimension(const TopoDS_Edge& aFirstEdge,
167 const TopoDS_Edge& aSecondEdge,
168 const Handle (Geom_Plane)& aPlane,
169 const Standard_Real aVal,
170 const TCollection_ExtendedString& aText)
175 cout << endl << "Call new AngleDimension for edges, default" << endl;
178 myFShape = aFirstEdge;
179 mySShape = aSecondEdge;
183 mySymbolPrs = DsgPrs_AS_BOTHAR;
184 myAutomaticPosition = Standard_True;
186 myArrowSize = myVal / 100.;
189 //=======================================================================
190 //function : Constructor
191 //purpose : TwoEdgesAngle dimension (avec position et texte)
192 //=======================================================================
194 AIS_AngleDimension::AIS_AngleDimension( const TopoDS_Edge& aFirstEdge,
195 const TopoDS_Edge& aSecondEdge,
196 const Handle (Geom_Plane)& aPlane,
197 const Standard_Real aVal,
198 const TCollection_ExtendedString& aText,
199 const gp_Pnt& aPosition,
200 const DsgPrs_ArrowSide aSymbolPrs,
201 const Standard_Real anArrowSize):
205 cout << endl << "Call new AngleDimension for edges" << endl;
208 myFShape = aFirstEdge;
209 mySShape = aSecondEdge;
213 mySymbolPrs = aSymbolPrs;
214 myAutomaticPosition = Standard_False;
216 SetArrowSize( anArrowSize );
218 myArrowSize = anArrowSize;
220 myPosition = aPosition;
224 //=======================================================================
225 //function : Constructor
226 //purpose : TwoPlanarFacesAngle dimension
227 //=======================================================================
229 AIS_AngleDimension::AIS_AngleDimension( const TopoDS_Face& aFirstFace,
230 const TopoDS_Face& aSecondFace,
231 const gp_Ax1& anAxis,
232 const Standard_Real aVal,
233 const TCollection_ExtendedString& aText):
238 cout << endl << "Call new AngleDimension for planar faces, default" << endl;
241 myFShape = aFirstFace;
242 mySShape = aSecondFace;
244 AIS::GetPlaneFromFace( aFirstFace, myFirstPlane, myFirstBasisSurf, myFirstSurfType, myFirstOffset );
245 AIS::GetPlaneFromFace( aSecondFace, mySecondPlane, mySecondBasisSurf, mySecondSurfType, mySecondOffset );
247 //POP init champ myPlane
248 myPlane = new Geom_Plane(myFirstPlane);
252 mySymbolPrs = DsgPrs_AS_BOTHAR;
253 myAutomaticPosition = Standard_True;
255 myArrowSize = myVal / 100.;
258 //=======================================================================
259 //function : Constructor
260 //purpose : TwoPlanarFacesAngle dimension (avec position et texte)
261 //=======================================================================
263 AIS_AngleDimension::AIS_AngleDimension( const TopoDS_Face& aFirstFace,
264 const TopoDS_Face& aSecondFace,
265 const gp_Ax1& anAxis,
266 const Standard_Real aVal,
267 const TCollection_ExtendedString& aText,
268 const gp_Pnt& aPosition,
269 const DsgPrs_ArrowSide aSymbolPrs,
270 const Standard_Real anArrowSize):
275 cout << endl << "Call new AngleDimension for planar faces" << endl;
278 myFShape = aFirstFace;
279 mySShape = aSecondFace;
281 AIS::GetPlaneFromFace( aFirstFace, myFirstPlane, myFirstBasisSurf, myFirstSurfType, myFirstOffset );
282 AIS::GetPlaneFromFace( aSecondFace, mySecondPlane, mySecondBasisSurf, mySecondSurfType, mySecondOffset );
284 //POP init champ myPlane
285 myPlane = new Geom_Plane(myFirstPlane);
289 mySymbolPrs = aSymbolPrs;
290 myAutomaticPosition = Standard_False;
292 SetArrowSize( anArrowSize );
294 myArrowSize = anArrowSize;
296 myPosition = aPosition;
300 //=======================================================================
301 //function : AIS_AngleDimension
302 //purpose : Two curvilinear faces dimension
303 //=======================================================================
305 AIS_AngleDimension::AIS_AngleDimension( const TopoDS_Face& aFFace,
306 const TopoDS_Face& aSFace,
307 const Standard_Real aVal,
308 const TCollection_ExtendedString& aText ):
312 cout << endl << "Call new AngleDimension for curvilinear faces, default" << endl;
315 SetFirstShape( aFFace );
316 SetSecondShape( aSFace );
320 mySymbolPrs = DsgPrs_AS_BOTHAR;
321 myAutomaticPosition = Standard_True;
323 myArrowSize = myVal / 100.;
326 //=======================================================================
327 //function : AIS_AngleDimension
329 //=======================================================================
331 AIS_AngleDimension::AIS_AngleDimension( const TopoDS_Face& aFFace,
332 const TopoDS_Face& aSFace,
333 const Standard_Real aVal,
334 const TCollection_ExtendedString& aText,
335 const gp_Pnt& aPosition,
336 const DsgPrs_ArrowSide aSymbolPrs,
337 const Standard_Real anArrowSize):
341 cout << endl << "Call new AngleDimension for curvilinear faces" << endl;
344 SetFirstShape( aFFace );
345 SetSecondShape( aSFace );
349 mySymbolPrs = DsgPrs_AS_BOTHAR;
350 myAutomaticPosition = Standard_True;
352 mySymbolPrs = aSymbolPrs;
353 myAutomaticPosition = Standard_False;
355 SetArrowSize( anArrowSize );
357 myArrowSize = anArrowSize;
359 myPosition = aPosition;
363 //=======================================================================
364 //function : SetConeFace
366 //=======================================================================
368 void AIS_AngleDimension::SetConeFace( const TopoDS_Face& aConeFace )
371 myAutomaticPosition = Standard_True;
375 //=======================================================================
376 //function : SetFirstShape
378 //=======================================================================
380 void AIS_AngleDimension::SetFirstShape( const TopoDS_Shape& aFShape )
384 if (myFShape.ShapeType() == TopAbs_FACE)
386 AIS::GetPlaneFromFace( TopoDS::Face( myFShape ),
392 if (myFirstSurfType == AIS_KOS_Cylinder)
393 myAxis = (Handle( Geom_CylindricalSurface )::DownCast( myFirstBasisSurf ))->Cylinder().Axis();
394 else if (myFirstSurfType == AIS_KOS_Cone)
395 myAxis = (Handle( Geom_ConicalSurface )::DownCast( myFirstBasisSurf ))->Cone().Axis();
396 else if (myFirstSurfType == AIS_KOS_Revolution)
397 myAxis = (Handle( Geom_SurfaceOfRevolution )::DownCast( myFirstBasisSurf ))->Axis();
398 else if (myFirstSurfType == AIS_KOS_Extrusion)
400 myAxis.SetDirection((Handle( Geom_SurfaceOfLinearExtrusion )::DownCast( myFirstBasisSurf ))
402 //myAxis.SetLocation( ??? );
407 //=======================================================================
408 //function : SetSecondShape
410 //=======================================================================
412 void AIS_AngleDimension::SetSecondShape( const TopoDS_Shape& aSShape )
416 if (myFShape.ShapeType() == TopAbs_FACE)
417 AIS::GetPlaneFromFace( TopoDS::Face( mySShape ),
427 ///=======================================================================
430 //=======================================================================
432 void AIS_AngleDimension::Compute(const Handle(PrsMgr_PresentationManager3d)&,
433 const Handle(Prs3d_Presentation)& aPresentation,
434 const Standard_Integer)
436 aPresentation->Clear();
440 // cout << "Computing for cone' angle " << endl;
441 ComputeConeAngle(aPresentation);
444 switch (myFShape.ShapeType()) {
447 // cas angle entre deux faces
448 ComputeTwoFacesAngle(aPresentation);
453 // cas angle entre deux edges
454 ComputeTwoEdgesAngle(aPresentation);
463 //=======================================================================
465 //purpose : : to avoid warning
466 //=======================================================================
468 void AIS_AngleDimension::Compute(const Handle(Prs3d_Projector)& aProjector,
469 const Handle(Prs3d_Presentation)& aPresentation)
471 // Standard_NotImplemented::Raise("AIS_AngleDimension::Compute(const Handle(Prs3d_Projector)&,const Handle(Prs3d_Presentation)&)");
472 PrsMgr_PresentableObject::Compute( aProjector , aPresentation ) ;
475 void AIS_AngleDimension::Compute(const Handle_Prs3d_Projector& aProjector, const Handle_Geom_Transformation& aTransformation, const Handle_Prs3d_Presentation& aPresentation)
477 // Standard_NotImplemented::Raise("AIS_AngleDimension::Compute(const Handle_Prs3d_Projector&, const Handle_Geom_Transformation&, const Handle_Prs3d_Presentation&)");
478 PrsMgr_PresentableObject::Compute( aProjector , aTransformation , aPresentation ) ;
481 //=======================================================================
482 //function : ComputeSelection
484 //=======================================================================
486 void AIS_AngleDimension::ComputeSelection(const Handle(SelectMgr_Selection)& aSelection,
487 const Standard_Integer)
490 if ( myNbShape == 1 )
492 // cout << "Computing selection for cone's angle " << endl;
493 ComputeConeAngleSelection(aSelection);
498 if (myFShape.IsNull()) return;
500 if (myFShape.ShapeType() == TopAbs_FACE )
501 Compute3DSelection(aSelection);
503 Compute2DSelection(aSelection);
506 Handle( SelectMgr_EntityOwner ) own = new SelectMgr_EntityOwner( this, 7 );
507 Standard_Real size(Min(myVal/100.+1.e-6,myArrowSize+1.e-6));
508 Handle( Select3D_SensitiveBox ) box = new Select3D_SensitiveBox( own,
512 myPosition.X() + size,
513 myPosition.Y() + size,
514 myPosition.Z() + size);
515 aSelection->Add(box);
518 //=======================================================================
519 //function : ComputeConeAngle
521 //=======================================================================
523 void AIS_AngleDimension::ComputeConeAngle(const Handle(Prs3d_Presentation)& aPresentation)
525 if( myCone.IsNull() ) return;
531 Handle( Geom_Surface ) aSurf; //a surface from the Face
532 Handle( Geom_OffsetSurface ) aOffsetSurf;
533 Handle( Geom_ConicalSurface ) aConicalSurf;
534 Handle( Geom_SurfaceOfRevolution ) aRevSurf;
535 Handle( Geom_Line ) aLine;
536 BRepAdaptor_Surface tmpSurf(myCone);
538 AIS_KindOfSurface aSurfType;
539 Standard_Real Offset = 0. ;
540 Handle( Standard_Type ) aType;
542 Standard_Real maxV = tmpSurf.FirstVParameter();
543 Standard_Real minV = tmpSurf.LastVParameter();
546 AIS::GetPlaneFromFace( myCone, aPln, aSurf, aSurfType, Offset );
548 if ( aSurfType == AIS_KOS_Revolution ) { //surface of revolution
550 aRevSurf = Handle( Geom_SurfaceOfRevolution )::DownCast( aSurf );
551 gp_Lin ln( aRevSurf->Axis() );
552 Handle( Geom_Curve ) tmpCrv = aRevSurf->BasisCurve();
553 if ( tmpCrv ->DynamicType() != STANDARD_TYPE(Geom_Line) ) return; //Must be a part of line
556 gp_Pnt fst = tmpSurf.Value(0., minV);
557 gp_Pnt lst = tmpSurf.Value(0., maxV);
559 gp_Vec vec1(fst, lst);
561 par = ElCLib::Parameter( ln, fst );
562 gp_Pnt fst2 = ElCLib::Value( par, ln ); //projection fst on ln
563 par = ElCLib::Parameter( ln, lst );
564 gp_Pnt lst2 = ElCLib::Value( par, ln ); //projection lst on ln
566 gp_Vec vec2(fst2, lst2);
568 // Check if two parts of revolution are parallel ( it's a cylinder ) or normal (it's a circle )
569 if( vec1.IsParallel( vec2,Precision::Angular() ) || vec1.IsNormal( vec2,Precision::Angular() ) ) return;
571 gce_MakeCone mkCone(aRevSurf->Axis(), fst, lst);
572 aCone = mkCone.Value();
576 aType = aSurf->DynamicType();
577 if ( aType == STANDARD_TYPE(Geom_OffsetSurface) || Offset > 0.01 ) { //offset surface
578 aOffsetSurf = new Geom_OffsetSurface (aSurf, Offset);
579 aSurf = aOffsetSurf->Surface();
580 BRepBuilderAPI_MakeFace mkFace(aSurf, Precision::Confusion());
582 if( !mkFace.IsDone() ) return;
583 tmpSurf.Initialize( mkFace.Face() );
586 aCone = tmpSurf.Cone();
587 aConicalSurf = Handle( Geom_ConicalSurface)::DownCast( aSurf );
588 Apex = aConicalSurf->Apex();
591 Handle(Geom_Curve) aCurve; //A circle where the angle is drawn
592 if ( myAutomaticPosition ) {
593 Standard_Real midV = ( minV + maxV ) / 2.5;
595 aCurve = aSurf->VIso(midV);
596 myCircle = Handle(Geom_Circle)::DownCast(aCurve)->Circ();
598 myPosition = ElCLib::Value(M_PI / 2.0, myCircle);
599 myAutomaticPosition = Standard_False;
603 ElSLib::Parameters(aCone, myPosition, U, V);
604 aCurve = aSurf->VIso(V);
605 myCircle = Handle(Geom_Circle)::DownCast(aCurve)->Circ();
608 //__________________________________________________________________
609 aCurve = aSurf->VIso(maxV);
610 gp_Circ CircVmax = Handle(Geom_Circle)::DownCast(aCurve)->Circ();
611 aCurve = aSurf->VIso(minV);
612 gp_Circ CircVmin = Handle(Geom_Circle)::DownCast(aCurve)->Circ();
613 //__________________________________________________________________
615 if( CircVmax.Radius() < CircVmin.Radius() ) {
616 gp_Circ tmpCirc = CircVmax;
621 DsgPrs_AnglePresentation::Add(aPresentation, myDrawer, myVal,
622 myText, myCircle, myPosition, Apex, CircVmin, CircVmax, myArrowSize);
623 // cout << "ComputeConeAngle is over" << endl;
627 //=======================================================================
628 //function : ComputeTwoFacesAngle
630 //=======================================================================
632 void AIS_AngleDimension::ComputeTwoFacesAngle(const Handle(Prs3d_Presentation)& aPresentation)
634 if (myFirstSurfType == AIS_KOS_Plane)
635 ComputeTwoPlanarFacesAngle( aPresentation );
637 ComputeTwoCurvilinearFacesAngle( aPresentation );
640 //=======================================================================
641 //function : ComputeTwoCurvilinearFacesAngle
643 //=======================================================================
645 void AIS_AngleDimension::ComputeTwoCurvilinearFacesAngle(const Handle(Prs3d_Presentation)& aPresentation)
647 AIS::ComputeAngleBetweenCurvilinearFaces( TopoDS::Face( myFShape ),
648 TopoDS::Face( mySShape ),
663 if (myAutomaticPosition && myIsSetBndBox)
664 myPosition = AIS::TranslatePointToBound( myPosition, gp_Dir( gp_Vec( myCenter, myPosition ) ), myBndBox );
666 Handle(Prs3d_AngleAspect) la = myDrawer->AngleAspect();
667 Handle(Prs3d_ArrowAspect) arr = la->ArrowAspect();
669 if( !myArrowSizeIsDefined ) {
671 Standard_Real arrsize = myCenter.Distance( myPosition );
673 if ( (myArrowSize-arrsize) < 0.1 ) arrsize = myArrowSize;
674 if (arrsize == 0.) arrsize = 1.;
676 myArrowSize = arrsize;
678 arr->SetLength( myArrowSize );
680 arr->SetLength(arrsize);
684 if (myVal <= Precision::Angular() || Abs( M_PI-myVal ) <= Precision::Angular())
685 DsgPrs_AnglePresentation::Add(aPresentation,
694 myPlane->Pln().Axis().Direction(),
695 Standard_False, // not plane
700 DsgPrs_AnglePresentation::Add(aPresentation,
710 Standard_False, // not plane
716 //=======================================================================
717 //function : ComputeTwoPlanarFacesAngle
719 //=======================================================================
721 void AIS_AngleDimension::ComputeTwoPlanarFacesAngle( const Handle( Prs3d_Presentation )& aPresentation )
723 AIS::ComputeAngleBetweenPlanarFaces( TopoDS::Face( myFShape ),
724 TopoDS::Face( mySShape ),
735 if (myAutomaticPosition && myIsSetBndBox)
736 myPosition = AIS::TranslatePointToBound( myPosition, gp_Dir( gp_Vec( myCenter, myPosition ) ), myBndBox );
738 Handle(Prs3d_AngleAspect) la = myDrawer->AngleAspect();
739 Handle(Prs3d_ArrowAspect) arr = la->ArrowAspect();
741 if( !myArrowSizeIsDefined ) {
743 Standard_Real arrsize = myCenter.Distance( myPosition );
745 if ( (myArrowSize-arrsize) < 0.1 ) arrsize = myArrowSize;
746 if (arrsize == 0.) arrsize = 1.;
748 myArrowSize = arrsize;
750 arr->SetLength( myArrowSize );
752 arr->SetLength(arrsize);
756 DsgPrs_AnglePresentation::Add(aPresentation,
773 //=======================================================================
774 //function : ComputeTwoEdgesAngle
776 //=======================================================================
778 void AIS_AngleDimension::ComputeTwoEdgesAngle(const Handle(Prs3d_Presentation)& aPresentation)
780 BRepAdaptor_Curve cu1(TopoDS::Edge(myFShape));
781 BRepAdaptor_Curve cu2(TopoDS::Edge(mySShape));
782 if ((cu1.GetType() != GeomAbs_Line) || (cu2.GetType() != GeomAbs_Line)) return;
785 BRepBuilderAPI_MakeFace makeface(myPlane->Pln());
786 TopoDS_Face face(makeface.Face());
787 BRepAdaptor_Surface adp(makeface.Face());
790 Handle(Geom_Line) geom_lin1,geom_lin2;
791 gp_Pnt ptat11,ptat12,ptat21,ptat22;//,pint3d;
792 Standard_Boolean isInfinite1,isInfinite2;
793 Handle(Geom_Curve) extCurv;
794 Standard_Integer copyOfMyExtShape = myExtShape;
795 if (!AIS::ComputeGeometry(TopoDS::Edge(myFShape),
796 TopoDS::Edge(mySShape),
810 // Temporary: computation of myVal
811 // myVal = Abs(geom_lin1->Lin().Angle( geom_lin2->Lin())); // Pb with angles JPR
813 if (copyOfMyExtShape != 0) myExtShape = copyOfMyExtShape;
815 // 2d lines => projection of 3d on current plane
818 Handle(Geom2d_Curve) geoC1 = GeomAPI::To2d(geom_lin1,myPlane->Pln());
819 Handle(Geom2d_Line) lin1_2d = *((Handle(Geom2d_Line)*)& geoC1);
820 Handle(Geom2d_Curve) geoC2 = GeomAPI::To2d(geom_lin2,myPlane->Pln());
821 Handle(Geom2d_Line) lin2_2d = *((Handle(Geom2d_Line)*)& geoC2);
824 if( !myArrowSizeIsDefined ) {
826 Standard_Real arrSize1(myArrowSize),arrSize2(myArrowSize);
827 if (!isInfinite1) arrSize1 = ptat11.Distance(ptat12)/100.;
828 if (!isInfinite2) arrSize2 = ptat21.Distance(ptat22)/100.;
830 myArrowSize = Min(myArrowSize,Max(arrSize1,arrSize2));
832 myArrowSize = Min(myArrowSize,Min(arrSize1,arrSize2));
839 // Processing in case of 2 parallel straight lines
840 if (lin1_2d->Lin2d().Direction()
841 .IsParallel(lin2_2d->Lin2d().Direction(),Precision::Angular())) {
842 ComputeTwoEdgesNullAngle(aPresentation,
847 isInfinite1,isInfinite2);
850 // Processing in case of 2 non-parallel straight lines
852 ComputeTwoEdgesNotNullAngle(aPresentation,
859 isInfinite1,isInfinite2);
861 if ( (myExtShape != 0) && !extCurv.IsNull()) {
863 if ( myExtShape == 1 ) {
868 aPresentation->SetInfiniteState(isInfinite1);
869 ComputeProjEdgePresentation(aPresentation,TopoDS::Edge(myFShape),geom_lin1,pf,pl);
876 aPresentation->SetInfiniteState(isInfinite2);
877 ComputeProjEdgePresentation(aPresentation,TopoDS::Edge(mySShape),geom_lin2,pf,pl);
883 //=======================================================================
884 //function : ComputeTwoEdgesNotNullAngle
886 //=======================================================================
888 void AIS_AngleDimension::ComputeTwoEdgesNotNullAngle(const Handle(Prs3d_Presentation)& aPresentation,
889 const Handle(Geom_Line)& l1,
890 const Handle(Geom_Line)& l2,
891 const gp_Pnt& ptat11,
892 const gp_Pnt& ptat12,
893 const gp_Pnt& ptat21,
894 const gp_Pnt& ptat22,
895 const Standard_Boolean isInfinite1,
896 const Standard_Boolean isInfinite2)
899 BRepBuilderAPI_MakeFace makeface(myPlane->Pln());
900 TopoDS_Face face(makeface.Face());
901 BRepAdaptor_Surface adp(makeface.Face());
902 // 2d lines => projection of 3d on current plane
903 Handle(Geom2d_Curve) geoC1 = GeomAPI::To2d(l1,myPlane->Pln());
904 const Handle(Geom2d_Line)& l1_2d = *((Handle(Geom2d_Line)*)& geoC1);
905 Handle(Geom2d_Curve) geoC2 = GeomAPI::To2d(l2,myPlane->Pln());
906 const Handle(Geom2d_Line)& l2_2d = *((Handle(Geom2d_Line)*)& geoC2);
908 //----------------------------------------------------------
909 // Computation of myCenter
910 //----------------------------------------------------------
911 IntAna2d_AnaIntersection inter(l1_2d->Lin2d(),l2_2d->Lin2d());
912 if (!inter.IsDone()) return;
913 if (!inter.NbPoints()) return;
915 gp_Pnt2d pint(inter.Point(1).Value());
916 myCenter = adp.Value(pint.X(),pint.Y());
918 //----------------------------------------------------------
919 // Computation of the 2 directions
920 //----------------------------------------------------------
923 if (myCenter.SquareDistance(ptat11) > myCenter.SquareDistance(ptat12)) d1 = gp_Dir(gp_Vec(myCenter,ptat11));
924 else d1 = gp_Dir(gp_Vec(myCenter,ptat12));
926 else d1 = l1->Lin().Direction();
929 if (myCenter.SquareDistance(ptat21) > myCenter.SquareDistance(ptat22)) d2 = gp_Dir(gp_Vec(myCenter,ptat21));
930 else d2 = gp_Dir(gp_Vec(myCenter,ptat22));
932 else d2 = l2->Lin().Direction();
934 Standard_Boolean In1(Standard_False);
935 Standard_Boolean In2(Standard_False);
936 if ( !(Abs(d1.Angle(d2) - Abs(myVal)) <= Precision::Confusion())
937 && (Abs(myVal) < M_PI) ) {
938 Standard_Real parcent1 = ElCLib::Parameter(l1->Lin(), myCenter);
939 Standard_Real par11 = ElCLib::Parameter(l1->Lin(), ptat11);
940 Standard_Real par12 = ElCLib::Parameter(l1->Lin(), ptat12);
941 if ( par11 < par12) {
942 if ( ( parcent1> par11) && (parcent1< par12)) {
948 if ( ( parcent1> par12) && (parcent1< par11)) {
963 gp_Lin gpl1 = l1->Lin();
964 gp_Lin gpl2 = l2->Lin();
965 theaxis = gp_Lin(myCenter,myFDir^mySDir);
972 TColStd_Array1OfReal tabdist(1,4);
974 tabdist(1) = theaxis.Distance(ptat11);
975 tabdist(2) = theaxis.Distance(ptat12);
978 tabdist(1) = tabdist(2) = 0.;
982 tabdist(3) = theaxis.Distance(ptat21);
983 tabdist(4) = theaxis.Distance(ptat22);
986 tabdist(3) = tabdist(4) = 0.;
989 if (myAutomaticPosition) {
990 Standard_Real length_1(RealLast());
991 if (!isInfinite1) length_1 = .75*Abs(tabdist(2)-tabdist(1))+Min(tabdist(1),tabdist(2));
993 Standard_Real length_2(RealLast());
994 if (!isInfinite2) length_2 = .75*Abs(tabdist(4)-tabdist(3))+Min(tabdist(3),tabdist(4));
995 Standard_Real theLength(Min(length_1,length_2));
996 if (Precision::IsInfinite(theLength)) theLength = 50.;
998 myFAttach = myCenter.Translated(gp_Vec(d1)*theLength);
999 mySAttach = myCenter.Translated(gp_Vec(d2)*theLength);
1002 Standard_Real par_p1_attach(ElCLib::Parameter(gpl1,myFAttach));
1003 Standard_Real par11 = ElCLib::Parameter(gpl1,ptat11);
1004 Standard_Real par12 = ElCLib::Parameter(gpl1,ptat12);
1005 if (par_p1_attach > par11 && par_p1_attach > par12) {
1006 par_p1_attach = Max(par11,par12);
1007 myFAttach = ElCLib::Value(par_p1_attach,gpl1);
1009 else if (par_p1_attach < par11 && par_p1_attach < par12) {
1010 par_p1_attach = Min(par11,par12);
1011 myFAttach = ElCLib::Value(par_p1_attach,gpl1);
1016 Standard_Real par_p2_attach(ElCLib::Parameter(gpl2,mySAttach));
1017 Standard_Real par21 = ElCLib::Parameter(gpl2,ptat21);
1018 Standard_Real par22 = ElCLib::Parameter(gpl2,ptat22);
1019 if (par_p2_attach > par21 && par_p2_attach > par22) {
1020 par_p2_attach = Max(par21,par22);
1021 mySAttach = ElCLib::Value(par_p2_attach,gpl2);
1023 else if (par_p2_attach < par21 && par_p2_attach < par22) {
1024 par_p2_attach = Min(par21,par22);
1025 mySAttach = ElCLib::Value(par_p2_attach,gpl2);
1028 if ( myVal < M_PI) curpos.SetXYZ(.5*(myFAttach.XYZ()+mySAttach.XYZ()));
1030 curpos.SetXYZ(.5*(myFAttach.XYZ()+mySAttach.XYZ()));
1031 gp_Vec transl(curpos, myCenter);
1033 curpos.Translate(transl);
1036 gp_Ax2 ax(myCenter,myFDir.Crossed(mySDir),myFDir);
1037 gp_Circ circle(ax,theLength);
1038 Standard_Real par = ElCLib::Parameter(circle,curpos);
1039 curpos = ElCLib::Value(par,circle);
1041 // small offset like in LengthDimension
1042 gp_Vec transl(myCenter, curpos);
1044 curpos.Translate(transl);
1047 curpos = AIS::TranslatePointToBound( curpos, gp_Dir( gp_Vec( myCenter, curpos ) ), myBndBox );
1049 myPosition = curpos;
1050 myAutomaticPosition = Standard_True;
1054 // point is projected on the plane
1055 gp_Pnt2d pointOnPln(ProjLib::Project(myPlane->Pln(),myPosition));
1056 myPosition = BRepAdaptor_Surface(BRepBuilderAPI_MakeFace(myPlane->Pln()).Face()).Value(pointOnPln.X(),pointOnPln.Y());
1057 curpos = myPosition;
1058 Standard_Real dist(curpos.Distance(myCenter));
1059 if (dist<=Precision::Confusion()) {
1060 gp_XYZ delta(1.,1.,1.);
1061 curpos.SetXYZ(curpos.XYZ()+delta);
1062 dist = curpos.Distance(myCenter);
1064 // To learn if it is necessary to take distance -dist or not
1065 // it is necessary to know if we are in the sector opposite to the angle
1066 // if not : we are in the opposite sector if the coordinates
1067 // of curpos in point (d1,d2) are negative
1068 gp_Ax2 ax(myCenter,myFDir.Crossed(mySDir),myFDir);
1069 gp_Circ circle(ax,dist);
1071 // gp_Pnt p1(myCenter.Translated(gp_Vec(d1)*dist));
1073 gp_Pnt p2(myCenter.Translated(gp_Vec(d2)*dist));
1074 Standard_Real uc1 = 0;
1075 Standard_Real uc2 = ElCLib::Parameter(circle, p2 );
1076 Standard_Real uco = ElCLib::Parameter(circle, curpos );
1077 Standard_Real udeb = uc1;
1078 Standard_Real ufin = uc2;
1080 if (Abs(myVal)<M_PI) {
1081 // test if uco is in the opposite sector
1082 if (uco > udeb+M_PI && uco < ufin+M_PI){
1088 gp_Pnt p1_attach(myCenter.Translated(gp_Vec(d1)*dist));
1089 gp_Pnt p2_attach(myCenter.Translated(gp_Vec(d2)*dist));
1092 Standard_Real par_p1_attach(ElCLib::Parameter(gpl1,p1_attach));
1093 Standard_Real par11 = ElCLib::Parameter(gpl1,ptat11);
1094 Standard_Real par12 = ElCLib::Parameter(gpl1,ptat12);
1095 if (par_p1_attach > par11 && par_p1_attach > par12) {
1096 par_p1_attach = Max(par11,par12);
1097 p1_attach = ElCLib::Value(par_p1_attach,gpl1);
1099 else if (par_p1_attach < par11 && par_p1_attach < par12) {
1100 par_p1_attach = Min(par11,par12);
1101 p1_attach = ElCLib::Value(par_p1_attach,gpl1);
1104 myFAttach = p1_attach;
1107 Standard_Real par_p2_attach(ElCLib::Parameter(gpl2,p2_attach));
1108 Standard_Real par21 = ElCLib::Parameter(gpl2,ptat21);
1109 Standard_Real par22 = ElCLib::Parameter(gpl2,ptat22);
1110 if (par_p2_attach > par21 && par_p2_attach > par22) {
1111 par_p2_attach = Max(par21,par22);
1112 p2_attach = ElCLib::Value(par_p2_attach,gpl2);
1114 else if (par_p2_attach < par21 && par_p2_attach < par22) {
1115 par_p2_attach = Min(par21,par22);
1116 p2_attach = ElCLib::Value(par_p2_attach,gpl2);
1119 mySAttach = p2_attach;
1121 myAxis = theaxis.Position();
1123 //--------------------------------------------------------
1124 // Computation of the presentation
1125 //--------------------------------------------------------
1126 Handle(Prs3d_AngleAspect) la = myDrawer->AngleAspect();
1127 Handle(Prs3d_ArrowAspect) arr = la->ArrowAspect();
1129 arr->SetLength(myArrowSize);
1131 DsgPrs_AnglePresentation::Add(aPresentation,
1146 //=======================================================================
1147 //function : ComputeTwoEdgesNullAngle
1148 //purpose : compute the presentation of a angle dimension if it's null.
1149 // -> the aim of the computation is to have a constant radius
1150 // during the dimension moving : the radius is independant
1151 // of the cursor position, it's equal to a arbitrary value
1152 //=======================================================================
1154 void AIS_AngleDimension::ComputeTwoEdgesNullAngle(const Handle(Prs3d_Presentation)& aPresentation,
1155 const Handle(Geom_Line)& l1,
1156 const Handle(Geom_Line)& l2,
1157 const gp_Pnt& ptat11,
1158 const gp_Pnt& ptat12,
1159 const gp_Pnt& ptat21,
1160 const gp_Pnt& ptat22,
1161 const Standard_Boolean isInfinite1,
1162 const Standard_Boolean isInfinite2)
1165 BRepBuilderAPI_MakeFace makeface(myPlane->Pln());
1166 TopoDS_Face face(makeface.Face());
1167 BRepAdaptor_Surface adp(makeface.Face());
1168 // 2d lines => projection of 3d on current plane
1169 Handle(Geom2d_Curve) geoC1 = GeomAPI::To2d(l1,myPlane->Pln());
1170 Handle(Geom2d_Line) l1_2d = *((Handle(Geom2d_Line)*)& geoC1);
1171 Handle(Geom2d_Curve) geoC2 = GeomAPI::To2d(l2,myPlane->Pln());
1172 Handle(Geom2d_Line) l2_2d = *((Handle(Geom2d_Line)*)& geoC2);
1174 gp_Lin gpl1 = l1->Lin();
1175 gp_Lin gpl2 = l2->Lin();
1177 //------------------------------------------------------------
1178 // Computation of myCenter
1179 // -> Point located on the median of 2 straight lines,
1180 // is calculated as located between 2 closest points
1181 // of each straight line.
1182 //-----------------------------------------------------------
1183 // theLength : radius of the future circle
1184 Standard_Real theLength = gpl1.Distance(gpl2.Location());
1185 // processing of the particular case when 2 straight lines are coincident
1186 Standard_Boolean SameLines(Standard_False);
1187 if ( theLength <= Precision::Confusion()) {
1188 SameLines = Standard_True;
1190 if (!isInfinite2) theLength = 0.75 * Max( ptat11.Distance(ptat12), ptat21.Distance(ptat22));
1191 else theLength = 0.75*ptat11.Distance(ptat12);
1194 if (!isInfinite2) theLength = 0.75*ptat21.Distance(ptat22);
1195 else theLength = 50.;
1198 else theLength = theLength*8/10;
1200 gp_Pnt pmin1 ,pmin2;
1201 if (!isInfinite1 && !isInfinite2) {
1202 pmin1 = ptat11; pmin2 = ptat21;
1203 Standard_Real dis = ptat11.Distance(ptat21);
1204 Standard_Real dis2 = ptat11.Distance(ptat22);
1210 dis2 = ptat12.Distance(ptat22);
1216 dis2 = ptat12.Distance(ptat21);
1222 myCenter.SetXYZ( (pmin1.XYZ() + pmin2.XYZ()) / 2. );
1225 gp_Pnt pntOnl1 = gpl1.Location();
1226 gp_Pnt pntOnl2 = ElCLib::Value(ElCLib::Parameter(gpl1,pntOnl1),gpl2);
1227 myCenter.SetXYZ( (pntOnl1.XYZ() + pntOnl2.XYZ()) / 2. );
1234 if (myCenter.SquareDistance(ptat11) > myCenter.SquareDistance(ptat12)) d1 = gp_Dir(gp_Vec(myCenter,ptat11));
1235 else d1 = gp_Dir(gp_Vec(myCenter,ptat12));
1237 else d1 = gpl1.Direction();
1240 if (myCenter.SquareDistance(ptat21) > myCenter.SquareDistance(ptat22)) d2 = gp_Dir(gp_Vec(myCenter,ptat21));
1241 else d2 = gp_Dir(gp_Vec(myCenter,ptat22));
1243 else d2 = gpl2.Direction();
1246 if ( SameLines ) theaxis = myPlane->Pln().Axis().Direction();
1248 theaxis = gp_Dir(d1^d2);
1249 gp_Vec V1(d1); gp_Vec V2(d2);
1250 if ( V1.CrossMagnitude(V2) < 0 ) theaxis.Reverse();
1253 gp_Pnt curpos; // cursor position
1254 TColStd_Array1OfReal tabdist(1,4);
1255 gp_Pnt P1, P2; // points at intersection of the circle with 2 straight lines
1257 if (myAutomaticPosition) {
1259 tabdist(1) = myCenter.Distance(ptat11);
1260 tabdist(2) = myCenter.Distance(ptat12);
1263 tabdist(1) = tabdist(2) = 0.;
1266 tabdist(3) = myCenter.Distance(ptat21);
1267 tabdist(4) = myCenter.Distance(ptat22);
1270 tabdist(3) = tabdist(4) = 0.;
1273 Standard_Real dist1(RealLast());
1274 if (!isInfinite1) dist1 = Max(tabdist(1),tabdist(2));
1275 Standard_Real dist2(RealLast());
1276 if (!isInfinite2) dist2 = Max(tabdist(3),tabdist(4));
1278 myFAttach = myCenter;
1279 mySAttach = myCenter;
1283 myCenter.Translate(gp_Vec(d1)*theLength);
1285 // calculate attachments of the face
1286 // -> they are points of intersection if
1287 // intersection is outside of the edges
1288 Standard_Real pparam = ElCLib::Parameter(gpl1,myFAttach);
1289 Standard_Real pparam1 = ElCLib::Parameter(gpl1,ptat11);
1290 Standard_Real pparam2 = ElCLib::Parameter(gpl1,ptat12);
1292 if ( pparam1 < pparam2 ) {
1293 if ( pparam < pparam1 ) myFAttach = ptat11;
1294 else if ( pparam > pparam2) myFAttach = ptat12;
1297 if ( pparam < pparam2) myFAttach = ptat12;
1298 else if ( pparam > pparam1) myFAttach = ptat11;
1302 pparam = ElCLib::Parameter(gpl2,myFAttach);
1303 pparam1 = ElCLib::Parameter(gpl2,ptat21);
1304 pparam2 = ElCLib::Parameter(gpl2,ptat22);
1305 if ( pparam1 < pparam2 ) {
1306 if ( pparam < pparam1 ) mySAttach = ptat21;
1307 else if ( pparam > pparam2) mySAttach = ptat22;
1310 if ( pparam < pparam2) mySAttach = ptat22;
1311 else if ( pparam > pparam1) mySAttach = ptat21;
1315 // Case of disconneted lines
1317 gp_Ax2 AX(myCenter,theaxis,d1);
1318 Handle(Geom_Circle) circle = new Geom_Circle(AX,theLength);
1319 Handle(Geom2d_Curve) geoCurve = GeomAPI::To2d(circle,myPlane->Pln());
1320 Handle(Geom2d_Circle) c2d = *((Handle(Geom2d_Circle)*)& geoCurve);
1321 // calculate the intersection of circle with l1
1322 Standard_Real pparam; // parameter of the point of intersection on l1
1323 IntAna2d_AnaIntersection inter(l1_2d->Lin2d(),c2d->Circ2d());
1324 gp_Pnt2d pint1(inter.Point(1).Value());
1325 gp_Pnt2d pint2(inter.Point(2).Value());
1327 gp_Pnt Int1 = adp.Value(pint1.X(),pint1.Y());
1328 gp_Pnt Int2 = adp.Value(pint2.X(),pint2.Y());
1329 gp_Dir I1I2(gp_Vec(Int1,Int2));
1330 if ( d1*I1I2 > 0 ) {
1332 pparam = inter.Point(2).ParamOnFirst();
1336 pparam = inter.Point(1).ParamOnFirst();
1340 Standard_Real pparam1;
1341 Standard_Real pparam2;
1343 pparam1 = ElCLib::Parameter(gpl1,ptat11);
1344 pparam2 = ElCLib::Parameter(gpl1,ptat12);
1345 if ( pparam1 < pparam2 ) {
1346 if ( pparam < pparam1 ) myFAttach = ptat11;
1347 else if ( pparam > pparam2) myFAttach = ptat12;
1350 if ( pparam < pparam2) myFAttach = ptat12;
1351 else if ( pparam > pparam1) myFAttach = ptat11;
1354 pparam = ElCLib::Parameter(gpl2,P1);
1355 mySAttach = ElCLib::Value(pparam, gpl2);
1359 pparam1 = ElCLib::Parameter(gpl2,ptat21);
1360 pparam2 = ElCLib::Parameter(gpl2,ptat22);
1361 if ( pparam1 < pparam2 ) {
1362 if ( pparam < pparam1 ) mySAttach = ptat21;
1363 else if ( pparam > pparam2) mySAttach = ptat22;
1366 if ( pparam < pparam2) mySAttach = ptat22;
1367 else if ( pparam > pparam1) mySAttach = ptat21;
1371 curpos.SetXYZ(.5*(P1.XYZ()+P2.XYZ()));
1373 gp_Ax2 ax(myCenter,theaxis,d1);
1374 gp_Circ circle(ax,theLength);
1375 Standard_Real par = ElCLib::Parameter(circle,curpos);
1376 curpos = ElCLib::Value(par,circle);
1379 curpos = AIS::TranslatePointToBound( curpos, gp_Dir( gp_Vec( myCenter, curpos ) ), myBndBox );
1381 myAutomaticPosition = Standard_True;
1384 curpos = myPosition;
1385 gp_Lin Media(myCenter, gpl1.Direction());
1386 Standard_Real pcurpos = ElCLib::Parameter(Media, curpos);
1387 myCenter = ElCLib::Value(pcurpos, Media);
1388 // the centre is translated to avoid a constant radius!
1389 myCenter.Translate(-theLength*gp_Vec(gpl1.Direction()));
1390 gp_Ax2 AX(myCenter,theaxis,gpl1.Direction());
1391 Handle(Geom_Circle) circle = new Geom_Circle(AX,theLength);
1394 pcurpos = ElCLib::Parameter(circle->Circ(), curpos);
1395 curpos = ElCLib::Value(pcurpos, circle->Circ());
1397 Handle(Geom2d_Curve) geoCurve = GeomAPI::To2d(circle,myPlane->Pln());
1398 Handle(Geom2d_Circle) c2d = *((Handle(Geom2d_Circle)*)& geoCurve);
1399 // calculate the point of intersection of circle with l1
1400 IntAna2d_AnaIntersection inter(l1_2d->Lin2d(),c2d->Circ2d());
1401 gp_Pnt2d pint1(inter.Point(1).Value());
1402 gp_Pnt2d pint2(inter.Point(2).Value());
1403 gp_Pnt Int1 = adp.Value(pint1.X(),pint1.Y());
1404 gp_Pnt Int2 = adp.Value(pint2.X(),pint2.Y());
1405 if ( curpos.SquareDistance(Int1) < curpos.SquareDistance(Int2)) myFAttach = Int1;
1406 else myFAttach = Int2;
1409 // calculate the point of intersection of circle with l2
1410 // -> this is the projection because the centre of circle
1411 // is in the middle of l1 and l2
1412 Standard_Real pparam = ElCLib::Parameter(gpl2,myFAttach);
1413 mySAttach = ElCLib::Value(pparam, gpl2);
1417 Standard_Real par_attach(ElCLib::Parameter(gpl1,myFAttach));
1418 Standard_Real par1,par2;
1420 par1 = ElCLib::Parameter(gpl1,ptat11);
1421 par2 = ElCLib::Parameter(gpl1,ptat12);
1423 if ( par_attach < par1 ) myFAttach = ptat11;
1424 else if ( par_attach > par2) myFAttach = ptat12;
1427 if ( par_attach < par2 ) myFAttach = ptat12;
1428 else if ( par_attach > par1) myFAttach = ptat11;
1431 par_attach = ElCLib::Parameter(gpl2,mySAttach);
1433 par1 = ElCLib::Parameter(gpl2,ptat21);
1434 par2 = ElCLib::Parameter(gpl2,ptat22);
1436 if ( par_attach < par1 ) mySAttach = ptat21;
1437 else if ( par_attach > par2) mySAttach = ptat22;
1440 if ( par_attach < par2 ) mySAttach = ptat22;
1441 else if ( par_attach > par1) mySAttach = ptat21;
1446 myFDir = gp_Dir(gp_Vec(myCenter,P1));
1447 mySDir = gp_Dir(gp_Vec(myCenter,P2));
1449 //--------------------------------------------------------
1450 // Computation of the presentation
1451 //--------------------------------------------------------
1452 Handle(Prs3d_AngleAspect) la = myDrawer->AngleAspect();
1453 Handle(Prs3d_ArrowAspect) arr = la->ArrowAspect();
1455 arr->SetLength(myArrowSize);
1458 DsgPrs_AnglePresentation::Add(aPresentation,
1473 DsgPrs_AnglePresentation::Add(aPresentation,
1487 //=======================================================================
1488 //function : Compute3DSelection
1489 // purpose : compute the zones of selection for an angle dimension
1491 //=======================================================================
1493 void AIS_AngleDimension::Compute3DSelection( const Handle( SelectMgr_Selection )& aSelection )
1495 gp_Circ AngleCirc, AttachCirc;
1496 Standard_Real FirstParAngleCirc, LastParAngleCirc, FirstParAttachCirc, LastParAttachCirc;
1497 gp_Pnt EndOfArrow1, EndOfArrow2, ProjAttachPoint2;
1498 gp_Dir DirOfArrow1, DirOfArrow2;
1499 gp_Dir axisdir = (myVal <= Precision::Angular() || Abs( M_PI-myVal ) <= Precision::Angular())?
1500 myPlane->Pln().Axis().Direction() : (myFDir ^ mySDir);
1501 Standard_Boolean isPlane = (myFirstSurfType == AIS_KOS_Plane)? Standard_True : Standard_False;
1503 Standard_Real ArrowLength = myDrawer->AngleAspect()->ArrowAspect()->Length();
1504 DsgPrs::ComputeFacesAnglePresentation( ArrowLength,
1525 LastParAttachCirc );
1527 Handle( SelectMgr_EntityOwner ) own = new SelectMgr_EntityOwner( this, 7 );
1528 Handle( Select3D_SensitiveSegment ) seg;
1529 Handle( Geom_TrimmedCurve ) curve;
1530 Handle( Select3D_SensitiveCurve ) SensCurve;
1532 // Angle's arc or line
1533 if (myVal > Precision::Angular() && Abs( M_PI-myVal ) > Precision::Angular())
1535 curve = new Geom_TrimmedCurve( new Geom_Circle( AngleCirc ), FirstParAngleCirc, LastParAngleCirc );
1536 SensCurve = new Select3D_SensitiveCurve( own, curve );
1537 aSelection->Add( SensCurve );
1539 else // angle's line
1541 gp_Vec ArrowVec( DirOfArrow1 );
1542 ArrowVec *= ArrowLength;
1543 gp_Pnt FirstPoint, LastPoint;
1545 if (myPosition.Distance( EndOfArrow1 ) > ArrowLength)
1547 FirstPoint = myPosition;
1548 LastPoint = EndOfArrow1.Translated( ArrowVec );
1549 if (myPosition.SquareDistance( LastPoint ) < myPosition.SquareDistance( EndOfArrow1 ))
1550 LastPoint = EndOfArrow1.Translated( -ArrowVec );
1554 FirstPoint = EndOfArrow1.Translated( ArrowVec );
1555 LastPoint = EndOfArrow1.Translated( -ArrowVec );
1557 seg = new Select3D_SensitiveSegment( own, FirstPoint, LastPoint );
1558 aSelection->Add( seg );
1561 if (! myFAttach.IsEqual( EndOfArrow1, Precision::Confusion() ))
1563 seg = new Select3D_SensitiveSegment( own, myFAttach, EndOfArrow1 );
1564 aSelection->Add( seg );
1566 if (! ProjAttachPoint2.IsEqual( EndOfArrow2, Precision::Confusion() ))
1568 seg = new Select3D_SensitiveSegment( own, ProjAttachPoint2, EndOfArrow2 );
1569 aSelection->Add( seg );
1572 // Line or arc from mySAttach to its "projection"
1573 if (! mySAttach.IsEqual( ProjAttachPoint2, Precision::Confusion() ))
1577 seg = new Select3D_SensitiveSegment( own, mySAttach, ProjAttachPoint2 );
1578 aSelection->Add( seg );
1582 curve = new Geom_TrimmedCurve( new Geom_Circle( AttachCirc ),
1584 LastParAttachCirc );
1585 SensCurve = new Select3D_SensitiveCurve( own, curve );
1586 aSelection->Add( SensCurve );
1591 Standard_Real size(Min(myVal/100.+1.e-6,myArrowSize+1.e-6));
1592 Handle( Select3D_SensitiveBox ) box = new Select3D_SensitiveBox( own,
1596 myPosition.X() + size,
1597 myPosition.Y() + size,
1598 myPosition.Z() + size);
1599 aSelection->Add(box);
1602 //=======================================================================
1603 //function : Compute2DSelection
1604 //purpose : compute zones of selection on a side of angle between 2 edges
1605 // Special processing of zero angles!
1606 //=======================================================================
1608 void AIS_AngleDimension::Compute2DSelection(const Handle(SelectMgr_Selection)& aSelection)
1610 BRepAdaptor_Curve cu1(TopoDS::Edge(myFShape));
1611 BRepAdaptor_Curve cu2(TopoDS::Edge(mySShape));
1613 gp_Lin l1(cu1.Line());
1614 gp_Lin l2(cu2.Line());
1617 if (Abs( myVal ) <= Precision::Angular() || Abs( M_PI - myVal ) <= Precision::Angular())
1619 //---------------------------------------------------------
1620 // Cas de droites paralleles ( <=> angle nul a M_PI pres)
1621 if ((Abs(l1.Angle(l2)) < Precision::Angular()) ||
1622 (Abs((l1.Angle(l2) - M_PI)) < Precision::Angular()) )
1626 Standard_Real distLL= l1.Distance(l2);
1627 if ( Abs(distLL) <= Precision::Confusion() ) {
1628 gp_Pnt ptat11 = cu1.Value(cu1.FirstParameter());
1629 gp_Pnt ptat12 = cu1.Value(cu1.LastParameter());
1630 gp_Pnt ptat21 = cu2.Value(cu2.FirstParameter());
1631 gp_Pnt ptat22 = cu2.Value(cu2.LastParameter());
1632 distLL = 0.75 * Max( ptat11.Distance(ptat12), ptat21.Distance(ptat22));
1633 ComputeNull2DSelection(aSelection, distLL);
1636 ComputeNull2DSelection(aSelection, distLL*8/10);
1640 //----------------------------------------------------------
1641 // Classic case ( angle != 0 )
1644 if (myFDir.IsParallel(mySDir,Precision::Angular())) {
1645 Standard_Real distLL= l1.Distance(l2);
1646 if ( Abs(distLL) <= Precision::Confusion() ) {
1647 gp_Pnt ptat11 = cu1.Value(cu1.FirstParameter());
1648 gp_Pnt ptat12 = cu1.Value(cu1.LastParameter());
1649 gp_Pnt ptat21 = cu2.Value(cu2.FirstParameter());
1650 gp_Pnt ptat22 = cu2.Value(cu2.LastParameter());
1651 distLL = 0.75 * Max( ptat11.Distance(ptat12), ptat21.Distance(ptat22));
1652 ComputeNull2DSelection(aSelection, distLL*8/10);
1656 gp_Dir Norm = myFDir.Crossed(mySDir);
1658 gp_Ax2 ax(myCenter,Norm,myFDir);
1659 gp_Circ cer(ax,myCenter.Distance(myPosition));
1660 gp_Vec vec1(myFDir);
1662 Standard_Boolean nullrad(Standard_False);
1663 if (cer.Radius() == 0.) {
1665 nullrad = Standard_True;
1667 vec1 *= cer.Radius();
1668 gp_Pnt p1 = myCenter.Translated(vec1);
1669 gp_Vec vec2(mySDir);
1670 vec2 *= cer.Radius();
1671 gp_Pnt p2 = myCenter.Translated(vec2);
1673 Standard_Real uc1 = 0.;
1674 Standard_Real uc2 = ElCLib::Parameter(cer,p2);
1676 if (nullrad) uco = ElCLib::Parameter(cer,p1);
1677 else uco = ElCLib::Parameter(cer,myPosition);
1679 Standard_Real udeb = uc1;
1680 Standard_Real ufin = uc2;
1683 if (Abs(myVal)<M_PI) {
1684 // test if uco is in the opposing sector
1685 if (uco > udeb+M_PI && uco < ufin+M_PI){
1694 if ((uco-uc2) < (uc1-uco+(2*M_PI))) ufin = uco;
1695 else udeb = uco - 2*M_PI;
1697 p1 = ElCLib::Value(udeb,cer);
1698 p2 = ElCLib::Value(ufin,cer);
1700 //Create 2 owners for each part of the arrow
1701 Handle(AIS_DimensionOwner) own1 = new AIS_DimensionOwner(this,7);
1702 Handle(AIS_DimensionOwner) own2 = new AIS_DimensionOwner(this,7);
1703 if (myExtShape != 0) {
1704 if (myExtShape == 1) {
1705 own1->SetShape(mySShape);
1706 own2->SetShape(mySShape);
1709 own1->SetShape(myFShape);
1710 own2->SetShape(myFShape);
1714 own1->SetShape(myFShape);
1715 own2->SetShape(mySShape);
1718 Handle(Geom_Circle) thecirc = new Geom_Circle(cer);
1720 Handle(Geom_TrimmedCurve) thecu1 = new Geom_TrimmedCurve(thecirc,udeb,(udeb+ufin)/2);
1721 Handle(Geom_TrimmedCurve) thecu2 = new Geom_TrimmedCurve(thecirc,(udeb+ufin)/2,ufin);
1723 Handle(Select3D_SensitiveCurve) scurv = new Select3D_SensitiveCurve(own1,thecu1);
1724 aSelection->Add(scurv);
1725 scurv = new Select3D_SensitiveCurve(own2,thecu2);
1726 aSelection->Add(scurv);
1728 Handle(Select3D_SensitiveSegment) seg;
1729 if (!myFAttach.IsEqual(p1,Precision::Confusion())) {
1730 seg = new Select3D_SensitiveSegment(own1,myFAttach,p1);
1731 aSelection->Add(seg);
1733 if (!mySAttach.IsEqual(p2,Precision::Confusion())) {
1734 seg = new Select3D_SensitiveSegment(own2,mySAttach,p2);
1735 aSelection->Add(seg);
1741 //=======================================================================
1742 //function : Compute2DNullSelection
1743 //purpose : for dimension of null angle
1744 //=======================================================================
1746 void AIS_AngleDimension::ComputeNull2DSelection(
1747 const Handle(SelectMgr_Selection)& aSelection,
1748 const Standard_Real distLL)
1751 if ( myFDir.IsParallel(mySDir, Precision::Angular()) ) {
1752 Norm = myPlane->Pln().Axis().Direction();
1755 Norm = myFDir.Crossed(mySDir);
1757 gp_Ax2 ax(myCenter,Norm,myFDir);
1758 gp_Circ cer(ax,distLL);
1760 gp_Vec vec1(myFDir);
1761 vec1 *= cer.Radius();
1762 gp_Pnt p1 = myCenter.Translated(vec1);
1763 gp_Vec vec2(mySDir);
1764 vec2 *= cer.Radius();
1765 gp_Pnt p2 = myCenter.Translated(vec2);
1767 // calcul de parametres de debut et de fin des extremites de l'arc
1768 Standard_Real uc1 = 0.;
1769 Standard_Real uc2 = ElCLib::Parameter(cer,p2);
1770 Standard_Real uco = ElCLib::Parameter(cer,myPosition);
1772 Standard_Real udeb = uc1;
1773 Standard_Real ufin = uc2;
1776 if (Abs(myVal)<M_PI) {
1777 // test if uco is in the opposing sector
1778 if (uco > udeb+M_PI && uco < ufin+M_PI){
1788 if ((uco-uc2) < (uc1-uco+(2*M_PI))) {
1792 udeb = uco - 2*M_PI;
1796 //Create 2 owners for each part of the arrow
1797 Handle(AIS_DimensionOwner) own1 = new AIS_DimensionOwner(this,7);
1798 Handle(AIS_DimensionOwner) own2 = new AIS_DimensionOwner(this,7);
1799 if (myExtShape != 0) {
1800 if (myExtShape == 1) {
1801 own1->SetShape(mySShape);
1802 own2->SetShape(mySShape);
1805 own1->SetShape(myFShape);
1806 own2->SetShape(myFShape);
1810 own1->SetShape(myFShape);
1811 own2->SetShape(mySShape);
1814 Handle(Geom_Circle) thecirc = new Geom_Circle(cer);
1816 if ( udeb != ufin ) {
1817 Handle(Geom_TrimmedCurve) thecu1 = new Geom_TrimmedCurve(thecirc,udeb,(udeb+ufin)/2);
1818 Handle(Geom_TrimmedCurve) thecu2 = new Geom_TrimmedCurve(thecirc,(udeb+ufin)/2,ufin);
1820 Handle(Select3D_SensitiveCurve) scurv = new Select3D_SensitiveCurve(own1,thecu1);
1821 aSelection->Add(scurv);
1822 scurv = new Select3D_SensitiveCurve(own2,thecu2);
1823 aSelection->Add(scurv);
1826 // find end of segment to allow selection
1827 gp_Vec VTrans(myFDir.Crossed(Norm));
1828 Handle(Select3D_SensitiveSegment) seg1;
1829 seg1 = new Select3D_SensitiveSegment(own1,
1831 p1.Translated( VTrans*distLL/10 ) );
1832 aSelection->Add(seg1);
1833 seg1 = new Select3D_SensitiveSegment(own2,
1835 p2.Translated(-VTrans*distLL/10 ) );
1836 aSelection->Add(seg1);
1839 Handle(Select3D_SensitiveSegment) seg;
1840 if (!myFAttach.IsEqual(p1,Precision::Confusion())) {
1841 seg = new Select3D_SensitiveSegment(own1,myFAttach,p1);
1842 aSelection->Add(seg);
1845 if (!mySAttach.IsEqual(p2,Precision::Confusion())) {
1846 seg = new Select3D_SensitiveSegment(own2,mySAttach,p2);
1847 aSelection->Add(seg);
1852 //=======================================================================
1853 //function : ComputeConeAngleSelection
1854 //purpose : for cone angle
1855 //=======================================================================
1856 void AIS_AngleDimension::ComputeConeAngleSelection(const Handle(SelectMgr_Selection)& aSelection)
1858 if( myCone.IsNull() ) return;
1861 Handle( SelectMgr_EntityOwner ) owner = new SelectMgr_EntityOwner( this, 7 );
1862 Handle( Select3D_SensitiveSegment ) seg;
1868 Handle( Geom_Surface ) aSurf; //a surface from the Face
1869 Handle( Geom_OffsetSurface ) aOffsetSurf;
1870 Handle( Geom_ConicalSurface ) aConicalSurf;
1871 Handle( Geom_SurfaceOfRevolution ) aRevSurf;
1872 Handle( Geom_Line ) aLine;
1873 BRepAdaptor_Surface tmpSurf(myCone);
1875 AIS_KindOfSurface aSurfType;
1876 Standard_Real Offset = 0. ;
1877 Handle( Standard_Type ) aType;
1879 Standard_Real maxV = tmpSurf.FirstVParameter();
1880 Standard_Real minV = tmpSurf.LastVParameter();
1882 AIS::GetPlaneFromFace( myCone, aPln, aSurf, aSurfType, Offset );
1884 if ( aSurfType == AIS_KOS_Revolution ) { //surface of revolution
1886 aRevSurf = Handle( Geom_SurfaceOfRevolution )::DownCast( aSurf );
1887 gp_Lin ln( aRevSurf->Axis() );
1888 Handle( Geom_Curve ) tmpCrv = aRevSurf->BasisCurve();
1889 if ( tmpCrv ->DynamicType() != STANDARD_TYPE(Geom_Line) ) return; //Must be a part of line
1892 gp_Pnt fst = tmpSurf.Value(0., minV);
1893 gp_Pnt lst = tmpSurf.Value(0., maxV);
1895 gp_Vec vec1(fst, lst);
1897 par = ElCLib::Parameter( ln, fst );
1898 gp_Pnt fst2 = ElCLib::Value( par, ln ); //projection fst on ln
1899 par = ElCLib::Parameter( ln, lst );
1900 gp_Pnt lst2 = ElCLib::Value( par, ln ); //projection lst on ln
1902 gp_Vec vec2(fst2, lst2);
1904 // Check if two parts of revolution are parallel ( it's a cylinder ) or normal (it's a circle )
1905 if( vec1.IsParallel( vec2,Precision::Angular() ) || vec1.IsNormal( vec2,Precision::Angular() ) ) return;
1907 gce_MakeCone mkCone(aRevSurf->Axis(), fst, lst);
1908 aCone = mkCone.Value();
1909 Apex = aCone.Apex();
1912 aType = aSurf->DynamicType();
1913 if ( aType == STANDARD_TYPE(Geom_OffsetSurface) || Offset > 0.01 ) { //offset surface
1914 aOffsetSurf = new Geom_OffsetSurface (aSurf, Offset);
1915 aSurf = aOffsetSurf->Surface();
1916 BRepBuilderAPI_MakeFace mkFace(aSurf, Precision::Confusion());
1918 if( !mkFace.IsDone() ) return;
1919 tmpSurf.Initialize( mkFace.Face() );
1922 aCone = tmpSurf.Cone();
1923 aConicalSurf = Handle( Geom_ConicalSurface)::DownCast( aSurf );
1924 Apex = aConicalSurf->Apex();
1927 Handle(Geom_Curve) aCurve; //A circle where the angle is drawn
1929 if ( myAutomaticPosition ) {
1930 Standard_Real midV = ( minV + maxV ) / 2.5;
1932 aCurve = aSurf->VIso(midV);
1933 myCircle = Handle(Geom_Circle)::DownCast(aCurve)->Circ();
1935 myPosition = ElCLib::Value(M_PI / 2.0, myCircle);
1936 myAutomaticPosition = Standard_False;
1940 ElSLib::Parameters(aCone, myPosition, U, V);
1941 aCurve = aSurf->VIso(V);
1942 myCircle = Handle(Geom_Circle)::DownCast(aCurve)->Circ();
1944 //__________________________________________________________________
1945 aCurve = aSurf->VIso(maxV);
1946 gp_Circ CircVmax = Handle(Geom_Circle)::DownCast(aCurve)->Circ();
1947 aCurve = aSurf->VIso(minV);
1948 gp_Circ CircVmin = Handle(Geom_Circle)::DownCast(aCurve)->Circ();
1949 //__________________________________________________________________
1951 if( CircVmax.Radius() < CircVmin.Radius() ) {
1952 gp_Circ tmpCirc = CircVmax;
1953 CircVmax = CircVmin;
1957 Standard_Boolean IsArrowOut = Standard_True; //Is arrows inside or outside of the cone
1958 //Standard_Real PntOnMainAxis = 0; //Is projection of aPosition inside of the cone = 0, above = 1, or below = -1
1959 Standard_Boolean IsConeTrimmed = Standard_False;
1961 if( CircVmin.Radius() > 0.01 ) IsConeTrimmed = Standard_True;
1963 gp_Pnt AttachmentPnt;
1966 Standard_Real param = ElCLib::Parameter(myCircle, myPosition);
1969 gp_Pnt P1 = ElCLib::Value(0., myCircle);
1970 gp_Pnt P2 = ElCLib::Value(M_PI, myCircle);
1972 gce_MakePln mkPln(P1, P2, aPnt); // create a plane whitch defines plane for projection aPosition on it
1974 aPnt = AIS::ProjectPointOnPlane(myPosition, mkPln.Value());
1975 gp_Pnt tmpPnt = aPnt;
1977 if( aPnt.Distance(P1) < aPnt.Distance(P2) ){
1986 aPnt = AttachmentPnt ; // Creating of circle whitch defines a plane for a dimension arc
1987 gp_Vec Vec(AttachmentPnt, Apex); // Dimension arc is a part of the circle
1989 aPnt.Translate(Vec);
1990 GC_MakeCircle mkCirc(AttachmentPnt, OppositePnt, aPnt);
1991 gp_Circ aCircle2 = mkCirc.Value()->Circ();
1995 Standard_Real AttParam = ElCLib::Parameter(aCircle2, AttachmentPnt);
1996 Standard_Real OppParam = ElCLib::Parameter(aCircle2, OppositePnt);
1998 while ( AttParam >= 2 * M_PI ) AttParam -= 2 * M_PI;
1999 while ( OppParam >= 2 * M_PI ) OppParam -= 2 * M_PI;
2001 if( myPosition.Distance( myCircle.Location() ) <= myCircle.Radius() )
2002 if( 2 * myCircle.Radius() > aCircle2.Radius() * 0.4 ) IsArrowOut = Standard_False; //four times more than an arrow size
2005 Standard_Real angle = OppParam - AttParam;
2009 angle += M_PI / 6; //An angle between AttParam and OppParam + 30 degrees
2010 param -= M_PI / 12; //out parts of dimension line are 15 degrees
2013 while ( angle > 2. * M_PI ) angle -= 2. * M_PI;
2015 gp_Pnt Vprev = ElCLib::Value(param, aCircle2);
2016 for( i = 1; i <= 11; i++ ) //calculating of arc
2018 gp_Pnt Vcur = ElCLib::Value(param + angle/11 * i, aCircle2);
2019 seg = new Select3D_SensitiveSegment(owner, Vprev, Vcur);
2020 aSelection->Add(seg);
2024 tmpPnt = tmpPnt.Translated(gp_Vec(0, 0, -2));
2026 const Standard_Real size(Min(myVal/100.+1.e-6,myArrowSize+1.e-6));
2027 Handle( Select3D_SensitiveBox ) box = new Select3D_SensitiveBox( owner,
2034 aSelection->Add(box);