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