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