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