1 // Created on: 1996-12-05
2 // Created by: Jean-Pierre COMBE/Odile Olivier
3 // Copyright (c) 1996-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
6 // This file is part of Open CASCADE Technology software library.
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
19 #include <AIS_Shape.hxx>
20 #include <AIS_TangentRelation.hxx>
21 #include <Bnd_Box.hxx>
22 #include <BRep_Tool.hxx>
23 #include <BRepAdaptor_Surface.hxx>
24 #include <BRepBuilderAPI_MakeFace.hxx>
25 #include <DsgPrs_TangentPresentation.hxx>
27 #include <Geom_Circle.hxx>
28 #include <Geom_Ellipse.hxx>
29 #include <Geom_Line.hxx>
30 #include <Geom_Plane.hxx>
31 #include <Geom_Transformation.hxx>
32 #include <GeomAPI_ExtremaCurveCurve.hxx>
33 #include <gp_Circ.hxx>
38 #include <Precision.hxx>
39 #include <Prs3d_Presentation.hxx>
40 #include <Prs3d_Projector.hxx>
41 #include <Select3D_SensitiveSegment.hxx>
42 #include <SelectMgr_EntityOwner.hxx>
43 #include <SelectMgr_Selection.hxx>
44 #include <Standard_NotImplemented.hxx>
45 #include <Standard_Type.hxx>
46 #include <TColStd_ListIteratorOfListOfTransient.hxx>
47 #include <TopAbs_ShapeEnum.hxx>
48 #include <TopExp_Explorer.hxx>
50 #include <TopoDS_Edge.hxx>
51 #include <TopoDS_Face.hxx>
52 #include <TopoDS_Shape.hxx>
53 #include <TopoDS_Vertex.hxx>
55 IMPLEMENT_STANDARD_RTTIEXT(AIS_TangentRelation,AIS_Relation)
57 //=======================================================================
58 //function : Constructor
60 //=======================================================================
61 AIS_TangentRelation::AIS_TangentRelation(const TopoDS_Shape& aFShape,
62 const TopoDS_Shape& aSShape,
63 const Handle(Geom_Plane)& aPlane,
64 const Standard_Integer anExternRef)
65 :myExternRef(anExternRef)
70 myAutomaticPosition = Standard_False;
73 //=======================================================================
74 //function : ExternRef
76 //=======================================================================
77 Standard_Integer AIS_TangentRelation::ExternRef()
82 //=======================================================================
83 //function : SetExternRef
85 //=======================================================================
86 void AIS_TangentRelation::SetExternRef(const Standard_Integer aRef)
91 //=======================================================================
94 //=======================================================================
95 void AIS_TangentRelation::Compute(const Handle(PrsMgr_PresentationManager3d)&,
96 const Handle(Prs3d_Presentation)& aPresentation,
97 const Standard_Integer)
99 aPresentation->Clear();
101 switch (myFShape.ShapeType())
105 ComputeTwoFacesTangent(aPresentation);
110 ComputeTwoEdgesTangent(aPresentation);
118 //=======================================================================
120 //purpose : to avoid warning
121 //=======================================================================
122 void AIS_TangentRelation::Compute(const Handle(Prs3d_Projector)& aProjector,
123 const Handle(Prs3d_Presentation)& aPresentation)
125 // Standard_NotImplemented::Raise("AIS_TangentRelation::Compute(const Handle(Prs3d_Projector)&,const Handle(Prs3d_Presentation)&)");
126 PrsMgr_PresentableObject::Compute( aProjector , aPresentation ) ;
129 void AIS_TangentRelation::Compute(const Handle(Prs3d_Projector)& aProjector,
130 const Handle(Geom_Transformation)& aTransformation,
131 const Handle(Prs3d_Presentation)& aPresentation)
133 // Standard_NotImplemented::Raise("AIS_TangentRelation::Compute(const Handle(Prs3d_Projector)&, const Handle(Geom_Transformation)&, const Handle(Prs3d_Presentation)&)");
134 PrsMgr_PresentableObject::Compute( aProjector , aTransformation , aPresentation ) ;
137 //=======================================================================
138 //function : ComputeSelection
140 //=======================================================================
141 void AIS_TangentRelation::ComputeSelection(const Handle(SelectMgr_Selection)& aSelection,
142 const Standard_Integer)
145 gp_Vec vec1 = vec.Multiplied(myLength);
146 gp_Vec vec2 = vec.Multiplied(-myLength);
147 gp_Pnt p1 = myPosition.Translated(vec1);
148 gp_Pnt p2 = myPosition.Translated(vec2);
150 Handle(SelectMgr_EntityOwner) own = new SelectMgr_EntityOwner(this,7);
151 Handle(Select3D_SensitiveSegment) seg = new Select3D_SensitiveSegment(own,p1,p2);
152 aSelection->Add(seg);
155 //=======================================================================
156 //function : ComputeTwoFacesTangent
158 //=======================================================================
159 void AIS_TangentRelation::ComputeTwoFacesTangent
160 (const Handle(Prs3d_Presentation)& /*aPresentation*/)
164 // jfa 19/10/2000 begin
165 //=======================================================================
166 //function : ComputeTangencyPoint
168 //=======================================================================
169 static Standard_Boolean ComputeTangencyPoint(const Handle(Geom_Curve)& GC1,
170 const Handle(Geom_Curve)& GC2,
173 Standard_Real U1f = GC1->FirstParameter();
174 Standard_Real U1l = GC1->LastParameter();
175 Standard_Real U2f = GC2->FirstParameter();
176 Standard_Real U2l = GC2->LastParameter();
179 Standard_Real mindist=0;
180 GeomAPI_ExtremaCurveCurve Ex(GC1,GC2,U1f,U1l,U2f,U2l);
181 for ( Standard_Integer i = 1; i <= Ex.NbExtrema(); i++)
185 Standard_Real dist = P1.Distance(P2);
193 if ( (dist < mindist) || (dist < Precision::Confusion()) )
199 if ( dist < Precision::Confusion() )
201 if (GC1->IsInstance(STANDARD_TYPE(Geom_Line)))
203 continue; // tangent line and conic can have only one point with zero distance
205 gp_Vec aVector1,aVector2;
206 if (GC1->IsInstance(STANDARD_TYPE(Geom_Circle)))
208 Handle(Geom_Circle) circle (Handle(Geom_Circle)::DownCast (GC1));
209 Standard_Real par_inter = ElCLib::Parameter(circle->Circ(), P1);
210 ElCLib::D1(par_inter,circle->Circ(),P1,aVector1);
212 else if (GC1->IsInstance(STANDARD_TYPE(Geom_Ellipse)))
214 Handle(Geom_Ellipse) ellipse (Handle(Geom_Ellipse)::DownCast (GC1));
215 Standard_Real par_inter = ElCLib::Parameter(ellipse->Elips(), P1);
216 ElCLib::D1(par_inter,ellipse->Elips(),P1,aVector1);
218 if (GC2->IsInstance(STANDARD_TYPE(Geom_Circle)))
220 Handle(Geom_Circle) circle (Handle(Geom_Circle)::DownCast (GC2));
221 Standard_Real par_inter = ElCLib::Parameter(circle->Circ(), P2);
222 ElCLib::D1(par_inter,circle->Circ(),P2,aVector2);
224 else if (GC2->IsInstance(STANDARD_TYPE(Geom_Ellipse)))
226 Handle(Geom_Ellipse) ellipse (Handle(Geom_Ellipse)::DownCast (GC2));
227 Standard_Real par_inter = ElCLib::Parameter(ellipse->Elips(), P2);
228 ElCLib::D1(par_inter,ellipse->Elips(),P2,aVector2);
230 // if ( aVector1.IsParallel(aVector2, 100*Precision::Angular()) ) break;
231 if ( aVector1.IsParallel(aVector2, M_PI / 360.0) ) break; // 0.5 graduce
235 return Standard_True;
237 // jfa 19/10/2000 end
239 //=======================================================================
240 //function : ComputeTwoEdgesTangent
242 //=======================================================================
243 void AIS_TangentRelation::ComputeTwoEdgesTangent(const Handle(Prs3d_Presentation)& aPresentation)
245 Handle(Geom_Curve) copy1,copy2;
246 gp_Pnt ptat11,ptat12,ptat21,ptat22;
247 Standard_Boolean isInfinite1,isInfinite2;
248 Handle(Geom_Curve) extCurv;
249 if (!AIS::ComputeGeometry(TopoDS::Edge(myFShape),
250 TopoDS::Edge(mySShape),
259 isInfinite1,isInfinite2,
265 aPresentation->SetInfiniteState(isInfinite1 || isInfinite2);
267 BRepBuilderAPI_MakeFace makeface(myPlane->Pln());
268 TopoDS_Face face(makeface.Face());
269 BRepAdaptor_Surface adp(makeface.Face());
271 Standard_Integer typArg(0);
273 if (copy1->IsInstance(STANDARD_TYPE(Geom_Line)))
277 else if (copy1->IsInstance(STANDARD_TYPE(Geom_Circle)))
281 else if (copy1->IsInstance(STANDARD_TYPE(Geom_Ellipse)))
287 if (copy2->IsInstance(STANDARD_TYPE(Geom_Line)))
291 else if (copy2->IsInstance(STANDARD_TYPE(Geom_Circle)))
295 else if (copy2->IsInstance(STANDARD_TYPE(Geom_Ellipse)))
301 //First find the tangengy vector if exists
303 TopExp_Explorer expF(TopoDS::Edge(myFShape),TopAbs_VERTEX);
304 TopExp_Explorer expS(TopoDS::Edge(mySShape),TopAbs_VERTEX);
307 for (p = 0; expF.More(); expF.Next(),p++)
309 tab[p] = TopoDS::Vertex(expF.Current());
311 Standard_Boolean found(Standard_False);
312 for ( ; expS.More() && !found; expS.Next())
314 for ( Standard_Integer l = 0; l<=p && !found; l++)
316 found = ( expS.Current().IsSame(tab[l]));
317 if (found) VCom = TopoDS::Vertex(expS.Current());
322 gp_Pnt pint3d; // tangency point
323 gp_Dir theDir; // tangency direction
324 Standard_Real par_inter = 0.0; // parameter of tangency point
328 pint3d = BRep_Tool::Pnt(VCom);
331 // Otherwise it is found as if it was known that 2 curves
332 // are tangents (which must be the cases)
335 case 12: // circle line
337 Handle(Geom_Line) line (Handle(Geom_Line)::DownCast (copy1));
338 Handle(Geom_Circle) circle (Handle(Geom_Circle)::DownCast (copy2));
342 // it is enough to project the circus center on the straight line
343 par_inter = ElCLib::Parameter(line->Lin(), circle->Location());
344 pint3d = ElCLib::Value(par_inter, line->Lin());
347 theDir = line->Lin().Direction();
348 myLength = circle->Radius()/5.;
351 Standard_Real copy1Length = ptat12.Distance(ptat11);
352 if ( copy1Length < myLength )
353 myLength = copy1Length/3.;
357 case 21: // circle line
359 Handle(Geom_Circle) circle (Handle(Geom_Circle)::DownCast (copy1));
360 Handle(Geom_Line) line (Handle(Geom_Line)::DownCast (copy2));
364 // it is enough to project the circus center on the straight line
365 par_inter = ElCLib::Parameter(line->Lin(), circle->Location());
366 pint3d = ElCLib::Value(par_inter, line->Lin());
369 theDir = line->Lin().Direction();
370 myLength = circle->Radius()/5.;
373 Standard_Real copy2Length = ptat21.Distance(ptat22);
374 if ( copy2Length < myLength )
375 myLength = copy2Length/3.;
379 // jfa 19/10/2000 begin
380 case 13: // line ellipse
382 Handle(Geom_Line) line (Handle(Geom_Line)::DownCast (copy1));
383 Handle(Geom_Ellipse) ellipse (Handle(Geom_Ellipse)::DownCast (copy2));
387 ComputeTangencyPoint(line,ellipse,pint3d);
390 theDir = line->Lin().Direction();
391 myLength = ellipse->MajorRadius()/5.;
395 Standard_Real copy1Length = ptat12.Distance(ptat11);
396 if ( copy1Length < myLength )
397 myLength = copy1Length/3.;
401 case 31: // ellipse line
403 Handle(Geom_Ellipse) ellipse (Handle(Geom_Ellipse)::DownCast (copy1));
404 Handle(Geom_Line) line (Handle(Geom_Line)::DownCast (copy2));
408 ComputeTangencyPoint(line,ellipse,pint3d);
411 theDir = line->Lin().Direction();
412 myLength = ellipse->MajorRadius()/5.;
416 Standard_Real copy2Length = ptat21.Distance(ptat22);
417 if ( copy2Length < myLength )
418 myLength = copy2Length/3.;
422 case 22: // circle circle
424 Handle(Geom_Circle) circle1 (Handle(Geom_Circle)::DownCast (copy1));
425 Handle(Geom_Circle) circle2 (Handle(Geom_Circle)::DownCast (copy2));
426 Standard_Real R1 = circle1->Radius();
427 Standard_Real R2 = circle2->Radius();
428 myLength = Max(R1,R2)/5.0;
431 if ( (circle1->Location()).IsEqual(circle2->Location(),Precision::Confusion()) )
435 ElCLib::D1(par_inter,circle1->Circ(),pint3d,theVector);
439 ElCLib::D1(par_inter,circle2->Circ(),pint3d,theVector);
446 par_inter = ElCLib::Parameter(circle1->Circ(), circle2->Location());
447 ElCLib::D1(par_inter,circle1->Circ(),pint3d,theVector);
451 par_inter = ElCLib::Parameter(circle2->Circ(), circle1->Location());
452 ElCLib::D1(par_inter,circle2->Circ(),pint3d,theVector);
458 par_inter = ElCLib::Parameter(circle1->Circ(), pint3d);
459 ElCLib::D1(par_inter,circle1->Circ(),pint3d,theVector);
461 theDir = gp_Dir(theVector);
464 case 23: // circle ellipse
466 Handle(Geom_Circle) circle (Handle(Geom_Circle)::DownCast (copy1));
467 Handle(Geom_Ellipse) ellipse (Handle(Geom_Ellipse)::DownCast (copy2));
468 Standard_Real R1 = circle->Radius();
469 Standard_Real R2 = ellipse->MajorRadius();
470 myLength = Max(R1,R2)/5.0;
475 ComputeTangencyPoint(circle,ellipse,pint3d);
476 par_inter = ElCLib::Parameter(circle->Circ(), pint3d);
477 ElCLib::D1(par_inter,circle->Circ(),pint3d,theVector);
481 ComputeTangencyPoint(ellipse,circle,pint3d);
482 par_inter = ElCLib::Parameter(ellipse->Elips(), pint3d);
483 ElCLib::D1(par_inter,ellipse->Elips(),pint3d,theVector);
488 par_inter = ElCLib::Parameter(circle->Circ(), pint3d);
489 ElCLib::D1(par_inter,circle->Circ(),pint3d,theVector);
491 theDir = gp_Dir(theVector);
494 case 32: // ellipse circle
496 Handle(Geom_Ellipse) ellipse (Handle(Geom_Ellipse)::DownCast (copy1));
497 Handle(Geom_Circle) circle (Handle(Geom_Circle)::DownCast (copy2));
498 Standard_Real R1 = ellipse->MajorRadius();
499 Standard_Real R2 = circle->Radius();
500 myLength = Max(R1,R2)/5.0;
505 ComputeTangencyPoint(ellipse,circle,pint3d);
506 par_inter = ElCLib::Parameter( ellipse->Elips(), pint3d);
507 ElCLib::D1(par_inter,ellipse->Elips(),pint3d,theVector);
511 ComputeTangencyPoint(circle,ellipse,pint3d);
512 par_inter = ElCLib::Parameter( circle->Circ(), pint3d);
513 ElCLib::D1(par_inter,circle->Circ(),pint3d,theVector);
518 par_inter = ElCLib::Parameter(circle->Circ(), pint3d);
519 ElCLib::D1(par_inter,circle->Circ(),pint3d,theVector);
521 theDir = gp_Dir(theVector);
524 case 33: // ellipse ellipse
526 Handle(Geom_Ellipse) ellipse1 (Handle(Geom_Ellipse)::DownCast (copy1));
527 Handle(Geom_Ellipse) ellipse2 (Handle(Geom_Ellipse)::DownCast (copy2));
528 Standard_Real R1 = ellipse1->MajorRadius();
529 Standard_Real R2 = ellipse2->MajorRadius();
530 myLength = Max(R1,R2)/5.0;
535 ComputeTangencyPoint(ellipse1,ellipse2,pint3d);
536 par_inter = ElCLib::Parameter( ellipse1->Elips(), pint3d);
537 ElCLib::D1(par_inter,ellipse1->Elips(),pint3d,theVector);
541 ComputeTangencyPoint(ellipse2,ellipse1,pint3d);
542 par_inter = ElCLib::Parameter( ellipse2->Elips(), pint3d);
543 ElCLib::D1(par_inter,ellipse2->Elips(),pint3d,theVector);
548 par_inter = ElCLib::Parameter(ellipse1->Elips(), pint3d);
549 ElCLib::D1(par_inter,ellipse1->Elips(),pint3d,theVector);
551 theDir = gp_Dir(theVector);
554 // jfa 19/10/2000 end
562 myLength = Min(myLength,myArrowSize);
564 DsgPrs_TangentPresentation::Add(aPresentation,myDrawer,myAttach,myDir,myLength);
565 if ( (myExtShape != 0) && !extCurv.IsNull())
568 if ( myExtShape == 1 )
575 ComputeProjEdgePresentation(aPresentation,TopoDS::Edge(myFShape),copy1,pf,pl);
584 ComputeProjEdgePresentation(aPresentation,TopoDS::Edge(mySShape),copy2,pf,pl);