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