0024023: Revamp the OCCT Handle -- downcast (automatic)
[occt.git] / src / AIS / AIS_PerpendicularRelation.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_PerpendicularRelation.ixx>
20
21 #include <AIS.hxx>
22
23 #include <BRepBuilderAPI_MakeFace.hxx>
24 #include <BRepAdaptor_Surface.hxx>
25 #include <BRep_Tool.hxx>
26
27 #include <DsgPrs_PerpenPresentation.hxx>
28
29 #include <ElCLib.hxx>
30
31 #include <Geom2d_Line.hxx>
32 #include <GeomAPI.hxx>
33 #include <Geom_Line.hxx>
34 #include <Geom_Line.hxx>
35 #include <Geom_Plane.hxx>
36
37 #include <IntAna2d_AnaIntersection.hxx>
38 #include <IntAna2d_IntPoint.hxx>
39
40 #include <Precision.hxx>
41
42 #include <Select3D_SensitiveSegment.hxx>
43 #include <SelectMgr_EntityOwner.hxx>
44 #include <SelectMgr_Selection.hxx>
45
46 #include <TopoDS.hxx>
47 #include <TopoDS_Edge.hxx>
48 #include <TopoDS_Face.hxx>
49 #include <TopoDS_Vertex.hxx>
50
51 #include <gce_MakeDir.hxx>
52
53 #include <gp_Pln.hxx>
54 #include <gp_Pnt.hxx>
55 #include <gp_Pnt2d.hxx>
56 #include <gp_Trsf.hxx>
57 #include <gp_Vec.hxx>
58 #include <Geom_Ellipse.hxx>
59
60 //=======================================================================
61 //function : Constructor
62 //purpose  : TwoEdgesPerpendicular
63 //=======================================================================
64 AIS_PerpendicularRelation::AIS_PerpendicularRelation(const TopoDS_Shape& aFShape, 
65                                                      const TopoDS_Shape& aSShape, 
66                                                      const Handle(Geom_Plane)& aPlane)
67 :AIS_Relation()
68 {
69   myFShape = aFShape;
70   mySShape = aSShape;
71   myPlane = aPlane;
72 }
73
74 //=======================================================================
75 //function : Constructor
76 //purpose  : TwoFacesPerpendicular
77 //=======================================================================
78 AIS_PerpendicularRelation::AIS_PerpendicularRelation(const TopoDS_Shape& aFShape, 
79                                                      const TopoDS_Shape& aSShape)
80 :AIS_Relation()
81 {
82   myFShape = aFShape;
83   mySShape = aSShape;
84 }
85
86 //=======================================================================
87 //function : Compute
88 //purpose  : 
89 //=======================================================================
90 void AIS_PerpendicularRelation::Compute(const Handle(PrsMgr_PresentationManager3d)&, 
91                                         const Handle(Prs3d_Presentation)& aPresentation, 
92                                         const Standard_Integer)
93 {
94   aPresentation->Clear();
95
96   if (myFShape.ShapeType() == mySShape.ShapeType()) {
97     switch (myFShape.ShapeType()) {
98     case TopAbs_FACE :
99       {
100         // cas perpendiculaire entre deux faces
101         ComputeTwoFacesPerpendicular(aPresentation);
102       }
103       break;
104     case TopAbs_EDGE :
105       {
106         // cas perpendiculaire entre deux edges
107         ComputeTwoEdgesPerpendicular(aPresentation);
108       }
109       break;
110     default:
111       break;
112     }
113   }
114   // Cas pas traite - Edge/Face
115 }
116
117 //=======================================================================
118 //function : Compute
119 //purpose  : to avoid warning
120 //=======================================================================
121 void AIS_PerpendicularRelation::Compute(const Handle(Prs3d_Projector)& aProjector,
122                                         const Handle(Prs3d_Presentation)& aPresentation)
123 {
124 // Standard_NotImplemented::Raise("AIS_PerpendicularRelation::Compute(const Handle(Prs3d_Projector)&,const Handle(Prs3d_Presentation)&)");
125  PrsMgr_PresentableObject::Compute( aProjector , aPresentation ) ;
126 }
127
128 void AIS_PerpendicularRelation::Compute(const Handle(Prs3d_Projector)& aProjector, const Handle(Geom_Transformation)& aTransformation, const Handle(Prs3d_Presentation)& aPresentation)
129 {
130 // Standard_NotImplemented::Raise("AIS_PerpendicularRelation::Compute(const Handle(Prs3d_Projector)&, const Handle(Geom_Transformation)&, const Handle(Prs3d_Presentation)&)");
131  PrsMgr_PresentableObject::Compute( aProjector , aTransformation , aPresentation ) ;
132 }
133
134 //=======================================================================
135 //function : ComputeSelection
136 //purpose  : 
137 //=======================================================================
138 void AIS_PerpendicularRelation::ComputeSelection(const Handle(SelectMgr_Selection)& aSelection, 
139                                                  const Standard_Integer)
140 {
141   Handle(SelectMgr_EntityOwner) own = new SelectMgr_EntityOwner(this,7);
142   const gp_Pnt& pos = myPosition;
143   Handle(Select3D_SensitiveSegment) seg;
144   Standard_Boolean ok1(Standard_False),ok2(Standard_False);
145
146   if (!myFAttach.IsEqual(pos,Precision::Confusion())) {
147     seg = new Select3D_SensitiveSegment(own,
148                                         myFAttach,
149                                         pos);
150     aSelection->Add(seg);
151     ok1 = Standard_True;
152  }
153   if (!mySAttach.IsEqual(myPosition,Precision::Confusion())) {
154     seg = new Select3D_SensitiveSegment(own,
155                                         mySAttach,
156                                         pos);
157     aSelection->Add(seg);
158     ok2 = Standard_True;
159   }
160
161   if (ok1 && ok2) {
162     gp_Vec vec1(gce_MakeDir(pos,myFAttach));
163     gp_Vec vec2(gce_MakeDir(pos,mySAttach));
164     Standard_Real dist1(pos.Distance(myFAttach));
165     Standard_Real dist2(pos.Distance(mySAttach));
166     vec1 *= dist1;
167     vec1 *= .2;
168     vec2 *= dist2;
169     vec2 *= .2;
170     
171     gp_Pnt pAx11 = pos.Translated(vec1);
172     gp_Pnt pAx22 = pos.Translated(vec2);
173     gp_Pnt p_symb = pAx22.Translated(vec1);
174     seg = new Select3D_SensitiveSegment(own,pAx11,p_symb);
175     aSelection->Add(seg);
176     seg = new Select3D_SensitiveSegment(own,p_symb,pAx22);
177     aSelection->Add(seg);
178   }
179 }
180
181 //=======================================================================
182 //function : ComputeTwoFacesPerpendicular
183 //purpose  : 
184 //=======================================================================
185 void AIS_PerpendicularRelation::ComputeTwoFacesPerpendicular
186   (const Handle(Prs3d_Presentation)& /*aPresentation*/)
187 {
188 }
189
190 //=======================================================================
191 //function : ComputeTwoEdgesPerpendicular
192 //purpose  : 
193 //=======================================================================
194 void AIS_PerpendicularRelation::ComputeTwoEdgesPerpendicular(const Handle(Prs3d_Presentation)& aPresentation)
195 {
196   // 3d lines
197   Handle(Geom_Curve) geom1,geom2;
198   gp_Pnt pint3d,p1,p2,pAx1,pAx2,ptat11,ptat12,ptat21,ptat22;
199   Standard_Boolean isInfinite1,isInfinite2;
200   Handle(Geom_Curve) extCurv;
201   if ( !AIS::ComputeGeometry(TopoDS::Edge(myFShape),TopoDS::Edge(mySShape),
202                             myExtShape,
203                             geom1,geom2,
204                             ptat11,ptat12,ptat21,ptat22,
205                             extCurv,
206                             isInfinite1,isInfinite2,
207                             myPlane) ) return;
208
209   Standard_Boolean interOut1(Standard_False),interOut2(Standard_False);
210   
211   Handle(Geom_Line) geom_lin1;
212   Handle(Geom_Line) geom_lin2;
213   if ( geom1->IsInstance(STANDARD_TYPE(Geom_Ellipse)) )
214     {
215       Handle(Geom_Ellipse) geom_el (Handle(Geom_Ellipse)::DownCast (geom1));
216       // construct lines through focuses
217       gp_Ax1 elAx = geom_el->XAxis();
218       gp_Lin ll (elAx);
219       geom_lin1 = new Geom_Line(ll);
220       Standard_Real focex = geom_el->MajorRadius() - geom_el->Focal()/2.0;
221       gp_Vec transvec = gp_Vec(elAx.Direction())*focex;
222       ptat11 = geom_el->Focus1().Translated(transvec);
223       ptat12 = geom_el->Focus2().Translated(-transvec);
224       interOut1 = Standard_True;
225     }
226   else if ( geom1->IsInstance(STANDARD_TYPE(Geom_Line)) )
227     {
228       geom_lin1 = Handle(Geom_Line)::DownCast (geom1);
229     }
230   else return;
231
232   if (geom2->IsInstance(STANDARD_TYPE(Geom_Ellipse)))
233     {
234       Handle(Geom_Ellipse) geom_el (Handle(Geom_Ellipse)::DownCast (geom2));
235       // construct lines through focuses
236       gp_Ax1 elAx = geom_el->XAxis();
237       gp_Lin ll (elAx);
238       geom_lin2 = new Geom_Line(ll);
239       Standard_Real focex = geom_el->MajorRadius() - geom_el->Focal()/2.0;
240       gp_Vec transvec = gp_Vec(elAx.Direction())*focex;
241       ptat21 = geom_el->Focus1().Translated(transvec);
242       ptat22 = geom_el->Focus2().Translated(-transvec);
243       interOut2 = Standard_True;
244     }
245   else if ( geom2->IsInstance(STANDARD_TYPE(Geom_Line)) )
246     {
247       geom_lin2 = Handle(Geom_Line)::DownCast (geom2);
248     }
249   else return;
250
251   // current face
252   BRepBuilderAPI_MakeFace makeface (myPlane->Pln());
253   TopoDS_Face face (makeface.Face());  
254   BRepAdaptor_Surface adp (makeface.Face());
255   
256   // 2d lines => projection of 3d on current plane
257   Handle(Geom2d_Curve) aGeom2dCurve = GeomAPI::To2d(geom_lin1,myPlane->Pln());
258   Handle(Geom2d_Line) lin1_2d = Handle(Geom2d_Line)::DownCast (aGeom2dCurve) ;
259   aGeom2dCurve = GeomAPI::To2d(geom_lin2,myPlane->Pln());
260   Handle(Geom2d_Line) lin2_2d = Handle(Geom2d_Line)::DownCast (aGeom2dCurve) ;
261   IntAna2d_AnaIntersection inter(lin1_2d->Lin2d(),lin2_2d->Lin2d());
262   if (!inter.IsDone()) return;
263   if (!inter.NbPoints()) return;
264   
265   gp_Pnt2d pint(inter.Point(1).Value());
266   pint3d = adp.Value(pint.X(),pint.Y());
267
268   myPosition = pint3d;
269   // recherche points attache
270   Standard_Real par1,par2,curpar,pmin,pmax;//,dist,sign;
271   Standard_Real length(0.);
272   
273   if ( isInfinite1 && isInfinite2 )
274     {
275       Standard_Real curpar1 = ElCLib::Parameter(geom_lin1->Lin(),pint3d);
276       Standard_Real curpar2 = ElCLib::Parameter(geom_lin2->Lin(),pint3d);
277       par1 = par2 = 50.;    
278       p1 = p2 = pint3d;
279       myFAttach = ElCLib::Value(curpar1+par1,geom_lin1->Lin());
280       mySAttach = ElCLib::Value(curpar2+par2,geom_lin2->Lin());    
281     }
282   else
283     {
284       Standard_Boolean lengthComputed (Standard_False);
285       if ( !isInfinite1 )
286         {
287           curpar = ElCLib::Parameter(geom_lin1->Lin(),pint3d);
288           par1 = ElCLib::Parameter(geom_lin1->Lin(),ptat11);
289           par2 = ElCLib::Parameter(geom_lin1->Lin(),ptat12);
290           pmin = Min(par1,par2);
291           pmax = Max(par1,par2);
292       
293           if ( myPosition.SquareDistance(ptat11) > myPosition.SquareDistance(ptat12) )
294             p1 = ptat11;
295           else
296             p1 = ptat12;
297           if ( (curpar < pmin) || (curpar > pmax) )
298             {
299               interOut1 = Standard_True;
300             }
301           if ( !isInfinite2 ) length = 2.*Min(ptat11.Distance(ptat12),ptat21.Distance(ptat22))/5.;
302           else length = 2.*ptat11.Distance(ptat12)/5.;
303           lengthComputed = Standard_True;
304           gp_Vec vec1 (gce_MakeDir(myPosition,p1));
305           vec1.Multiply(length);
306           pAx1 = myPosition.Translated(vec1);
307           myFAttach = pAx1;
308         }
309       if ( !isInfinite2 )
310         {
311           curpar = ElCLib::Parameter(geom_lin2->Lin(),pint3d);
312           par1 = ElCLib::Parameter(geom_lin2->Lin(),ptat21);
313           par2 = ElCLib::Parameter(geom_lin2->Lin(),ptat22);
314           pmin = Min(par1,par2);
315           pmax = Max(par1,par2);
316           
317           if ( myPosition.SquareDistance(ptat21) > myPosition.SquareDistance(ptat22) ) p2 = ptat21;
318           else p2 = ptat22;
319           if ( (curpar < pmin) || (curpar > pmax) )
320             {
321               interOut2 = Standard_True;
322             }
323           gp_Vec vec2 (gce_MakeDir(myPosition,p2));
324           if ( !lengthComputed )
325             {
326               if ( !isInfinite1 ) length = 2.*Min(ptat11.Distance(ptat12),ptat21.Distance(ptat22))/5.;
327               else length = 2.*ptat21.Distance(ptat22)/5.;
328             }
329           vec2.Multiply(length);
330           pAx2 = myPosition.Translated(vec2);
331           mySAttach = pAx2;
332         }
333       if ( isInfinite1 )
334         {
335           p1 = myPosition;
336           gp_Vec vec1(geom_lin1->Lin().Direction());
337           vec1.Multiply(length);
338           myFAttach = myPosition.Translated(vec1);
339         }
340       if ( isInfinite2 )
341         {
342           p2 = myPosition;
343           gp_Vec vec2(geom_lin2->Lin().Direction());
344           vec2.Multiply(length);
345           mySAttach = myPosition.Translated(vec2);      
346         }
347     }
348   DsgPrs_PerpenPresentation::Add(aPresentation,myDrawer,
349                                  myFAttach,mySAttach,
350                                  p1,p2,
351                                  myPosition,
352                                  interOut1,interOut2);
353
354   if ( (myExtShape != 0) && !extCurv.IsNull()) {
355     gp_Pnt pf,pl;
356     if ( myExtShape == 1 ) {
357       if (!isInfinite1) {
358         pf = ptat11; 
359         pl = ptat12;
360       }
361       aPresentation->SetInfiniteState(isInfinite1);
362       ComputeProjEdgePresentation(aPresentation,TopoDS::Edge(myFShape),geom_lin1,pf,pl);
363     }
364     else {
365       if (!isInfinite2) {
366         pf = ptat21; 
367         pl = ptat22;
368       }
369       aPresentation->SetInfiniteState(isInfinite2);
370       ComputeProjEdgePresentation(aPresentation,TopoDS::Edge(mySShape),geom_lin2,pf,pl);
371     }
372   }
373 }