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 //=======================================================================
477 //purpose : : to avoid warning
478 //=======================================================================
480 void AIS_AngleDimension::Compute(const Handle(PrsMgr_PresentationManager2d)& aPresentationManager2d,
481 const Handle(Graphic2d_GraphicObject)& aGraphicObject,
482 const Standard_Integer anInteger)
484 // Standard_NotImplemented::Raise("AIS_AngleDimension::Compute(const Handle(PrsMgr_PresentationManager2d)&,const Handle(Graphic2d_GraphicObject)&,const Standard_Integer)");
485 PrsMgr_PresentableObject::Compute( aPresentationManager2d ,aGraphicObject,anInteger) ;
488 void AIS_AngleDimension::Compute(const Handle_Prs3d_Projector& aProjector, const Handle_Geom_Transformation& aTransformation, const Handle_Prs3d_Presentation& aPresentation)
490 // Standard_NotImplemented::Raise("AIS_AngleDimension::Compute(const Handle_Prs3d_Projector&, const Handle_Geom_Transformation&, const Handle_Prs3d_Presentation&)");
491 PrsMgr_PresentableObject::Compute( aProjector , aTransformation , aPresentation ) ;
494 //=======================================================================
495 //function : ComputeSelection
497 //=======================================================================
499 void AIS_AngleDimension::ComputeSelection(const Handle(SelectMgr_Selection)& aSelection,
500 const Standard_Integer)
503 if ( myNbShape == 1 )
505 // cout << "Computing selection for cone's angle " << endl;
506 ComputeConeAngleSelection(aSelection);
511 if (myFShape.IsNull()) return;
513 if (myFShape.ShapeType() == TopAbs_FACE )
514 Compute3DSelection(aSelection);
516 Compute2DSelection(aSelection);
519 Handle( SelectMgr_EntityOwner ) own = new SelectMgr_EntityOwner( this, 7 );
520 Standard_Real size(Min(myVal/100.+1.e-6,myArrowSize+1.e-6));
521 Handle( Select3D_SensitiveBox ) box = new Select3D_SensitiveBox( own,
525 myPosition.X() + size,
526 myPosition.Y() + size,
527 myPosition.Z() + size);
528 aSelection->Add(box);
531 //=======================================================================
532 //function : ComputeConeAngle
534 //=======================================================================
536 void AIS_AngleDimension::ComputeConeAngle(const Handle(Prs3d_Presentation)& aPresentation)
538 if( myCone.IsNull() ) return;
544 Handle( Geom_Surface ) aSurf; //a surface from the Face
545 Handle( Geom_OffsetSurface ) aOffsetSurf;
546 Handle( Geom_ConicalSurface ) aConicalSurf;
547 Handle( Geom_SurfaceOfRevolution ) aRevSurf;
548 Handle( Geom_Line ) aLine;
549 BRepAdaptor_Surface tmpSurf(myCone);
551 AIS_KindOfSurface aSurfType;
552 Standard_Real Offset = 0. ;
553 Handle( Standard_Type ) aType;
555 Standard_Real maxV = tmpSurf.FirstVParameter();
556 Standard_Real minV = tmpSurf.LastVParameter();
559 AIS::GetPlaneFromFace( myCone, aPln, aSurf, aSurfType, Offset );
561 if ( aSurfType == AIS_KOS_Revolution ) { //surface of revolution
563 aRevSurf = Handle( Geom_SurfaceOfRevolution )::DownCast( aSurf );
564 gp_Lin ln( aRevSurf->Axis() );
565 Handle( Geom_Curve ) tmpCrv = aRevSurf->BasisCurve();
566 if ( tmpCrv ->DynamicType() != STANDARD_TYPE(Geom_Line) ) return; //Must be a part of line
569 gp_Pnt fst = tmpSurf.Value(0., minV);
570 gp_Pnt lst = tmpSurf.Value(0., maxV);
572 gp_Vec vec1(fst, lst);
574 par = ElCLib::Parameter( ln, fst );
575 gp_Pnt fst2 = ElCLib::Value( par, ln ); //projection fst on ln
576 par = ElCLib::Parameter( ln, lst );
577 gp_Pnt lst2 = ElCLib::Value( par, ln ); //projection lst on ln
579 gp_Vec vec2(fst2, lst2);
581 // Check if two parts of revolution are parallel ( it's a cylinder ) or normal (it's a circle )
582 if( vec1.IsParallel( vec2,Precision::Angular() ) || vec1.IsNormal( vec2,Precision::Angular() ) ) return;
584 gce_MakeCone mkCone(aRevSurf->Axis(), fst, lst);
585 aCone = mkCone.Value();
589 aType = aSurf->DynamicType();
590 if ( aType == STANDARD_TYPE(Geom_OffsetSurface) || Offset > 0.01 ) { //offset surface
591 aOffsetSurf = new Geom_OffsetSurface (aSurf, Offset);
592 aSurf = aOffsetSurf->Surface();
593 BRepBuilderAPI_MakeFace mkFace(aSurf, Precision::Confusion());
595 if( !mkFace.IsDone() ) return;
596 tmpSurf.Initialize( mkFace.Face() );
599 aCone = tmpSurf.Cone();
600 aConicalSurf = Handle( Geom_ConicalSurface)::DownCast( aSurf );
601 Apex = aConicalSurf->Apex();
604 Handle(Geom_Curve) aCurve; //A circle where the angle is drawn
605 if ( myAutomaticPosition ) {
606 Standard_Real midV = ( minV + maxV ) / 2.5;
608 aCurve = aSurf->VIso(midV);
609 myCircle = Handle(Geom_Circle)::DownCast(aCurve)->Circ();
611 myPosition = ElCLib::Value(M_PI / 2.0, myCircle);
612 myAutomaticPosition = Standard_False;
616 ElSLib::Parameters(aCone, myPosition, U, V);
617 aCurve = aSurf->VIso(V);
618 myCircle = Handle(Geom_Circle)::DownCast(aCurve)->Circ();
621 //__________________________________________________________________
622 aCurve = aSurf->VIso(maxV);
623 gp_Circ CircVmax = Handle(Geom_Circle)::DownCast(aCurve)->Circ();
624 aCurve = aSurf->VIso(minV);
625 gp_Circ CircVmin = Handle(Geom_Circle)::DownCast(aCurve)->Circ();
626 //__________________________________________________________________
628 if( CircVmax.Radius() < CircVmin.Radius() ) {
629 gp_Circ tmpCirc = CircVmax;
634 DsgPrs_AnglePresentation::Add(aPresentation, myDrawer, myVal,
635 myText, myCircle, myPosition, Apex, CircVmin, CircVmax, myArrowSize);
636 // cout << "ComputeConeAngle is over" << endl;
640 //=======================================================================
641 //function : ComputeTwoFacesAngle
643 //=======================================================================
645 void AIS_AngleDimension::ComputeTwoFacesAngle(const Handle(Prs3d_Presentation)& aPresentation)
647 if (myFirstSurfType == AIS_KOS_Plane)
648 ComputeTwoPlanarFacesAngle( aPresentation );
650 ComputeTwoCurvilinearFacesAngle( aPresentation );
653 //=======================================================================
654 //function : ComputeTwoCurvilinearFacesAngle
656 //=======================================================================
658 void AIS_AngleDimension::ComputeTwoCurvilinearFacesAngle(const Handle(Prs3d_Presentation)& aPresentation)
660 AIS::ComputeAngleBetweenCurvilinearFaces( TopoDS::Face( myFShape ),
661 TopoDS::Face( mySShape ),
676 if (myAutomaticPosition && myIsSetBndBox)
677 myPosition = AIS::TranslatePointToBound( myPosition, gp_Dir( gp_Vec( myCenter, myPosition ) ), myBndBox );
679 Handle(Prs3d_AngleAspect) la = myDrawer->AngleAspect();
680 Handle(Prs3d_ArrowAspect) arr = la->ArrowAspect();
682 if( !myArrowSizeIsDefined ) {
684 Standard_Real arrsize = myCenter.Distance( myPosition );
686 if ( (myArrowSize-arrsize) < 0.1 ) arrsize = myArrowSize;
687 if (arrsize == 0.) arrsize = 1.;
689 myArrowSize = arrsize;
691 arr->SetLength( myArrowSize );
693 arr->SetLength(arrsize);
697 if (myVal <= Precision::Angular() || Abs( M_PI-myVal ) <= Precision::Angular())
698 DsgPrs_AnglePresentation::Add(aPresentation,
707 myPlane->Pln().Axis().Direction(),
708 Standard_False, // not plane
713 DsgPrs_AnglePresentation::Add(aPresentation,
723 Standard_False, // not plane
729 //=======================================================================
730 //function : ComputeTwoPlanarFacesAngle
732 //=======================================================================
734 void AIS_AngleDimension::ComputeTwoPlanarFacesAngle( const Handle( Prs3d_Presentation )& aPresentation )
736 AIS::ComputeAngleBetweenPlanarFaces( TopoDS::Face( myFShape ),
737 TopoDS::Face( mySShape ),
748 if (myAutomaticPosition && myIsSetBndBox)
749 myPosition = AIS::TranslatePointToBound( myPosition, gp_Dir( gp_Vec( myCenter, myPosition ) ), myBndBox );
751 Handle(Prs3d_AngleAspect) la = myDrawer->AngleAspect();
752 Handle(Prs3d_ArrowAspect) arr = la->ArrowAspect();
754 if( !myArrowSizeIsDefined ) {
756 Standard_Real arrsize = myCenter.Distance( myPosition );
758 if ( (myArrowSize-arrsize) < 0.1 ) arrsize = myArrowSize;
759 if (arrsize == 0.) arrsize = 1.;
761 myArrowSize = arrsize;
763 arr->SetLength( myArrowSize );
765 arr->SetLength(arrsize);
769 DsgPrs_AnglePresentation::Add(aPresentation,
786 //=======================================================================
787 //function : ComputeTwoEdgesAngle
789 //=======================================================================
791 void AIS_AngleDimension::ComputeTwoEdgesAngle(const Handle(Prs3d_Presentation)& aPresentation)
793 BRepAdaptor_Curve cu1(TopoDS::Edge(myFShape));
794 BRepAdaptor_Curve cu2(TopoDS::Edge(mySShape));
795 if ((cu1.GetType() != GeomAbs_Line) || (cu2.GetType() != GeomAbs_Line)) return;
798 BRepBuilderAPI_MakeFace makeface(myPlane->Pln());
799 TopoDS_Face face(makeface.Face());
800 BRepAdaptor_Surface adp(makeface.Face());
803 Handle(Geom_Line) geom_lin1,geom_lin2;
804 gp_Pnt ptat11,ptat12,ptat21,ptat22;//,pint3d;
805 Standard_Boolean isInfinite1,isInfinite2;
806 Handle(Geom_Curve) extCurv;
807 Standard_Integer copyOfMyExtShape = myExtShape;
808 if (!AIS::ComputeGeometry(TopoDS::Edge(myFShape),
809 TopoDS::Edge(mySShape),
823 // Temporary: computation of myVal
824 // myVal = Abs(geom_lin1->Lin().Angle( geom_lin2->Lin())); // Pb with angles JPR
826 if (copyOfMyExtShape != 0) myExtShape = copyOfMyExtShape;
828 // 2d lines => projection of 3d on current plane
831 Handle(Geom2d_Curve) geoC1 = GeomAPI::To2d(geom_lin1,myPlane->Pln());
832 Handle(Geom2d_Line) lin1_2d = *((Handle(Geom2d_Line)*)& geoC1);
833 Handle(Geom2d_Curve) geoC2 = GeomAPI::To2d(geom_lin2,myPlane->Pln());
834 Handle(Geom2d_Line) lin2_2d = *((Handle(Geom2d_Line)*)& geoC2);
837 if( !myArrowSizeIsDefined ) {
839 Standard_Real arrSize1(myArrowSize),arrSize2(myArrowSize);
840 if (!isInfinite1) arrSize1 = ptat11.Distance(ptat12)/100.;
841 if (!isInfinite2) arrSize2 = ptat21.Distance(ptat22)/100.;
843 myArrowSize = Min(myArrowSize,Max(arrSize1,arrSize2));
845 myArrowSize = Min(myArrowSize,Min(arrSize1,arrSize2));
852 // Processing in case of 2 parallel straight lines
853 if (lin1_2d->Lin2d().Direction()
854 .IsParallel(lin2_2d->Lin2d().Direction(),Precision::Angular())) {
855 ComputeTwoEdgesNullAngle(aPresentation,
860 isInfinite1,isInfinite2);
863 // Processing in case of 2 non-parallel straight lines
865 ComputeTwoEdgesNotNullAngle(aPresentation,
872 isInfinite1,isInfinite2);
874 if ( (myExtShape != 0) && !extCurv.IsNull()) {
876 if ( myExtShape == 1 ) {
881 aPresentation->SetInfiniteState(isInfinite1);
882 ComputeProjEdgePresentation(aPresentation,TopoDS::Edge(myFShape),geom_lin1,pf,pl);
889 aPresentation->SetInfiniteState(isInfinite2);
890 ComputeProjEdgePresentation(aPresentation,TopoDS::Edge(mySShape),geom_lin2,pf,pl);
896 //=======================================================================
897 //function : ComputeTwoEdgesNotNullAngle
899 //=======================================================================
901 void AIS_AngleDimension::ComputeTwoEdgesNotNullAngle(const Handle(Prs3d_Presentation)& aPresentation,
902 const Handle(Geom_Line)& l1,
903 const Handle(Geom_Line)& l2,
904 const gp_Pnt& ptat11,
905 const gp_Pnt& ptat12,
906 const gp_Pnt& ptat21,
907 const gp_Pnt& ptat22,
908 const Standard_Boolean isInfinite1,
909 const Standard_Boolean isInfinite2)
912 BRepBuilderAPI_MakeFace makeface(myPlane->Pln());
913 TopoDS_Face face(makeface.Face());
914 BRepAdaptor_Surface adp(makeface.Face());
915 // 2d lines => projection of 3d on current plane
916 Handle(Geom2d_Curve) geoC1 = GeomAPI::To2d(l1,myPlane->Pln());
917 const Handle(Geom2d_Line)& l1_2d = *((Handle(Geom2d_Line)*)& geoC1);
918 Handle(Geom2d_Curve) geoC2 = GeomAPI::To2d(l2,myPlane->Pln());
919 const Handle(Geom2d_Line)& l2_2d = *((Handle(Geom2d_Line)*)& geoC2);
921 //----------------------------------------------------------
922 // Computation of myCenter
923 //----------------------------------------------------------
924 IntAna2d_AnaIntersection inter(l1_2d->Lin2d(),l2_2d->Lin2d());
925 if (!inter.IsDone()) return;
926 if (!inter.NbPoints()) return;
928 gp_Pnt2d pint(inter.Point(1).Value());
929 myCenter = adp.Value(pint.X(),pint.Y());
931 //----------------------------------------------------------
932 // Computation of the 2 directions
933 //----------------------------------------------------------
936 if (myCenter.SquareDistance(ptat11) > myCenter.SquareDistance(ptat12)) d1 = gp_Dir(gp_Vec(myCenter,ptat11));
937 else d1 = gp_Dir(gp_Vec(myCenter,ptat12));
939 else d1 = l1->Lin().Direction();
942 if (myCenter.SquareDistance(ptat21) > myCenter.SquareDistance(ptat22)) d2 = gp_Dir(gp_Vec(myCenter,ptat21));
943 else d2 = gp_Dir(gp_Vec(myCenter,ptat22));
945 else d2 = l2->Lin().Direction();
947 Standard_Boolean In1(Standard_False);
948 Standard_Boolean In2(Standard_False);
949 if ( !(Abs(d1.Angle(d2) - Abs(myVal)) <= Precision::Confusion())
950 && (Abs(myVal) < M_PI) ) {
951 Standard_Real parcent1 = ElCLib::Parameter(l1->Lin(), myCenter);
952 Standard_Real par11 = ElCLib::Parameter(l1->Lin(), ptat11);
953 Standard_Real par12 = ElCLib::Parameter(l1->Lin(), ptat12);
954 if ( par11 < par12) {
955 if ( ( parcent1> par11) && (parcent1< par12)) {
961 if ( ( parcent1> par12) && (parcent1< par11)) {
976 gp_Lin gpl1 = l1->Lin();
977 gp_Lin gpl2 = l2->Lin();
978 theaxis = gp_Lin(myCenter,myFDir^mySDir);
985 TColStd_Array1OfReal tabdist(1,4);
987 tabdist(1) = theaxis.Distance(ptat11);
988 tabdist(2) = theaxis.Distance(ptat12);
991 tabdist(1) = tabdist(2) = 0.;
995 tabdist(3) = theaxis.Distance(ptat21);
996 tabdist(4) = theaxis.Distance(ptat22);
999 tabdist(3) = tabdist(4) = 0.;
1002 if (myAutomaticPosition) {
1003 Standard_Real length_1(RealLast());
1004 if (!isInfinite1) length_1 = .75*Abs(tabdist(2)-tabdist(1))+Min(tabdist(1),tabdist(2));
1006 Standard_Real length_2(RealLast());
1007 if (!isInfinite2) length_2 = .75*Abs(tabdist(4)-tabdist(3))+Min(tabdist(3),tabdist(4));
1008 Standard_Real theLength(Min(length_1,length_2));
1009 if (Precision::IsInfinite(theLength)) theLength = 50.;
1011 myFAttach = myCenter.Translated(gp_Vec(d1)*theLength);
1012 mySAttach = myCenter.Translated(gp_Vec(d2)*theLength);
1015 Standard_Real par_p1_attach(ElCLib::Parameter(gpl1,myFAttach));
1016 Standard_Real par11 = ElCLib::Parameter(gpl1,ptat11);
1017 Standard_Real par12 = ElCLib::Parameter(gpl1,ptat12);
1018 if (par_p1_attach > par11 && par_p1_attach > par12) {
1019 par_p1_attach = Max(par11,par12);
1020 myFAttach = ElCLib::Value(par_p1_attach,gpl1);
1022 else if (par_p1_attach < par11 && par_p1_attach < par12) {
1023 par_p1_attach = Min(par11,par12);
1024 myFAttach = ElCLib::Value(par_p1_attach,gpl1);
1029 Standard_Real par_p2_attach(ElCLib::Parameter(gpl2,mySAttach));
1030 Standard_Real par21 = ElCLib::Parameter(gpl2,ptat21);
1031 Standard_Real par22 = ElCLib::Parameter(gpl2,ptat22);
1032 if (par_p2_attach > par21 && par_p2_attach > par22) {
1033 par_p2_attach = Max(par21,par22);
1034 mySAttach = ElCLib::Value(par_p2_attach,gpl2);
1036 else if (par_p2_attach < par21 && par_p2_attach < par22) {
1037 par_p2_attach = Min(par21,par22);
1038 mySAttach = ElCLib::Value(par_p2_attach,gpl2);
1041 if ( myVal < M_PI) curpos.SetXYZ(.5*(myFAttach.XYZ()+mySAttach.XYZ()));
1043 curpos.SetXYZ(.5*(myFAttach.XYZ()+mySAttach.XYZ()));
1044 gp_Vec transl(curpos, myCenter);
1046 curpos.Translate(transl);
1049 gp_Ax2 ax(myCenter,myFDir.Crossed(mySDir),myFDir);
1050 gp_Circ circle(ax,theLength);
1051 Standard_Real par = ElCLib::Parameter(circle,curpos);
1052 curpos = ElCLib::Value(par,circle);
1054 // small offset like in LengthDimension
1055 gp_Vec transl(myCenter, curpos);
1057 curpos.Translate(transl);
1060 curpos = AIS::TranslatePointToBound( curpos, gp_Dir( gp_Vec( myCenter, curpos ) ), myBndBox );
1062 myPosition = curpos;
1063 myAutomaticPosition = Standard_True;
1067 // point is projected on the plane
1068 gp_Pnt2d pointOnPln(ProjLib::Project(myPlane->Pln(),myPosition));
1069 myPosition = BRepAdaptor_Surface(BRepBuilderAPI_MakeFace(myPlane->Pln()).Face()).Value(pointOnPln.X(),pointOnPln.Y());
1070 curpos = myPosition;
1071 Standard_Real dist(curpos.Distance(myCenter));
1072 if (dist<=Precision::Confusion()) {
1073 gp_XYZ delta(1.,1.,1.);
1074 curpos.SetXYZ(curpos.XYZ()+delta);
1075 dist = curpos.Distance(myCenter);
1077 // To learn if it is necessary to take distance -dist or not
1078 // it is necessary to know if we are in the sector opposite to the angle
1079 // if not : we are in the opposite sector if the coordinates
1080 // of curpos in point (d1,d2) are negative
1081 gp_Ax2 ax(myCenter,myFDir.Crossed(mySDir),myFDir);
1082 gp_Circ circle(ax,dist);
1084 // gp_Pnt p1(myCenter.Translated(gp_Vec(d1)*dist));
1086 gp_Pnt p2(myCenter.Translated(gp_Vec(d2)*dist));
1087 Standard_Real uc1 = 0;
1088 Standard_Real uc2 = ElCLib::Parameter(circle, p2 );
1089 Standard_Real uco = ElCLib::Parameter(circle, curpos );
1090 Standard_Real udeb = uc1;
1091 Standard_Real ufin = uc2;
1093 if (Abs(myVal)<M_PI) {
1094 // test if uco is in the opposite sector
1095 if (uco > udeb+M_PI && uco < ufin+M_PI){
1101 gp_Pnt p1_attach(myCenter.Translated(gp_Vec(d1)*dist));
1102 gp_Pnt p2_attach(myCenter.Translated(gp_Vec(d2)*dist));
1105 Standard_Real par_p1_attach(ElCLib::Parameter(gpl1,p1_attach));
1106 Standard_Real par11 = ElCLib::Parameter(gpl1,ptat11);
1107 Standard_Real par12 = ElCLib::Parameter(gpl1,ptat12);
1108 if (par_p1_attach > par11 && par_p1_attach > par12) {
1109 par_p1_attach = Max(par11,par12);
1110 p1_attach = ElCLib::Value(par_p1_attach,gpl1);
1112 else if (par_p1_attach < par11 && par_p1_attach < par12) {
1113 par_p1_attach = Min(par11,par12);
1114 p1_attach = ElCLib::Value(par_p1_attach,gpl1);
1117 myFAttach = p1_attach;
1120 Standard_Real par_p2_attach(ElCLib::Parameter(gpl2,p2_attach));
1121 Standard_Real par21 = ElCLib::Parameter(gpl2,ptat21);
1122 Standard_Real par22 = ElCLib::Parameter(gpl2,ptat22);
1123 if (par_p2_attach > par21 && par_p2_attach > par22) {
1124 par_p2_attach = Max(par21,par22);
1125 p2_attach = ElCLib::Value(par_p2_attach,gpl2);
1127 else if (par_p2_attach < par21 && par_p2_attach < par22) {
1128 par_p2_attach = Min(par21,par22);
1129 p2_attach = ElCLib::Value(par_p2_attach,gpl2);
1132 mySAttach = p2_attach;
1134 myAxis = theaxis.Position();
1136 //--------------------------------------------------------
1137 // Computation of the presentation
1138 //--------------------------------------------------------
1139 Handle(Prs3d_AngleAspect) la = myDrawer->AngleAspect();
1140 Handle(Prs3d_ArrowAspect) arr = la->ArrowAspect();
1142 arr->SetLength(myArrowSize);
1144 DsgPrs_AnglePresentation::Add(aPresentation,
1159 //=======================================================================
1160 //function : ComputeTwoEdgesNullAngle
1161 //purpose : compute the presentation of a angle dimension if it's null.
1162 // -> the aim of the computation is to have a constant radius
1163 // during the dimension moving : the radius is independant
1164 // of the cursor position, it's equal to a arbitrary value
1165 //=======================================================================
1167 void AIS_AngleDimension::ComputeTwoEdgesNullAngle(const Handle(Prs3d_Presentation)& aPresentation,
1168 const Handle(Geom_Line)& l1,
1169 const Handle(Geom_Line)& l2,
1170 const gp_Pnt& ptat11,
1171 const gp_Pnt& ptat12,
1172 const gp_Pnt& ptat21,
1173 const gp_Pnt& ptat22,
1174 const Standard_Boolean isInfinite1,
1175 const Standard_Boolean isInfinite2)
1178 BRepBuilderAPI_MakeFace makeface(myPlane->Pln());
1179 TopoDS_Face face(makeface.Face());
1180 BRepAdaptor_Surface adp(makeface.Face());
1181 // 2d lines => projection of 3d on current plane
1182 Handle(Geom2d_Curve) geoC1 = GeomAPI::To2d(l1,myPlane->Pln());
1183 Handle(Geom2d_Line) l1_2d = *((Handle(Geom2d_Line)*)& geoC1);
1184 Handle(Geom2d_Curve) geoC2 = GeomAPI::To2d(l2,myPlane->Pln());
1185 Handle(Geom2d_Line) l2_2d = *((Handle(Geom2d_Line)*)& geoC2);
1187 gp_Lin gpl1 = l1->Lin();
1188 gp_Lin gpl2 = l2->Lin();
1190 //------------------------------------------------------------
1191 // Computation of myCenter
1192 // -> Point located on the median of 2 straight lines,
1193 // is calculated as located between 2 closest points
1194 // of each straight line.
1195 //-----------------------------------------------------------
1196 // theLength : radius of the future circle
1197 Standard_Real theLength = gpl1.Distance(gpl2.Location());
1198 // processing of the particular case when 2 straight lines are coincident
1199 Standard_Boolean SameLines(Standard_False);
1200 if ( theLength <= Precision::Confusion()) {
1201 SameLines = Standard_True;
1203 if (!isInfinite2) theLength = 0.75 * Max( ptat11.Distance(ptat12), ptat21.Distance(ptat22));
1204 else theLength = 0.75*ptat11.Distance(ptat12);
1207 if (!isInfinite2) theLength = 0.75*ptat21.Distance(ptat22);
1208 else theLength = 50.;
1211 else theLength = theLength*8/10;
1213 gp_Pnt pmin1 ,pmin2;
1214 if (!isInfinite1 && !isInfinite2) {
1215 pmin1 = ptat11; pmin2 = ptat21;
1216 Standard_Real dis = ptat11.Distance(ptat21);
1217 Standard_Real dis2 = ptat11.Distance(ptat22);
1223 dis2 = ptat12.Distance(ptat22);
1229 dis2 = ptat12.Distance(ptat21);
1235 myCenter.SetXYZ( (pmin1.XYZ() + pmin2.XYZ()) / 2. );
1238 gp_Pnt pntOnl1 = gpl1.Location();
1239 gp_Pnt pntOnl2 = ElCLib::Value(ElCLib::Parameter(gpl1,pntOnl1),gpl2);
1240 myCenter.SetXYZ( (pntOnl1.XYZ() + pntOnl2.XYZ()) / 2. );
1247 if (myCenter.SquareDistance(ptat11) > myCenter.SquareDistance(ptat12)) d1 = gp_Dir(gp_Vec(myCenter,ptat11));
1248 else d1 = gp_Dir(gp_Vec(myCenter,ptat12));
1250 else d1 = gpl1.Direction();
1253 if (myCenter.SquareDistance(ptat21) > myCenter.SquareDistance(ptat22)) d2 = gp_Dir(gp_Vec(myCenter,ptat21));
1254 else d2 = gp_Dir(gp_Vec(myCenter,ptat22));
1256 else d2 = gpl2.Direction();
1259 if ( SameLines ) theaxis = myPlane->Pln().Axis().Direction();
1261 theaxis = gp_Dir(d1^d2);
1262 gp_Vec V1(d1); gp_Vec V2(d2);
1263 if ( V1.CrossMagnitude(V2) < 0 ) theaxis.Reverse();
1266 gp_Pnt curpos; // cursor position
1267 TColStd_Array1OfReal tabdist(1,4);
1268 gp_Pnt P1, P2; // points at intersection of the circle with 2 straight lines
1270 if (myAutomaticPosition) {
1272 tabdist(1) = myCenter.Distance(ptat11);
1273 tabdist(2) = myCenter.Distance(ptat12);
1276 tabdist(1) = tabdist(2) = 0.;
1279 tabdist(3) = myCenter.Distance(ptat21);
1280 tabdist(4) = myCenter.Distance(ptat22);
1283 tabdist(3) = tabdist(4) = 0.;
1286 Standard_Real dist1(RealLast());
1287 if (!isInfinite1) dist1 = Max(tabdist(1),tabdist(2));
1288 Standard_Real dist2(RealLast());
1289 if (!isInfinite2) dist2 = Max(tabdist(3),tabdist(4));
1291 myFAttach = myCenter;
1292 mySAttach = myCenter;
1296 myCenter.Translate(gp_Vec(d1)*theLength);
1298 // calculate attachments of the face
1299 // -> they are points of intersection if
1300 // intersection is outside of the edges
1301 Standard_Real pparam = ElCLib::Parameter(gpl1,myFAttach);
1302 Standard_Real pparam1 = ElCLib::Parameter(gpl1,ptat11);
1303 Standard_Real pparam2 = ElCLib::Parameter(gpl1,ptat12);
1305 if ( pparam1 < pparam2 ) {
1306 if ( pparam < pparam1 ) myFAttach = ptat11;
1307 else if ( pparam > pparam2) myFAttach = ptat12;
1310 if ( pparam < pparam2) myFAttach = ptat12;
1311 else if ( pparam > pparam1) myFAttach = ptat11;
1315 pparam = ElCLib::Parameter(gpl2,myFAttach);
1316 pparam1 = ElCLib::Parameter(gpl2,ptat21);
1317 pparam2 = ElCLib::Parameter(gpl2,ptat22);
1318 if ( pparam1 < pparam2 ) {
1319 if ( pparam < pparam1 ) mySAttach = ptat21;
1320 else if ( pparam > pparam2) mySAttach = ptat22;
1323 if ( pparam < pparam2) mySAttach = ptat22;
1324 else if ( pparam > pparam1) mySAttach = ptat21;
1328 // Case of disconneted lines
1330 gp_Ax2 AX(myCenter,theaxis,d1);
1331 Handle(Geom_Circle) circle = new Geom_Circle(AX,theLength);
1332 Handle(Geom2d_Curve) geoCurve = GeomAPI::To2d(circle,myPlane->Pln());
1333 Handle(Geom2d_Circle) c2d = *((Handle(Geom2d_Circle)*)& geoCurve);
1334 // calculate the intersection of circle with l1
1335 Standard_Real pparam; // parameter of the point of intersection on l1
1336 IntAna2d_AnaIntersection inter(l1_2d->Lin2d(),c2d->Circ2d());
1337 gp_Pnt2d pint1(inter.Point(1).Value());
1338 gp_Pnt2d pint2(inter.Point(2).Value());
1340 gp_Pnt Int1 = adp.Value(pint1.X(),pint1.Y());
1341 gp_Pnt Int2 = adp.Value(pint2.X(),pint2.Y());
1342 gp_Dir I1I2(gp_Vec(Int1,Int2));
1343 if ( d1*I1I2 > 0 ) {
1345 pparam = inter.Point(2).ParamOnFirst();
1349 pparam = inter.Point(1).ParamOnFirst();
1353 Standard_Real pparam1;
1354 Standard_Real pparam2;
1356 pparam1 = ElCLib::Parameter(gpl1,ptat11);
1357 pparam2 = ElCLib::Parameter(gpl1,ptat12);
1358 if ( pparam1 < pparam2 ) {
1359 if ( pparam < pparam1 ) myFAttach = ptat11;
1360 else if ( pparam > pparam2) myFAttach = ptat12;
1363 if ( pparam < pparam2) myFAttach = ptat12;
1364 else if ( pparam > pparam1) myFAttach = ptat11;
1367 pparam = ElCLib::Parameter(gpl2,P1);
1368 mySAttach = ElCLib::Value(pparam, gpl2);
1372 pparam1 = ElCLib::Parameter(gpl2,ptat21);
1373 pparam2 = ElCLib::Parameter(gpl2,ptat22);
1374 if ( pparam1 < pparam2 ) {
1375 if ( pparam < pparam1 ) mySAttach = ptat21;
1376 else if ( pparam > pparam2) mySAttach = ptat22;
1379 if ( pparam < pparam2) mySAttach = ptat22;
1380 else if ( pparam > pparam1) mySAttach = ptat21;
1384 curpos.SetXYZ(.5*(P1.XYZ()+P2.XYZ()));
1386 gp_Ax2 ax(myCenter,theaxis,d1);
1387 gp_Circ circle(ax,theLength);
1388 Standard_Real par = ElCLib::Parameter(circle,curpos);
1389 curpos = ElCLib::Value(par,circle);
1392 curpos = AIS::TranslatePointToBound( curpos, gp_Dir( gp_Vec( myCenter, curpos ) ), myBndBox );
1394 myAutomaticPosition = Standard_True;
1397 curpos = myPosition;
1398 gp_Lin Media(myCenter, gpl1.Direction());
1399 Standard_Real pcurpos = ElCLib::Parameter(Media, curpos);
1400 myCenter = ElCLib::Value(pcurpos, Media);
1401 // the centre is translated to avoid a constant radius!
1402 myCenter.Translate(-theLength*gp_Vec(gpl1.Direction()));
1403 gp_Ax2 AX(myCenter,theaxis,gpl1.Direction());
1404 Handle(Geom_Circle) circle = new Geom_Circle(AX,theLength);
1407 pcurpos = ElCLib::Parameter(circle->Circ(), curpos);
1408 curpos = ElCLib::Value(pcurpos, circle->Circ());
1410 Handle(Geom2d_Curve) geoCurve = GeomAPI::To2d(circle,myPlane->Pln());
1411 Handle(Geom2d_Circle) c2d = *((Handle(Geom2d_Circle)*)& geoCurve);
1412 // calculate the point of intersection of circle with l1
1413 IntAna2d_AnaIntersection inter(l1_2d->Lin2d(),c2d->Circ2d());
1414 gp_Pnt2d pint1(inter.Point(1).Value());
1415 gp_Pnt2d pint2(inter.Point(2).Value());
1416 gp_Pnt Int1 = adp.Value(pint1.X(),pint1.Y());
1417 gp_Pnt Int2 = adp.Value(pint2.X(),pint2.Y());
1418 if ( curpos.SquareDistance(Int1) < curpos.SquareDistance(Int2)) myFAttach = Int1;
1419 else myFAttach = Int2;
1422 // calculate the point of intersection of circle with l2
1423 // -> this is the projection because the centre of circle
1424 // is in the middle of l1 and l2
1425 Standard_Real pparam = ElCLib::Parameter(gpl2,myFAttach);
1426 mySAttach = ElCLib::Value(pparam, gpl2);
1430 Standard_Real par_attach(ElCLib::Parameter(gpl1,myFAttach));
1431 Standard_Real par1,par2;
1433 par1 = ElCLib::Parameter(gpl1,ptat11);
1434 par2 = ElCLib::Parameter(gpl1,ptat12);
1436 if ( par_attach < par1 ) myFAttach = ptat11;
1437 else if ( par_attach > par2) myFAttach = ptat12;
1440 if ( par_attach < par2 ) myFAttach = ptat12;
1441 else if ( par_attach > par1) myFAttach = ptat11;
1444 par_attach = ElCLib::Parameter(gpl2,mySAttach);
1446 par1 = ElCLib::Parameter(gpl2,ptat21);
1447 par2 = ElCLib::Parameter(gpl2,ptat22);
1449 if ( par_attach < par1 ) mySAttach = ptat21;
1450 else if ( par_attach > par2) mySAttach = ptat22;
1453 if ( par_attach < par2 ) mySAttach = ptat22;
1454 else if ( par_attach > par1) mySAttach = ptat21;
1459 myFDir = gp_Dir(gp_Vec(myCenter,P1));
1460 mySDir = gp_Dir(gp_Vec(myCenter,P2));
1462 //--------------------------------------------------------
1463 // Computation of the presentation
1464 //--------------------------------------------------------
1465 Handle(Prs3d_AngleAspect) la = myDrawer->AngleAspect();
1466 Handle(Prs3d_ArrowAspect) arr = la->ArrowAspect();
1468 arr->SetLength(myArrowSize);
1471 DsgPrs_AnglePresentation::Add(aPresentation,
1486 DsgPrs_AnglePresentation::Add(aPresentation,
1500 //=======================================================================
1501 //function : Compute3DSelection
1502 // purpose : compute the zones of selection for an angle dimension
1504 //=======================================================================
1506 void AIS_AngleDimension::Compute3DSelection( const Handle( SelectMgr_Selection )& aSelection )
1508 gp_Circ AngleCirc, AttachCirc;
1509 Standard_Real FirstParAngleCirc, LastParAngleCirc, FirstParAttachCirc, LastParAttachCirc;
1510 gp_Pnt EndOfArrow1, EndOfArrow2, ProjAttachPoint2;
1511 gp_Dir DirOfArrow1, DirOfArrow2;
1512 gp_Dir axisdir = (myVal <= Precision::Angular() || Abs( M_PI-myVal ) <= Precision::Angular())?
1513 myPlane->Pln().Axis().Direction() : (myFDir ^ mySDir);
1514 Standard_Boolean isPlane = (myFirstSurfType == AIS_KOS_Plane)? Standard_True : Standard_False;
1516 Standard_Real ArrowLength = myDrawer->AngleAspect()->ArrowAspect()->Length();
1517 DsgPrs::ComputeFacesAnglePresentation( ArrowLength,
1538 LastParAttachCirc );
1540 Handle( SelectMgr_EntityOwner ) own = new SelectMgr_EntityOwner( this, 7 );
1541 Handle( Select3D_SensitiveSegment ) seg;
1542 Handle( Geom_TrimmedCurve ) curve;
1543 Handle( Select3D_SensitiveCurve ) SensCurve;
1545 // Angle's arc or line
1546 if (myVal > Precision::Angular() && Abs( M_PI-myVal ) > Precision::Angular())
1548 curve = new Geom_TrimmedCurve( new Geom_Circle( AngleCirc ), FirstParAngleCirc, LastParAngleCirc );
1549 SensCurve = new Select3D_SensitiveCurve( own, curve );
1550 aSelection->Add( SensCurve );
1552 else // angle's line
1554 gp_Vec ArrowVec( DirOfArrow1 );
1555 ArrowVec *= ArrowLength;
1556 gp_Pnt FirstPoint, LastPoint;
1558 if (myPosition.Distance( EndOfArrow1 ) > ArrowLength)
1560 FirstPoint = myPosition;
1561 LastPoint = EndOfArrow1.Translated( ArrowVec );
1562 if (myPosition.SquareDistance( LastPoint ) < myPosition.SquareDistance( EndOfArrow1 ))
1563 LastPoint = EndOfArrow1.Translated( -ArrowVec );
1567 FirstPoint = EndOfArrow1.Translated( ArrowVec );
1568 LastPoint = EndOfArrow1.Translated( -ArrowVec );
1570 seg = new Select3D_SensitiveSegment( own, FirstPoint, LastPoint );
1571 aSelection->Add( seg );
1574 if (! myFAttach.IsEqual( EndOfArrow1, Precision::Confusion() ))
1576 seg = new Select3D_SensitiveSegment( own, myFAttach, EndOfArrow1 );
1577 aSelection->Add( seg );
1579 if (! ProjAttachPoint2.IsEqual( EndOfArrow2, Precision::Confusion() ))
1581 seg = new Select3D_SensitiveSegment( own, ProjAttachPoint2, EndOfArrow2 );
1582 aSelection->Add( seg );
1585 // Line or arc from mySAttach to its "projection"
1586 if (! mySAttach.IsEqual( ProjAttachPoint2, Precision::Confusion() ))
1590 seg = new Select3D_SensitiveSegment( own, mySAttach, ProjAttachPoint2 );
1591 aSelection->Add( seg );
1595 curve = new Geom_TrimmedCurve( new Geom_Circle( AttachCirc ),
1597 LastParAttachCirc );
1598 SensCurve = new Select3D_SensitiveCurve( own, curve );
1599 aSelection->Add( SensCurve );
1604 Standard_Real size(Min(myVal/100.+1.e-6,myArrowSize+1.e-6));
1605 Handle( Select3D_SensitiveBox ) box = new Select3D_SensitiveBox( own,
1609 myPosition.X() + size,
1610 myPosition.Y() + size,
1611 myPosition.Z() + size);
1612 aSelection->Add(box);
1615 //=======================================================================
1616 //function : Compute2DSelection
1617 //purpose : compute zones of selection on a side of angle between 2 edges
1618 // Special processing of zero angles!
1619 //=======================================================================
1621 void AIS_AngleDimension::Compute2DSelection(const Handle(SelectMgr_Selection)& aSelection)
1623 BRepAdaptor_Curve cu1(TopoDS::Edge(myFShape));
1624 BRepAdaptor_Curve cu2(TopoDS::Edge(mySShape));
1626 gp_Lin l1(cu1.Line());
1627 gp_Lin l2(cu2.Line());
1630 if (Abs( myVal ) <= Precision::Angular() || Abs( M_PI - myVal ) <= Precision::Angular())
1632 //---------------------------------------------------------
1633 // Cas de droites paralleles ( <=> angle nul a M_PI pres)
1634 if ((Abs(l1.Angle(l2)) < Precision::Angular()) ||
1635 (Abs((l1.Angle(l2) - M_PI)) < Precision::Angular()) )
1639 Standard_Real distLL= l1.Distance(l2);
1640 if ( Abs(distLL) <= Precision::Confusion() ) {
1641 gp_Pnt ptat11 = cu1.Value(cu1.FirstParameter());
1642 gp_Pnt ptat12 = cu1.Value(cu1.LastParameter());
1643 gp_Pnt ptat21 = cu2.Value(cu2.FirstParameter());
1644 gp_Pnt ptat22 = cu2.Value(cu2.LastParameter());
1645 distLL = 0.75 * Max( ptat11.Distance(ptat12), ptat21.Distance(ptat22));
1646 ComputeNull2DSelection(aSelection, distLL);
1649 ComputeNull2DSelection(aSelection, distLL*8/10);
1653 //----------------------------------------------------------
1654 // Classic case ( angle != 0 )
1657 if (myFDir.IsParallel(mySDir,Precision::Angular())) {
1658 Standard_Real distLL= l1.Distance(l2);
1659 if ( Abs(distLL) <= Precision::Confusion() ) {
1660 gp_Pnt ptat11 = cu1.Value(cu1.FirstParameter());
1661 gp_Pnt ptat12 = cu1.Value(cu1.LastParameter());
1662 gp_Pnt ptat21 = cu2.Value(cu2.FirstParameter());
1663 gp_Pnt ptat22 = cu2.Value(cu2.LastParameter());
1664 distLL = 0.75 * Max( ptat11.Distance(ptat12), ptat21.Distance(ptat22));
1665 ComputeNull2DSelection(aSelection, distLL*8/10);
1669 gp_Dir Norm = myFDir.Crossed(mySDir);
1671 gp_Ax2 ax(myCenter,Norm,myFDir);
1672 gp_Circ cer(ax,myCenter.Distance(myPosition));
1673 gp_Vec vec1(myFDir);
1675 Standard_Boolean nullrad(Standard_False);
1676 if (cer.Radius() == 0.) {
1678 nullrad = Standard_True;
1680 vec1 *= cer.Radius();
1681 gp_Pnt p1 = myCenter.Translated(vec1);
1682 gp_Vec vec2(mySDir);
1683 vec2 *= cer.Radius();
1684 gp_Pnt p2 = myCenter.Translated(vec2);
1686 Standard_Real uc1 = 0.;
1687 Standard_Real uc2 = ElCLib::Parameter(cer,p2);
1689 if (nullrad) uco = ElCLib::Parameter(cer,p1);
1690 else uco = ElCLib::Parameter(cer,myPosition);
1692 Standard_Real udeb = uc1;
1693 Standard_Real ufin = uc2;
1696 if (Abs(myVal)<M_PI) {
1697 // test if uco is in the opposing sector
1698 if (uco > udeb+M_PI && uco < ufin+M_PI){
1707 if ((uco-uc2) < (uc1-uco+(2*M_PI))) ufin = uco;
1708 else udeb = uco - 2*M_PI;
1710 p1 = ElCLib::Value(udeb,cer);
1711 p2 = ElCLib::Value(ufin,cer);
1713 //Create 2 owners for each part of the arrow
1714 Handle(AIS_DimensionOwner) own1 = new AIS_DimensionOwner(this,7);
1715 Handle(AIS_DimensionOwner) own2 = new AIS_DimensionOwner(this,7);
1716 if (myExtShape != 0) {
1717 if (myExtShape == 1) {
1718 own1->SetShape(mySShape);
1719 own2->SetShape(mySShape);
1722 own1->SetShape(myFShape);
1723 own2->SetShape(myFShape);
1727 own1->SetShape(myFShape);
1728 own2->SetShape(mySShape);
1731 Handle(Geom_Circle) thecirc = new Geom_Circle(cer);
1733 Handle(Geom_TrimmedCurve) thecu1 = new Geom_TrimmedCurve(thecirc,udeb,(udeb+ufin)/2);
1734 Handle(Geom_TrimmedCurve) thecu2 = new Geom_TrimmedCurve(thecirc,(udeb+ufin)/2,ufin);
1736 Handle(Select3D_SensitiveCurve) scurv = new Select3D_SensitiveCurve(own1,thecu1);
1737 aSelection->Add(scurv);
1738 scurv = new Select3D_SensitiveCurve(own2,thecu2);
1739 aSelection->Add(scurv);
1741 Handle(Select3D_SensitiveSegment) seg;
1742 if (!myFAttach.IsEqual(p1,Precision::Confusion())) {
1743 seg = new Select3D_SensitiveSegment(own1,myFAttach,p1);
1744 aSelection->Add(seg);
1746 if (!mySAttach.IsEqual(p2,Precision::Confusion())) {
1747 seg = new Select3D_SensitiveSegment(own2,mySAttach,p2);
1748 aSelection->Add(seg);
1754 //=======================================================================
1755 //function : Compute2DNullSelection
1756 //purpose : for dimension of null angle
1757 //=======================================================================
1759 void AIS_AngleDimension::ComputeNull2DSelection(
1760 const Handle(SelectMgr_Selection)& aSelection,
1761 const Standard_Real distLL)
1764 if ( myFDir.IsParallel(mySDir, Precision::Angular()) ) {
1765 Norm = myPlane->Pln().Axis().Direction();
1768 Norm = myFDir.Crossed(mySDir);
1770 gp_Ax2 ax(myCenter,Norm,myFDir);
1771 gp_Circ cer(ax,distLL);
1773 gp_Vec vec1(myFDir);
1774 vec1 *= cer.Radius();
1775 gp_Pnt p1 = myCenter.Translated(vec1);
1776 gp_Vec vec2(mySDir);
1777 vec2 *= cer.Radius();
1778 gp_Pnt p2 = myCenter.Translated(vec2);
1780 // calcul de parametres de debut et de fin des extremites de l'arc
1781 Standard_Real uc1 = 0.;
1782 Standard_Real uc2 = ElCLib::Parameter(cer,p2);
1783 Standard_Real uco = ElCLib::Parameter(cer,myPosition);
1785 Standard_Real udeb = uc1;
1786 Standard_Real ufin = uc2;
1789 if (Abs(myVal)<M_PI) {
1790 // test if uco is in the opposing sector
1791 if (uco > udeb+M_PI && uco < ufin+M_PI){
1801 if ((uco-uc2) < (uc1-uco+(2*M_PI))) {
1805 udeb = uco - 2*M_PI;
1809 //Create 2 owners for each part of the arrow
1810 Handle(AIS_DimensionOwner) own1 = new AIS_DimensionOwner(this,7);
1811 Handle(AIS_DimensionOwner) own2 = new AIS_DimensionOwner(this,7);
1812 if (myExtShape != 0) {
1813 if (myExtShape == 1) {
1814 own1->SetShape(mySShape);
1815 own2->SetShape(mySShape);
1818 own1->SetShape(myFShape);
1819 own2->SetShape(myFShape);
1823 own1->SetShape(myFShape);
1824 own2->SetShape(mySShape);
1827 Handle(Geom_Circle) thecirc = new Geom_Circle(cer);
1829 if ( udeb != ufin ) {
1830 Handle(Geom_TrimmedCurve) thecu1 = new Geom_TrimmedCurve(thecirc,udeb,(udeb+ufin)/2);
1831 Handle(Geom_TrimmedCurve) thecu2 = new Geom_TrimmedCurve(thecirc,(udeb+ufin)/2,ufin);
1833 Handle(Select3D_SensitiveCurve) scurv = new Select3D_SensitiveCurve(own1,thecu1);
1834 aSelection->Add(scurv);
1835 scurv = new Select3D_SensitiveCurve(own2,thecu2);
1836 aSelection->Add(scurv);
1839 // find end of segment to allow selection
1840 gp_Vec VTrans(myFDir.Crossed(Norm));
1841 Handle(Select3D_SensitiveSegment) seg1;
1842 seg1 = new Select3D_SensitiveSegment(own1,
1844 p1.Translated( VTrans*distLL/10 ) );
1845 aSelection->Add(seg1);
1846 seg1 = new Select3D_SensitiveSegment(own2,
1848 p2.Translated(-VTrans*distLL/10 ) );
1849 aSelection->Add(seg1);
1852 Handle(Select3D_SensitiveSegment) seg;
1853 if (!myFAttach.IsEqual(p1,Precision::Confusion())) {
1854 seg = new Select3D_SensitiveSegment(own1,myFAttach,p1);
1855 aSelection->Add(seg);
1858 if (!mySAttach.IsEqual(p2,Precision::Confusion())) {
1859 seg = new Select3D_SensitiveSegment(own2,mySAttach,p2);
1860 aSelection->Add(seg);
1865 //=======================================================================
1866 //function : ComputeConeAngleSelection
1867 //purpose : for cone angle
1868 //=======================================================================
1869 void AIS_AngleDimension::ComputeConeAngleSelection(const Handle(SelectMgr_Selection)& aSelection)
1871 if( myCone.IsNull() ) return;
1874 Handle( SelectMgr_EntityOwner ) owner = new SelectMgr_EntityOwner( this, 7 );
1875 Handle( Select3D_SensitiveSegment ) seg;
1881 Handle( Geom_Surface ) aSurf; //a surface from the Face
1882 Handle( Geom_OffsetSurface ) aOffsetSurf;
1883 Handle( Geom_ConicalSurface ) aConicalSurf;
1884 Handle( Geom_SurfaceOfRevolution ) aRevSurf;
1885 Handle( Geom_Line ) aLine;
1886 BRepAdaptor_Surface tmpSurf(myCone);
1888 AIS_KindOfSurface aSurfType;
1889 Standard_Real Offset = 0. ;
1890 Handle( Standard_Type ) aType;
1892 Standard_Real maxV = tmpSurf.FirstVParameter();
1893 Standard_Real minV = tmpSurf.LastVParameter();
1895 AIS::GetPlaneFromFace( myCone, aPln, aSurf, aSurfType, Offset );
1897 if ( aSurfType == AIS_KOS_Revolution ) { //surface of revolution
1899 aRevSurf = Handle( Geom_SurfaceOfRevolution )::DownCast( aSurf );
1900 gp_Lin ln( aRevSurf->Axis() );
1901 Handle( Geom_Curve ) tmpCrv = aRevSurf->BasisCurve();
1902 if ( tmpCrv ->DynamicType() != STANDARD_TYPE(Geom_Line) ) return; //Must be a part of line
1905 gp_Pnt fst = tmpSurf.Value(0., minV);
1906 gp_Pnt lst = tmpSurf.Value(0., maxV);
1908 gp_Vec vec1(fst, lst);
1910 par = ElCLib::Parameter( ln, fst );
1911 gp_Pnt fst2 = ElCLib::Value( par, ln ); //projection fst on ln
1912 par = ElCLib::Parameter( ln, lst );
1913 gp_Pnt lst2 = ElCLib::Value( par, ln ); //projection lst on ln
1915 gp_Vec vec2(fst2, lst2);
1917 // Check if two parts of revolution are parallel ( it's a cylinder ) or normal (it's a circle )
1918 if( vec1.IsParallel( vec2,Precision::Angular() ) || vec1.IsNormal( vec2,Precision::Angular() ) ) return;
1920 gce_MakeCone mkCone(aRevSurf->Axis(), fst, lst);
1921 aCone = mkCone.Value();
1922 Apex = aCone.Apex();
1925 aType = aSurf->DynamicType();
1926 if ( aType == STANDARD_TYPE(Geom_OffsetSurface) || Offset > 0.01 ) { //offset surface
1927 aOffsetSurf = new Geom_OffsetSurface (aSurf, Offset);
1928 aSurf = aOffsetSurf->Surface();
1929 BRepBuilderAPI_MakeFace mkFace(aSurf, Precision::Confusion());
1931 if( !mkFace.IsDone() ) return;
1932 tmpSurf.Initialize( mkFace.Face() );
1935 aCone = tmpSurf.Cone();
1936 aConicalSurf = Handle( Geom_ConicalSurface)::DownCast( aSurf );
1937 Apex = aConicalSurf->Apex();
1940 Handle(Geom_Curve) aCurve; //A circle where the angle is drawn
1942 if ( myAutomaticPosition ) {
1943 Standard_Real midV = ( minV + maxV ) / 2.5;
1945 aCurve = aSurf->VIso(midV);
1946 myCircle = Handle(Geom_Circle)::DownCast(aCurve)->Circ();
1948 myPosition = ElCLib::Value(M_PI / 2.0, myCircle);
1949 myAutomaticPosition = Standard_False;
1953 ElSLib::Parameters(aCone, myPosition, U, V);
1954 aCurve = aSurf->VIso(V);
1955 myCircle = Handle(Geom_Circle)::DownCast(aCurve)->Circ();
1957 //__________________________________________________________________
1958 aCurve = aSurf->VIso(maxV);
1959 gp_Circ CircVmax = Handle(Geom_Circle)::DownCast(aCurve)->Circ();
1960 aCurve = aSurf->VIso(minV);
1961 gp_Circ CircVmin = Handle(Geom_Circle)::DownCast(aCurve)->Circ();
1962 //__________________________________________________________________
1964 if( CircVmax.Radius() < CircVmin.Radius() ) {
1965 gp_Circ tmpCirc = CircVmax;
1966 CircVmax = CircVmin;
1970 Standard_Boolean IsArrowOut = Standard_True; //Is arrows inside or outside of the cone
1971 //Standard_Real PntOnMainAxis = 0; //Is projection of aPosition inside of the cone = 0, above = 1, or below = -1
1972 Standard_Boolean IsConeTrimmed = Standard_False;
1974 if( CircVmin.Radius() > 0.01 ) IsConeTrimmed = Standard_True;
1976 gp_Pnt AttachmentPnt;
1979 Standard_Real param = ElCLib::Parameter(myCircle, myPosition);
1982 gp_Pnt P1 = ElCLib::Value(0., myCircle);
1983 gp_Pnt P2 = ElCLib::Value(M_PI, myCircle);
1985 gce_MakePln mkPln(P1, P2, aPnt); // create a plane whitch defines plane for projection aPosition on it
1987 aPnt = AIS::ProjectPointOnPlane(myPosition, mkPln.Value());
1988 gp_Pnt tmpPnt = aPnt;
1990 if( aPnt.Distance(P1) < aPnt.Distance(P2) ){
1999 aPnt = AttachmentPnt ; // Creating of circle whitch defines a plane for a dimension arc
2000 gp_Vec Vec(AttachmentPnt, Apex); // Dimension arc is a part of the circle
2002 aPnt.Translate(Vec);
2003 GC_MakeCircle mkCirc(AttachmentPnt, OppositePnt, aPnt);
2004 gp_Circ aCircle2 = mkCirc.Value()->Circ();
2008 Standard_Real AttParam = ElCLib::Parameter(aCircle2, AttachmentPnt);
2009 Standard_Real OppParam = ElCLib::Parameter(aCircle2, OppositePnt);
2011 while ( AttParam >= 2 * M_PI ) AttParam -= 2 * M_PI;
2012 while ( OppParam >= 2 * M_PI ) OppParam -= 2 * M_PI;
2014 if( myPosition.Distance( myCircle.Location() ) <= myCircle.Radius() )
2015 if( 2 * myCircle.Radius() > aCircle2.Radius() * 0.4 ) IsArrowOut = Standard_False; //four times more than an arrow size
2018 Standard_Real angle = OppParam - AttParam;
2022 angle += M_PI / 6; //An angle between AttParam and OppParam + 30 degrees
2023 param -= M_PI / 12; //out parts of dimension line are 15 degrees
2026 while ( angle > 2. * M_PI ) angle -= 2. * M_PI;
2028 gp_Pnt Vprev = ElCLib::Value(param, aCircle2);
2029 for( i = 1; i <= 11; i++ ) //calculating of arc
2031 gp_Pnt Vcur = ElCLib::Value(param + angle/11 * i, aCircle2);
2032 seg = new Select3D_SensitiveSegment(owner, Vprev, Vcur);
2033 aSelection->Add(seg);
2037 tmpPnt = tmpPnt.Translated(gp_Vec(0, 0, -2));
2039 const Standard_Real size(Min(myVal/100.+1.e-6,myArrowSize+1.e-6));
2040 Handle( Select3D_SensitiveBox ) box = new Select3D_SensitiveBox( owner,
2047 aSelection->Add(box);