Salome HOME
3d50660bdaf6dc8662ad3252d2024559243efdee
[modules/geom.git] / src / BlockFix / BlockFix_SphereSpaceModifier.cxx
1 // Copyright (C) 2007-2013  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 // File:        BlockFix.cxx
24 // Created:     Tue Dec  7 11:59:05 2004
25 // Author:      Pavel DURANDIN
26
27 #include <BlockFix_SphereSpaceModifier.hxx>
28
29 #include <ShapeAnalysis.hxx>
30
31 #include <ShapeFix_Edge.hxx>
32
33 #include <TopExp.hxx>
34
35 #include <TopLoc_Location.hxx>
36
37 #include <TopoDS.hxx>
38 #include <TopoDS_Edge.hxx>
39 #include <TopoDS_Face.hxx>
40 #include <TopoDS_Vertex.hxx>
41
42 #include <BRep_Tool.hxx>
43 #include <BRep_Builder.hxx>
44
45 #include <BRepGProp.hxx>
46 #include <GProp_GProps.hxx>
47
48 #include <Geom_SphericalSurface.hxx>
49 #include <Geom_RectangularTrimmedSurface.hxx>
50
51 #include <Geom_Curve.hxx>
52 #include <Geom_Surface.hxx>
53
54 #include <Geom2d_Curve.hxx>
55
56 #include <gp_Pnt.hxx>
57 #include <gp_Sphere.hxx>
58
59 IMPLEMENT_STANDARD_HANDLE(BlockFix_SphereSpaceModifier, BRepTools_Modification);
60 IMPLEMENT_STANDARD_RTTIEXT(BlockFix_SphereSpaceModifier, BRepTools_Modification);
61
62 //=======================================================================
63 //function : BlockFix_SphereSpaceModifier
64 //purpose  :
65 //=======================================================================
66 BlockFix_SphereSpaceModifier::BlockFix_SphereSpaceModifier()
67 {
68   myMapOfFaces.Clear();
69   myMapOfSpheres.Clear();
70 }
71
72 //=======================================================================
73 //function : ~BlockFix_SphereSpaceModifier
74 //purpose  :
75 //=======================================================================
76 BlockFix_SphereSpaceModifier::~BlockFix_SphereSpaceModifier() {}
77
78 //=======================================================================
79 //function : SetTolerance
80 //purpose  :
81 //=======================================================================
82 void BlockFix_SphereSpaceModifier::SetTolerance(const Standard_Real Tol)
83 {
84   myTolerance = Tol;
85 }
86
87 //=======================================================================
88 //function : NewSurface
89 //purpose  :
90 //=======================================================================
91 static Standard_Boolean ModifySurface(const TopoDS_Face& aFace,
92                                       const Handle(Geom_Surface)& aSurface,
93                                       Handle(Geom_Surface)& aNewSurface)
94 {
95   Handle(Geom_Surface) S = aSurface;
96   if(S->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface))) {
97     Handle(Geom_RectangularTrimmedSurface) RTS =
98       Handle(Geom_RectangularTrimmedSurface)::DownCast(S);
99     S = RTS->BasisSurface();
100   }
101
102   if(S->IsKind(STANDARD_TYPE(Geom_SphericalSurface))) {
103     Standard_Real Umin, Umax, Vmin, Vmax;
104     ShapeAnalysis::GetFaceUVBounds(aFace,Umin, Umax, Vmin, Vmax);
105     Standard_Real PI2 = M_PI/2.;
106     if(Vmax > PI2 - Precision::PConfusion() || Vmin < -PI2+::Precision::PConfusion()) {
107       Handle(Geom_SphericalSurface) aSphere = Handle(Geom_SphericalSurface)::DownCast(S);
108       gp_Sphere sp = aSphere->Sphere();
109       //modified by jgv, 12.11.2012 for issue 21777//
110       Standard_Real Radius = sp.Radius();
111       Standard_Real HalfArea = 2.*M_PI*Radius*Radius;
112       GProp_GProps Properties;
113       BRepGProp::SurfaceProperties(aFace, Properties);
114       Standard_Real anArea = Properties.Mass();
115       Standard_Real AreaTol = Radius*Radius*1.e-6;
116       if (anArea > HalfArea - AreaTol) //no chance to avoid singularity
117         return Standard_False;
118       ///////////////////////////////////////////////
119       gp_Ax3 ax3 = sp.Position();
120       if(Abs(Vmax-Vmin) < PI2) {
121         gp_Ax3 axnew3(ax3.Axis().Location(), ax3.Direction()^ax3.XDirection(),ax3.XDirection());
122         sp.SetPosition(axnew3);
123         Handle(Geom_SphericalSurface) aNewSphere = new Geom_SphericalSurface(sp);
124         aNewSurface = aNewSphere;
125         return Standard_True;
126       }
127       else {
128         gp_Pnt PC = ax3.Location();
129         Standard_Real Vpar;
130         if(fabs(PI2-Vmax)>fabs(-PI2-Vmin))
131           Vpar = (PI2+Vmax)/2.;
132         else
133           Vpar = (-PI2+Vmin)/2.;
134         Standard_Real Upar = (Umin+Umax)/2.;;
135         gp_Pnt PN,PX;
136         S->D0(Upar,Vpar,PN);
137         S->D0(Upar+PI2,0.,PX);
138         gp_Dir newNorm(gp_Vec(PC,PN));
139         gp_Dir newDirX(gp_Vec(PC,PX));
140         gp_Ax3 axnew3(ax3.Axis().Location(), newNorm, newDirX);
141         sp.SetPosition(axnew3);
142         Handle(Geom_SphericalSurface) aNewSphere = new Geom_SphericalSurface(sp);
143         aNewSurface = aNewSphere;
144         return Standard_True;
145       }
146     }
147   }
148   return Standard_False;
149 }
150
151 Standard_Boolean BlockFix_SphereSpaceModifier::NewSurface(const TopoDS_Face& F,
152                                                         Handle(Geom_Surface)& S,
153                                                         TopLoc_Location& L,Standard_Real& Tol,
154                                                         Standard_Boolean& RevWires,
155                                                         Standard_Boolean& RevFace)
156 {
157   TopLoc_Location LS;
158   Handle(Geom_Surface) SIni = BRep_Tool::Surface(F, LS);
159
160   //check if pole of the sphere in the parametric space
161   if(ModifySurface(F, SIni, S)) {
162
163     RevWires = Standard_False;
164     RevFace = Standard_False;
165
166     L = LS;
167     Tol = BRep_Tool::Tolerance(F);
168
169     Standard_Integer anIndex = myMapOfSpheres.Add(S);
170     myMapOfFaces.Bind(F,anIndex);
171     return Standard_True;
172   }
173
174   return Standard_False;
175 }
176
177 //=======================================================================
178 //function : NewCurve
179 //purpose  :
180 //=======================================================================
181 Standard_Boolean BlockFix_SphereSpaceModifier::NewCurve(const TopoDS_Edge& /*E*/,Handle(Geom_Curve)& /*C*/,
182                                                         TopLoc_Location& /*L*/,Standard_Real& /*Tol*/)
183 {
184   return Standard_False;
185 }
186
187 //=======================================================================
188 //function : NewPoint
189 //purpose  :
190 //=======================================================================
191 Standard_Boolean BlockFix_SphereSpaceModifier::NewPoint(const TopoDS_Vertex& /*V*/,
192                                                       gp_Pnt& /*P*/,
193                                                       Standard_Real& /*Tol*/)
194 {
195   return Standard_False;
196 }
197
198 //=======================================================================
199 //function : NewCurve2d
200 //purpose  :
201 //=======================================================================
202 Standard_Boolean BlockFix_SphereSpaceModifier::NewCurve2d(const TopoDS_Edge& E,const TopoDS_Face& F,
203                                                         const TopoDS_Edge& /*NewE*/,const TopoDS_Face& /*NewF*/,
204                                                         Handle(Geom2d_Curve)& C,Standard_Real& Tol)
205 {
206   //check if undelying surface of the face was modified
207   if(myMapOfFaces.IsBound(F)) {
208     Standard_Integer anIndex = myMapOfFaces.Find(F);
209
210     Handle(Geom_Surface) aNewSphere = Handle(Geom_Surface)::DownCast(myMapOfSpheres.FindKey(anIndex));
211
212     Standard_Real f,l;
213     TopLoc_Location LC, LS;
214     Handle(Geom_Curve) C3d = BRep_Tool::Curve ( E, LC, f, l );
215     Handle(Geom_Surface) S = BRep_Tool::Surface(F, LS);
216
217     //taking into accound the orientation of the seam
218     C = BRep_Tool::CurveOnSurface(E,F,f,l);
219     Tol = BRep_Tool::Tolerance(E);
220
221     BRep_Builder B;
222     TopoDS_Edge TempE;
223     B.MakeEdge(TempE);
224     B.Add(TempE, TopExp::FirstVertex(E));
225     B.Add(TempE, TopExp::LastVertex(E));
226
227     if(!C3d.IsNull())
228       B.UpdateEdge(TempE, Handle(Geom_Curve)::DownCast(C3d->Transformed(LC.Transformation())), Precision::Confusion());
229     B.Range(TempE, f, l);
230
231     Handle(ShapeFix_Edge) sfe = new ShapeFix_Edge;
232     Handle(Geom_Surface) STemp = Handle(Geom_Surface)::DownCast(aNewSphere->Transformed(LS.Transformation()));
233     TopLoc_Location LTemp;
234     LTemp.Identity();
235
236     Standard_Boolean isClosed = BRep_Tool::IsClosed (E, F);
237     Standard_Real aWorkTol = 2*myTolerance+Tol;
238     sfe->FixAddPCurve(TempE, STemp, LTemp, isClosed, Max(Precision::Confusion(), aWorkTol));
239     sfe->FixSameParameter(TempE);
240
241     //keep the orientation of original edge
242     TempE.Orientation(E.Orientation());
243     C = BRep_Tool::CurveOnSurface(TempE, STemp, LTemp, f, l);
244
245     // shifting seam of sphere
246     if(isClosed  && !C.IsNull()) {
247       Standard_Real f2,l2;
248       Handle(Geom2d_Curve) c22 =
249         BRep_Tool::CurveOnSurface(TopoDS::Edge(TempE.Reversed()),STemp, LTemp,f2,l2);
250       Standard_Real dPreci = Precision::PConfusion()*Precision::PConfusion();
251       if((C->Value(f).SquareDistance(c22->Value(f2)) < dPreci)
252          ||(C->Value(l).SquareDistance(c22->Value(l2)) < dPreci)) {
253         gp_Vec2d shift(S->UPeriod(),0.);
254         C->Translate(shift);
255       }
256     }
257     //sphere was modified
258     return Standard_True;
259   }
260
261   return Standard_False;
262 }
263
264 //=======================================================================
265 //function : NewParameter
266 //purpose  :
267 //=======================================================================
268 Standard_Boolean BlockFix_SphereSpaceModifier::NewParameter(const TopoDS_Vertex& /*V*/,const TopoDS_Edge& /*E*/,
269                                                             Standard_Real& /*P*/,Standard_Real& /*Tol*/)
270 {
271   return Standard_False;
272 }
273
274 //=======================================================================
275 //function : Continuity
276 //purpose  :
277 //=======================================================================
278 GeomAbs_Shape BlockFix_SphereSpaceModifier::Continuity(const TopoDS_Edge& E,const TopoDS_Face& F1,
279                                                      const TopoDS_Face& F2,const TopoDS_Edge& /*NewE*/,
280                                                      const TopoDS_Face& /*NewF1*/,const TopoDS_Face& /*NewF2*/)
281 {
282   return BRep_Tool::Continuity(E,F1,F2);
283 }