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