0030480: Visualization - Clear of Select3D_SensitiveGroup does not update internal...
[occt.git] / src / LocOpe / LocOpe_Revol.cxx
1 // Created on: 1996-09-04
2 // Created by: Olga PILLOT
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
18 #include <BRepLib_MakeVertex.hxx>
19 #include <BRepSweep_Revol.hxx>
20 #include <BRepTools_Modifier.hxx>
21 #include <BRepTools_TrsfModification.hxx>
22 #include <Geom_Circle.hxx>
23 #include <Geom_Curve.hxx>
24 #include <gp_Ax1.hxx>
25 #include <gp_Circ.hxx>
26 #include <gp_Trsf.hxx>
27 #include <gp_Vec.hxx>
28 #include <LocOpe.hxx>
29 #include <LocOpe_BuildShape.hxx>
30 #include <LocOpe_Revol.hxx>
31 #include <Precision.hxx>
32 #include <Standard_NoSuchObject.hxx>
33 #include <StdFail_NotDone.hxx>
34 #include <TColgp_SequenceOfPnt.hxx>
35 #include <TopExp.hxx>
36 #include <TopExp_Explorer.hxx>
37 #include <TopoDS.hxx>
38 #include <TopoDS_Edge.hxx>
39 #include <TopoDS_Shape.hxx>
40 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
41
42 static Standard_Boolean FindCircle(const gp_Ax1&,
43                                    const gp_Pnt&,
44                                    gp_Circ&);
45
46
47 //=======================================================================
48 //function : LocOpe_Revol
49 //purpose  : 
50 //=======================================================================
51
52 LocOpe_Revol::LocOpe_Revol() :  myDone(Standard_False)
53
54 {}
55
56
57 //=======================================================================
58 //function : Perform
59 //purpose  : 
60 //=======================================================================
61
62 void LocOpe_Revol::Perform(const TopoDS_Shape& Base,
63                            const gp_Ax1& Axis,
64                            const Standard_Real Angle)
65 {
66   myMap.Clear();
67   myFirstShape.Nullify();
68   myLastShape.Nullify();
69   myBase.Nullify();
70   myRes.Nullify();
71   myBase = Base;
72   myAngle = Angle;
73   myAxis = Axis;
74   myAngTra = 0.;
75   myIsTrans = Standard_False;
76   IntPerf();
77 }
78
79 //=======================================================================
80 //function : Perform
81 //purpose  : 
82 //=======================================================================
83
84 void LocOpe_Revol::Perform(const TopoDS_Shape& Base,
85                            const gp_Ax1& Axis,
86                            const Standard_Real Angle,
87                            const Standard_Real angledec)
88 {
89   myMap.Clear();
90   myFirstShape.Nullify();
91   myLastShape.Nullify();
92   myBase.Nullify();
93   myRes.Nullify();
94   myBase = Base;
95   myAngle  = Angle;
96   myAxis = Axis;
97   myAngTra = angledec;
98   myIsTrans = Standard_True;
99   IntPerf();
100 }
101
102
103 //=======================================================================
104 //function : IntPerf
105 //purpose  : 
106 //=======================================================================
107
108 void LocOpe_Revol::IntPerf()
109 {
110   TopoDS_Shape theBase = myBase;
111   BRepTools_Modifier Modif;
112   if (myIsTrans) {
113     gp_Trsf T;
114     T.SetRotation(myAxis,myAngTra);
115     Handle(BRepTools_TrsfModification) modbase = 
116       new BRepTools_TrsfModification(T);
117     Modif.Init(theBase);
118     Modif.Perform(modbase);
119     theBase = Modif.ModifiedShape(theBase);
120   }
121   
122   BRepSweep_Revol theRevol(theBase,myAxis,myAngle);
123
124   myFirstShape = theRevol.FirstShape();
125   myLastShape = theRevol.LastShape();
126
127   TopExp_Explorer exp;
128   if (theBase.ShapeType() == TopAbs_FACE) {
129     for (exp.Init(theBase,TopAbs_EDGE);exp.More();exp.Next()) {
130       const TopoDS_Edge& edg = TopoDS::Edge(exp.Current());
131       if (!myMap.IsBound(edg)) {
132         TopTools_ListOfShape thelist;
133         myMap.Bind(edg, thelist);
134         TopoDS_Shape desc = theRevol.Shape(edg);
135         if (!desc.IsNull()) {
136           myMap(edg).Append(desc);
137         }
138       }
139     }
140     myRes = theRevol.Shape();
141   }
142
143   else {
144     // Cas base != FACE
145     TopTools_IndexedDataMapOfShapeListOfShape theEFMap;
146     TopExp::MapShapesAndAncestors(theBase,TopAbs_EDGE,TopAbs_FACE,theEFMap);
147     TopTools_ListOfShape lfaces;
148     Standard_Boolean toremove = Standard_False;
149     for (Standard_Integer i=1; i<=theEFMap.Extent(); i++) {
150       const TopoDS_Shape& edg = theEFMap.FindKey(i);
151       TopTools_ListOfShape thelist1;
152       myMap.Bind(edg, thelist1);
153       TopoDS_Shape desc = theRevol.Shape(edg);
154       if (!desc.IsNull()) {
155         if (theEFMap(i).Extent() >= 2) {
156           toremove = Standard_True;
157         }
158         else {
159           myMap(edg).Append(desc);
160           lfaces.Append(desc);
161         }
162       }
163     }    
164     if(toremove) {
165       // Rajouter les faces de FirstShape et LastShape
166       for (exp.Init(myFirstShape,TopAbs_FACE);exp.More();exp.Next()) {
167         lfaces.Append(exp.Current());
168       }
169       for (exp.Init(myLastShape,TopAbs_FACE);exp.More();exp.Next()) {
170         lfaces.Append(exp.Current());
171       }
172       
173       LocOpe_BuildShape BS(lfaces);
174       myRes = BS.Shape();
175     }
176     else {
177       for (exp.Init(theBase,TopAbs_EDGE);exp.More();exp.Next()) {
178         const TopoDS_Edge& edg = TopoDS::Edge(exp.Current());
179         if (!myMap.IsBound(edg)) {
180           TopTools_ListOfShape thelist2;
181           myMap.Bind(edg, thelist2);
182           TopoDS_Shape desc = theRevol.Shape(edg);
183           if (!desc.IsNull()) {
184             myMap(edg).Append(desc);
185           }
186         }
187       }
188       myRes = theRevol.Shape();
189     }
190   }
191
192   if (myIsTrans) {
193     // m-a-j des descendants
194     TopExp_Explorer anExp;
195     for (anExp.Init(myBase,TopAbs_EDGE); anExp.More(); anExp.Next()) {
196       const TopoDS_Edge& edg = TopoDS::Edge(anExp.Current());
197       const TopoDS_Edge& edgbis = TopoDS::Edge(Modif.ModifiedShape(edg));
198       if (!edgbis.IsSame(edg) && myMap.IsBound(edgbis)) {
199         myMap.Bind(edg,myMap(edgbis));
200         myMap.UnBind(edgbis);
201       }
202     }
203   }
204   myDone = Standard_True;
205 }
206
207 //=======================================================================
208 //function : Shape
209 //purpose  : 
210 //=======================================================================
211
212 const TopoDS_Shape& LocOpe_Revol::Shape () const
213 {
214   if (!myDone) {
215     throw StdFail_NotDone();
216   }
217   return myRes;
218 }
219
220
221 //=======================================================================
222 //function : FirstShape
223 //purpose  : 
224 //=======================================================================
225
226 const TopoDS_Shape& LocOpe_Revol::FirstShape () const
227 {
228   return myFirstShape;
229 }
230
231 //=======================================================================
232 //function : LastShape
233 //purpose  : 
234 //=======================================================================
235
236 const TopoDS_Shape& LocOpe_Revol::LastShape () const
237 {
238   return myLastShape;
239 }
240
241
242 //=======================================================================
243 //function : Shapes
244 //purpose  : 
245 //=======================================================================
246
247 const TopTools_ListOfShape& LocOpe_Revol::Shapes (const TopoDS_Shape& S) const
248 {
249   return myMap(S);
250 }
251
252
253 //=======================================================================
254 //function : Curves
255 //purpose  : 
256 //=======================================================================
257
258 void LocOpe_Revol::Curves(TColGeom_SequenceOfCurve& Scurves) const
259 {
260   Scurves.Clear();
261   TColgp_SequenceOfPnt spt;
262   LocOpe::SampleEdges(myFirstShape,spt);
263   for (Standard_Integer jj=1;jj<=spt.Length(); jj++) {
264     const gp_Pnt& pvt = spt(jj);
265     gp_Circ CAX;
266     if (FindCircle(myAxis,pvt,CAX)) {
267       gp_Ax2 A2 = CAX.Position();
268       Standard_Real r = CAX.Radius();
269       Handle(Geom_Circle) Ci = new Geom_Circle(A2, r);
270       Scurves.Append(Ci);
271     }
272   }
273 }
274
275 //=======================================================================
276 //function : BarycCurve
277 //purpose  : 
278 //=======================================================================
279
280 Handle(Geom_Curve) LocOpe_Revol::BarycCurve() const
281 {
282   gp_Pnt bar(0., 0., 0.);
283   TColgp_SequenceOfPnt spt;
284   LocOpe::SampleEdges(myFirstShape,spt);
285   for (Standard_Integer jj=1;jj<=spt.Length(); jj++) {
286     const gp_Pnt& pvt = spt(jj);
287     bar.ChangeCoord() += pvt.XYZ();
288   }
289   bar.ChangeCoord().Divide(spt.Length());
290   gp_Circ CAX;
291   Handle(Geom_Circle) theCi;
292   if (FindCircle(myAxis,bar,CAX)) {
293     gp_Ax2 A2 = CAX.Position();
294     Standard_Real r = CAX.Radius();
295     theCi = new Geom_Circle(A2, r);
296   }
297   return theCi;
298 }
299
300
301
302 //=======================================================================
303 //function : FincCircle
304 //purpose  : 
305 //=======================================================================
306
307 static Standard_Boolean FindCircle(const gp_Ax1& Ax,
308                                    const gp_Pnt& Pt,
309                                    gp_Circ& Ci)
310 {
311
312   const gp_Dir& Dax = Ax.Direction();
313   gp_Vec OP(Ax.Location(),Pt);
314
315   Standard_Real prm = OP.Dot(Dax);
316
317   gp_Pnt prj(Ax.Location().XYZ().Added(prm*Dax.XYZ()));
318   gp_Vec axx(prj,Pt);
319   Standard_Real Radius = axx.Magnitude();
320   if (Radius < Precision::Confusion()) {
321     return Standard_False;
322   }
323   Ci.SetRadius(Radius);
324   Ci.SetPosition(gp_Ax2(prj,Dax,axx));
325   return Standard_True;
326 }