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