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