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