0026936: Drawbacks of inlining in new type system in OCCT 7.0 -- automatic
[occt.git] / src / AIS / AIS_TangentRelation.cxx
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
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
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.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17
18 #include <AIS.hxx>
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>
26 #include <ElCLib.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>
34 #include <gp_Lin.hxx>
35 #include <gp_Pln.hxx>
36 #include <gp_Pnt.hxx>
37 #include <gp_Vec.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>
49 #include <TopoDS.hxx>
50 #include <TopoDS_Edge.hxx>
51 #include <TopoDS_Face.hxx>
52 #include <TopoDS_Shape.hxx>
53 #include <TopoDS_Vertex.hxx>
54
55 IMPLEMENT_STANDARD_RTTIEXT(AIS_TangentRelation,AIS_Relation)
56
57 //=======================================================================
58 //function : Constructor
59 //purpose  : 
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)
66 {
67   myFShape = aFShape;
68   mySShape = aSShape;
69   myPlane = aPlane;
70   myAutomaticPosition = Standard_False;
71 }
72
73 //=======================================================================
74 //function : ExternRef
75 //purpose  : 
76 //=======================================================================
77 Standard_Integer AIS_TangentRelation::ExternRef()
78 {
79   return myExternRef;
80 }
81
82 //=======================================================================
83 //function : SetExternRef
84 //purpose  : 
85 //=======================================================================
86 void AIS_TangentRelation::SetExternRef(const Standard_Integer aRef)
87 {
88   myExternRef = aRef;
89 }
90
91 //=======================================================================
92 //function : Compute
93 //purpose  : 
94 //=======================================================================
95 void AIS_TangentRelation::Compute(const Handle(PrsMgr_PresentationManager3d)&, 
96                                   const Handle(Prs3d_Presentation)& aPresentation, 
97                                   const Standard_Integer)
98 {
99   aPresentation->Clear();
100  
101   switch (myFShape.ShapeType())
102     {
103     case TopAbs_FACE :
104       {
105         ComputeTwoFacesTangent(aPresentation);
106       }
107       break;
108     case TopAbs_EDGE :
109       {
110         ComputeTwoEdgesTangent(aPresentation);
111       }
112       break;
113     default:
114       break;
115     }
116 }
117
118 //=======================================================================
119 //function : Compute
120 //purpose  : to avoid warning
121 //=======================================================================
122 void AIS_TangentRelation::Compute(const Handle(Prs3d_Projector)& aProjector,
123                                   const Handle(Prs3d_Presentation)& aPresentation)
124 {
125 // Standard_NotImplemented::Raise("AIS_TangentRelation::Compute(const Handle(Prs3d_Projector)&,const Handle(Prs3d_Presentation)&)");
126   PrsMgr_PresentableObject::Compute( aProjector , aPresentation ) ;
127 }
128
129 void AIS_TangentRelation::Compute(const Handle(Prs3d_Projector)& aProjector,
130                                   const Handle(Geom_Transformation)& aTransformation,
131                                   const Handle(Prs3d_Presentation)& aPresentation)
132 {
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 ) ;
135 }
136
137 //=======================================================================
138 //function : ComputeSelection
139 //purpose  : 
140 //=======================================================================
141 void AIS_TangentRelation::ComputeSelection(const Handle(SelectMgr_Selection)& aSelection, 
142                                            const Standard_Integer)
143 {
144   gp_Vec vec(myDir);
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);
149
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);
153 }
154
155 //=======================================================================
156 //function : ComputeTwoFacesTangent
157 //purpose  : 
158 //=======================================================================
159 void AIS_TangentRelation::ComputeTwoFacesTangent
160   (const Handle(Prs3d_Presentation)& /*aPresentation*/)
161 {
162 }
163
164 // jfa 19/10/2000 begin
165 //=======================================================================
166 //function : ComputeTangencyPoint
167 //purpose  : 
168 //=======================================================================
169 static Standard_Boolean ComputeTangencyPoint(const Handle(Geom_Curve)& GC1,
170                                              const Handle(Geom_Curve)& GC2,
171                                              gp_Pnt& aPoint)
172 {
173   Standard_Real U1f = GC1->FirstParameter();
174   Standard_Real U1l = GC1->LastParameter();
175   Standard_Real U2f = GC2->FirstParameter();
176   Standard_Real U2l = GC2->LastParameter();
177
178   gp_Pnt PC1;
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++)
182     {
183       gp_Pnt P1,P2;
184       Ex.Points(i,P1,P2);
185       Standard_Real dist = P1.Distance(P2);
186       if ( i == 1 )
187         {
188           mindist = dist;
189           PC1 = P1;
190         }
191       else
192         {
193           if ( (dist < mindist) || (dist < Precision::Confusion()) )
194             {
195               mindist = dist;
196               PC1 = P1;
197             }
198         }
199       if ( dist < Precision::Confusion() )
200         {
201           if (GC1->IsInstance(STANDARD_TYPE(Geom_Line)))
202             {
203               continue; // tangent line and conic can have only one point with zero distance
204             }
205           gp_Vec aVector1,aVector2;
206           if (GC1->IsInstance(STANDARD_TYPE(Geom_Circle)))
207             {
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);
211             }
212           else if (GC1->IsInstance(STANDARD_TYPE(Geom_Ellipse)))
213             {
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);
217             }
218           if (GC2->IsInstance(STANDARD_TYPE(Geom_Circle)))
219             {
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);
223             }
224           else if (GC2->IsInstance(STANDARD_TYPE(Geom_Ellipse)))
225             {
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);
229             }
230 //        if ( aVector1.IsParallel(aVector2, 100*Precision::Angular()) ) break;
231           if ( aVector1.IsParallel(aVector2, M_PI / 360.0) ) break; // 0.5 graduce
232         }
233     }
234   aPoint = PC1;
235   return Standard_True;
236 }
237 // jfa 19/10/2000 end
238
239 //=======================================================================
240 //function : ComputeTwoEdgesTangent
241 //purpose  : 
242 //=======================================================================
243 void AIS_TangentRelation::ComputeTwoEdgesTangent(const Handle(Prs3d_Presentation)& aPresentation)
244 {
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),
251                             myExtShape,
252                             copy1,
253                             copy2,
254                             ptat11,
255                             ptat12,
256                             ptat21,
257                             ptat22,
258                             extCurv,
259                             isInfinite1,isInfinite2,
260                             myPlane))
261     {
262       return;
263     }
264
265   aPresentation->SetInfiniteState(isInfinite1 || isInfinite2);
266   // current face  
267   BRepBuilderAPI_MakeFace makeface(myPlane->Pln());
268   TopoDS_Face face(makeface.Face());  
269   BRepAdaptor_Surface adp(makeface.Face());
270     
271   Standard_Integer typArg(0);
272   
273   if (copy1->IsInstance(STANDARD_TYPE(Geom_Line)))
274     {
275       typArg = 10;
276     }
277   else if (copy1->IsInstance(STANDARD_TYPE(Geom_Circle)))
278     {
279       typArg = 20;
280     }
281   else if (copy1->IsInstance(STANDARD_TYPE(Geom_Ellipse)))
282     {
283       typArg = 30;
284     }
285   else return;
286
287   if (copy2->IsInstance(STANDARD_TYPE(Geom_Line)))
288     {
289       typArg += 1;
290     }
291   else if (copy2->IsInstance(STANDARD_TYPE(Geom_Circle)))
292     {
293       typArg += 2;
294     }
295   else if (copy2->IsInstance(STANDARD_TYPE(Geom_Ellipse)))
296     {
297       typArg += 3;
298     }
299   else return;
300
301   //First find the tangengy vector if exists
302   TopoDS_Vertex VCom;
303   TopExp_Explorer expF(TopoDS::Edge(myFShape),TopAbs_VERTEX);
304   TopExp_Explorer expS(TopoDS::Edge(mySShape),TopAbs_VERTEX);
305   TopoDS_Shape tab[2];
306   Standard_Integer p ;
307   for (p = 0; expF.More(); expF.Next(),p++)
308     {
309       tab[p] = TopoDS::Vertex(expF.Current());
310     }
311   Standard_Boolean found(Standard_False);
312   for ( ; expS.More() && !found; expS.Next())
313     {
314       for ( Standard_Integer l = 0; l<=p && !found; l++)
315         {
316           found = ( expS.Current().IsSame(tab[l]));
317           if (found) VCom = TopoDS::Vertex(expS.Current());
318         }
319     }
320
321   gp_Vec theVector;
322   gp_Pnt pint3d; // tangency point
323   gp_Dir theDir; // tangency direction
324   Standard_Real par_inter = 0.0; // parameter of tangency point
325
326   if (found)
327     {
328       pint3d = BRep_Tool::Pnt(VCom);
329     }
330
331   // Otherwise it is found as if it was known that 2 curves
332   // are tangents (which must be the cases)
333   switch (typArg)
334     {
335     case 12: // circle line      
336        {
337         Handle(Geom_Line) line (Handle(Geom_Line)::DownCast (copy1));
338         Handle(Geom_Circle) circle (Handle(Geom_Circle)::DownCast (copy2));
339
340         if ( !found )
341           {
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());
345           }
346       
347         theDir = line->Lin().Direction();
348         myLength = circle->Radius()/5.;
349         if ( !isInfinite1 )
350           {
351             Standard_Real copy1Length = ptat12.Distance(ptat11);
352             if ( copy1Length < myLength )
353               myLength = copy1Length/3.;
354           }
355       }
356       break;
357     case 21: // circle line
358       {
359         Handle(Geom_Circle) circle (Handle(Geom_Circle)::DownCast (copy1));
360         Handle(Geom_Line) line (Handle(Geom_Line)::DownCast (copy2));
361       
362         if (!found)
363           {
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());
367           }
368       
369         theDir = line->Lin().Direction();
370         myLength = circle->Radius()/5.;
371         if (!isInfinite2)
372           {
373             Standard_Real copy2Length = ptat21.Distance(ptat22);
374             if ( copy2Length < myLength )
375               myLength = copy2Length/3.;
376           }
377       }
378       break;
379     // jfa 19/10/2000 begin
380     case 13: // line ellipse
381       {
382         Handle(Geom_Line) line (Handle(Geom_Line)::DownCast (copy1));
383         Handle(Geom_Ellipse) ellipse (Handle(Geom_Ellipse)::DownCast (copy2));
384
385         if (!found)
386           {
387             ComputeTangencyPoint(line,ellipse,pint3d);
388           }
389       
390         theDir = line->Lin().Direction();
391         myLength = ellipse->MajorRadius()/5.;
392
393         if (!isInfinite1)
394           {
395             Standard_Real copy1Length = ptat12.Distance(ptat11);
396             if ( copy1Length < myLength )
397               myLength = copy1Length/3.;
398           }
399       }
400       break;
401     case 31: // ellipse line
402       {
403         Handle(Geom_Ellipse) ellipse (Handle(Geom_Ellipse)::DownCast (copy1));
404         Handle(Geom_Line) line (Handle(Geom_Line)::DownCast (copy2));
405       
406         if (!found)
407           {
408             ComputeTangencyPoint(line,ellipse,pint3d);
409           }
410       
411         theDir = line->Lin().Direction();
412         myLength = ellipse->MajorRadius()/5.;
413
414         if (!isInfinite2)
415           {
416             Standard_Real copy2Length = ptat21.Distance(ptat22);
417             if ( copy2Length < myLength )
418               myLength = copy2Length/3.;
419           }
420       }
421       break;
422     case 22: // circle circle
423       {
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;
429         if ( !found )
430           {
431             if ( (circle1->Location()).IsEqual(circle2->Location(),Precision::Confusion()) )
432               {
433                 if ( R1 >= R2 )
434                   {
435                     ElCLib::D1(par_inter,circle1->Circ(),pint3d,theVector);
436                   }
437                 else
438                   {
439                     ElCLib::D1(par_inter,circle2->Circ(),pint3d,theVector);
440                   }
441               }
442             else
443               {
444                 if ( R1 >= R2 )
445                   {
446                     par_inter = ElCLib::Parameter(circle1->Circ(), circle2->Location());
447                     ElCLib::D1(par_inter,circle1->Circ(),pint3d,theVector);
448                   }
449                 else
450                   {
451                     par_inter = ElCLib::Parameter(circle2->Circ(), circle1->Location());
452                     ElCLib::D1(par_inter,circle2->Circ(),pint3d,theVector);
453                   }
454               }
455           }
456         else
457           {
458             par_inter = ElCLib::Parameter(circle1->Circ(), pint3d);
459             ElCLib::D1(par_inter,circle1->Circ(),pint3d,theVector);
460           }
461         theDir = gp_Dir(theVector);    
462       }
463       break;
464     case 23: // circle ellipse
465       {
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;
471         if (!found)
472           {
473             if ( R1 >= R2 )
474               {
475                 ComputeTangencyPoint(circle,ellipse,pint3d);
476                 par_inter = ElCLib::Parameter(circle->Circ(), pint3d);
477                 ElCLib::D1(par_inter,circle->Circ(),pint3d,theVector);
478               }
479             else
480               {
481                 ComputeTangencyPoint(ellipse,circle,pint3d);
482                 par_inter = ElCLib::Parameter(ellipse->Elips(), pint3d);
483                 ElCLib::D1(par_inter,ellipse->Elips(),pint3d,theVector);
484               }
485           }
486         else
487           {
488             par_inter = ElCLib::Parameter(circle->Circ(), pint3d);
489             ElCLib::D1(par_inter,circle->Circ(),pint3d,theVector);
490           }
491         theDir = gp_Dir(theVector);    
492       }
493       break;
494     case 32: // ellipse circle
495       {
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;
501         if (!found)
502           {
503             if ( R1 >= R2 )
504               {
505                 ComputeTangencyPoint(ellipse,circle,pint3d);
506                 par_inter = ElCLib::Parameter( ellipse->Elips(), pint3d);
507                 ElCLib::D1(par_inter,ellipse->Elips(),pint3d,theVector);
508               }
509             else
510               {
511                 ComputeTangencyPoint(circle,ellipse,pint3d);
512                 par_inter = ElCLib::Parameter( circle->Circ(), pint3d);
513                 ElCLib::D1(par_inter,circle->Circ(),pint3d,theVector);
514               }
515           }
516         else
517           {
518             par_inter = ElCLib::Parameter(circle->Circ(), pint3d);
519             ElCLib::D1(par_inter,circle->Circ(),pint3d,theVector);
520           }
521         theDir = gp_Dir(theVector);    
522       }
523       break;
524     case 33: // ellipse ellipse
525       {
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;
531         if (!found)
532           {
533             if ( R1 > R2 )
534               {
535                 ComputeTangencyPoint(ellipse1,ellipse2,pint3d);
536                 par_inter = ElCLib::Parameter( ellipse1->Elips(), pint3d);
537                 ElCLib::D1(par_inter,ellipse1->Elips(),pint3d,theVector);
538               }
539             else
540               {
541                 ComputeTangencyPoint(ellipse2,ellipse1,pint3d);
542                 par_inter = ElCLib::Parameter( ellipse2->Elips(), pint3d);
543                 ElCLib::D1(par_inter,ellipse2->Elips(),pint3d,theVector);
544               }
545           }
546         else
547           {
548             par_inter = ElCLib::Parameter(ellipse1->Elips(), pint3d);
549             ElCLib::D1(par_inter,ellipse1->Elips(),pint3d,theVector);
550           }
551         theDir = gp_Dir(theVector);    
552       }
553       break;
554     // jfa 19/10/2000 end
555     default:
556       return;
557     }
558
559   myAttach = pint3d;
560   myDir = theDir;
561   myPosition = pint3d;
562   myLength = Min(myLength,myArrowSize);
563
564   DsgPrs_TangentPresentation::Add(aPresentation,myDrawer,myAttach,myDir,myLength);
565   if ( (myExtShape != 0) &&  !extCurv.IsNull())
566     {
567       gp_Pnt pf, pl;
568       if ( myExtShape == 1 )
569         {
570           if (!isInfinite1)
571             {
572               pf = ptat11; 
573               pl = ptat12;
574             }
575           ComputeProjEdgePresentation(aPresentation,TopoDS::Edge(myFShape),copy1,pf,pl);
576         }
577       else
578         {
579           if (!isInfinite2)
580             {
581               pf = ptat21; 
582               pl = ptat22;
583             }
584           ComputeProjEdgePresentation(aPresentation,TopoDS::Edge(mySShape),copy2,pf,pl);
585         }
586     }
587 }