1 // Copyright (C) 2007-2021 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
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, or (at your option) any later version.
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.
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
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
24 // Created: Tue Dec 7 11:59:05 2004
25 // Author: Pavel DURANDIN
27 #include <BlockFix_SphereSpaceModifier.hxx>
29 #include <ShapeAnalysis.hxx>
31 #include <ShapeFix_Edge.hxx>
35 #include <TopLoc_Location.hxx>
38 #include <TopoDS_Edge.hxx>
39 #include <TopoDS_Face.hxx>
40 #include <TopoDS_Vertex.hxx>
41 #include <TopoDS_Iterator.hxx>
43 #include <BRep_Tool.hxx>
44 #include <BRep_Builder.hxx>
45 #include <BRepTools.hxx>
46 #include <BRepAdaptor_Curve2d.hxx>
47 #include <BRepTopAdaptor_FClass2d.hxx>
50 #include <Geom_Circle.hxx>
51 #include <Geom_TrimmedCurve.hxx>
52 #include <Geom_SphericalSurface.hxx>
53 #include <Geom_RectangularTrimmedSurface.hxx>
55 #include <Geom_Curve.hxx>
56 #include <Geom_Surface.hxx>
58 #include <Geom2d_Curve.hxx>
61 #include <gp_Sphere.hxx>
63 IMPLEMENT_STANDARD_RTTIEXT(BlockFix_SphereSpaceModifier, BRepTools_Modification)
65 //=======================================================================
66 //function : BlockFix_SphereSpaceModifier
68 //=======================================================================
69 BlockFix_SphereSpaceModifier::BlockFix_SphereSpaceModifier()
72 myMapOfSpheres.Clear();
75 //=======================================================================
76 //function : ~BlockFix_SphereSpaceModifier
78 //=======================================================================
79 BlockFix_SphereSpaceModifier::~BlockFix_SphereSpaceModifier() {}
81 //=======================================================================
82 //function : SetTolerance
84 //=======================================================================
85 void BlockFix_SphereSpaceModifier::SetTolerance(const Standard_Real Tol)
90 //=======================================================================
91 //function : NewSurface
93 //=======================================================================
94 static Standard_Boolean ModifySurface(const TopoDS_Face& theFace,
95 const Handle(Geom_Surface)& theSurface,
96 Handle(Geom_Surface)& theNewSurface)
98 TopoDS_Face aFace = theFace;
99 aFace.Orientation (TopAbs_FORWARD);
101 Handle(Geom_Surface) aNewSurface;
103 Handle(Geom_Surface) aSurf = theSurface;
104 if (aSurf->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface))) {
105 Handle(Geom_RectangularTrimmedSurface) RTS =
106 Handle(Geom_RectangularTrimmedSurface)::DownCast(aSurf);
107 aSurf = RTS->BasisSurface();
110 if (aSurf->IsKind(STANDARD_TYPE(Geom_SphericalSurface))) {
111 Standard_Real Umin, Umax, Vmin, Vmax;
112 ShapeAnalysis::GetFaceUVBounds (aFace, Umin, Umax, Vmin, Vmax);
113 Standard_Real PI2 = M_PI/2.;
114 Handle(Geom_SphericalSurface) aSphere = Handle(Geom_SphericalSurface)::DownCast(aSurf);
115 gp_Sphere sp = aSphere->Sphere();
116 Standard_Real Radius = sp.Radius();
117 gp_Ax3 ax3 = sp.Position();
118 gp_Pnt aCentre = sp.Location();
120 TopoDS_Wire aWire = BRepTools::OuterWire (aFace);
121 BRepTopAdaptor_FClass2d aClassifier (aFace, Precision::PConfusion());
122 TopTools_MapOfShape aEmap;
123 const Standard_Real anOffsetValue = 0.01*M_PI;
124 for (Standard_Integer ii = 1; ii <= 2; ii++)
126 TopoDS_Iterator itw (aWire);
127 for (; itw.More(); itw.Next())
129 const TopoDS_Edge& anEdge = TopoDS::Edge (itw.Value());
130 if (aEmap.Contains (anEdge) ||
131 anEdge.Orientation() == TopAbs_INTERNAL ||
132 anEdge.Orientation() == TopAbs_EXTERNAL ||
133 BRep_Tool::Degenerated (anEdge) ||
134 BRepTools::IsReallyClosed (anEdge, aFace))
137 BRepAdaptor_Curve2d aBAcurve2d (anEdge, aFace);
138 GeomAbs_CurveType aType = aBAcurve2d.GetType();
139 if (ii == 1 && aType == GeomAbs_Line) //first pass: consider only curvilinear edges
142 Standard_Real aMidPar = (aBAcurve2d.FirstParameter() + aBAcurve2d.LastParameter())/2;
145 aBAcurve2d.D1 (aMidPar, aMidP2d, aTangent);
146 if (anEdge.Orientation() == TopAbs_REVERSED)
149 aTangent.Normalize();
150 gp_Vec2d aNormal (aTangent.Y(), -aTangent.X());
151 aNormal *= anOffsetValue;
152 gp_Pnt2d anUpperPole = aMidP2d.Translated (aNormal);
153 if (anUpperPole.Y() < -PI2 || anUpperPole.Y() > PI2)
158 if (anUpperPole.X() < 0.)
159 anUpperPole.SetX (anUpperPole.X() + 2.*M_PI);
160 else if (anUpperPole.X() > 2.*M_PI)
161 anUpperPole.SetX (anUpperPole.X() - 2.*M_PI);
163 TopAbs_State aStatus = aClassifier.Perform (anUpperPole);
164 if (aStatus != TopAbs_OUT)
170 gp_Pnt anUpperPole3d = aSphere->Value (anUpperPole.X(), anUpperPole.Y());
171 gp_Vec aVec (aCentre, anUpperPole3d);
173 gp_Pnt aLowerPole3d = aCentre.Translated (aVec);
174 Standard_Real aU, aV;
175 ElSLib::Parameters (sp, aLowerPole3d, aU, aV);
176 gp_Pnt2d aLowerPole (aU, aV);
177 aStatus = aClassifier.Perform (aLowerPole);
178 if (aStatus != TopAbs_OUT)
185 gp_Vec anUp (aCentre, anUpperPole3d);
187 gp_Pnt aMidPnt = aSphere->Value (aMidP2d.X(), aMidP2d.Y());
188 gp_Vec aMidOnEdge (aCentre, aMidPnt);
189 aMidOnEdge.Normalize();
190 gp_Vec AxisOfCircle = anUp ^ aMidOnEdge;
191 gp_Vec XDirOfCircle = anUp ^ AxisOfCircle;
192 gp_Ax2 anAxis (aCentre, AxisOfCircle, XDirOfCircle);
193 Handle(Geom_Circle) aCircle = new Geom_Circle (anAxis, Radius);
194 Handle(Geom_TrimmedCurve) aMeridian = new Geom_TrimmedCurve (aCircle, -PI2, PI2);
197 Standard_Boolean IsInnerPointFound = Standard_False;
198 Standard_Integer NbSamples = 10;
199 Standard_Real aDelta = M_PI / NbSamples;
200 for (Standard_Integer jj = 1; jj < NbSamples; jj++)
202 Standard_Real aParam = -PI2 + jj*aDelta;
203 gp_Pnt aPnt = aMeridian->Value (aParam);
204 ElSLib::Parameters (sp, aPnt, aU, aV);
205 gp_Pnt2d aP2d (aU, aV);
206 aStatus = aClassifier.Perform (aP2d);
207 if (aStatus != TopAbs_OUT)
209 IsInnerPointFound = Standard_True;
213 if (IsInnerPointFound)
219 gp_Ax3 anAxisOfNewSphere (aCentre, anUp, XDirOfCircle);
220 aNewSurface = new Geom_SphericalSurface (anAxisOfNewSphere, Radius);
222 } //for (; itw.More(); itw.Next()) (iteration on outer wire)
223 if (!aNewSurface.IsNull())
225 } //for (Standard_Integer ii = 1; ii <= 2; ii++) (two passes)
228 if (aNewSurface.IsNull())
229 return Standard_False;
231 theNewSurface = aNewSurface;
232 return Standard_True;
235 Standard_Boolean BlockFix_SphereSpaceModifier::NewSurface(const TopoDS_Face& F,
236 Handle(Geom_Surface)& S,
237 TopLoc_Location& L,Standard_Real& Tol,
238 Standard_Boolean& RevWires,
239 Standard_Boolean& RevFace)
242 Handle(Geom_Surface) SIni = BRep_Tool::Surface(F, LS);
244 //check if pole of the sphere in the parametric space
245 if(ModifySurface(F, SIni, S)) {
247 RevWires = Standard_False;
248 RevFace = Standard_False;
251 Tol = BRep_Tool::Tolerance(F);
253 Standard_Integer anIndex = myMapOfSpheres.Add(S);
254 myMapOfFaces.Bind(F,anIndex);
255 return Standard_True;
258 return Standard_False;
261 //=======================================================================
262 //function : NewCurve
264 //=======================================================================
265 Standard_Boolean BlockFix_SphereSpaceModifier::NewCurve(const TopoDS_Edge& /*E*/,Handle(Geom_Curve)& /*C*/,
266 TopLoc_Location& /*L*/,Standard_Real& /*Tol*/)
268 return Standard_False;
271 //=======================================================================
272 //function : NewPoint
274 //=======================================================================
275 Standard_Boolean BlockFix_SphereSpaceModifier::NewPoint(const TopoDS_Vertex& /*V*/,
277 Standard_Real& /*Tol*/)
279 return Standard_False;
282 //=======================================================================
283 //function : NewCurve2d
285 //=======================================================================
286 Standard_Boolean BlockFix_SphereSpaceModifier::NewCurve2d(const TopoDS_Edge& E,const TopoDS_Face& F,
287 const TopoDS_Edge& /*NewE*/,const TopoDS_Face& /*NewF*/,
288 Handle(Geom2d_Curve)& C,Standard_Real& Tol)
290 //check if undelying surface of the face was modified
291 if(myMapOfFaces.IsBound(F)) {
292 Standard_Integer anIndex = myMapOfFaces.Find(F);
294 Handle(Geom_Surface) aNewSphere = Handle(Geom_Surface)::DownCast(myMapOfSpheres.FindKey(anIndex));
297 TopLoc_Location LC, LS;
298 Handle(Geom_Curve) C3d = BRep_Tool::Curve ( E, LC, f, l );
299 Handle(Geom_Surface) S = BRep_Tool::Surface(F, LS);
301 //taking into account the orientation of the seam
302 C = BRep_Tool::CurveOnSurface(E,F,f,l);
303 Tol = BRep_Tool::Tolerance(E);
308 B.Add(TempE, TopExp::FirstVertex(E));
309 B.Add(TempE, TopExp::LastVertex(E));
312 B.UpdateEdge(TempE, Handle(Geom_Curve)::DownCast(C3d->Transformed(LC.Transformation())), Precision::Confusion());
313 B.Range(TempE, f, l);
315 Handle(ShapeFix_Edge) sfe = new ShapeFix_Edge;
316 Handle(Geom_Surface) STemp = Handle(Geom_Surface)::DownCast(aNewSphere->Transformed(LS.Transformation()));
317 TopLoc_Location LTemp;
320 Standard_Boolean isClosed = BRep_Tool::IsClosed (E, F);
321 Standard_Real aWorkTol = 2*myTolerance+Tol;
322 sfe->FixAddPCurve(TempE, STemp, LTemp, isClosed, Max(Precision::Confusion(), aWorkTol));
323 sfe->FixSameParameter(TempE);
325 //keep the orientation of original edge
326 TempE.Orientation(E.Orientation());
327 C = BRep_Tool::CurveOnSurface(TempE, STemp, LTemp, f, l);
329 // shifting seam of sphere
330 if(isClosed && !C.IsNull()) {
332 Handle(Geom2d_Curve) c22 =
333 BRep_Tool::CurveOnSurface(TopoDS::Edge(TempE.Reversed()),STemp, LTemp,f2,l2);
334 Standard_Real dPreci = Precision::PConfusion()*Precision::PConfusion();
335 if((C->Value(f).SquareDistance(c22->Value(f2)) < dPreci)
336 ||(C->Value(l).SquareDistance(c22->Value(l2)) < dPreci)) {
337 gp_Vec2d shift(S->UPeriod(),0.);
341 //sphere was modified
342 return Standard_True;
345 return Standard_False;
348 //=======================================================================
349 //function : NewParameter
351 //=======================================================================
352 Standard_Boolean BlockFix_SphereSpaceModifier::NewParameter(const TopoDS_Vertex& /*V*/,const TopoDS_Edge& /*E*/,
353 Standard_Real& /*P*/,Standard_Real& /*Tol*/)
355 return Standard_False;
358 //=======================================================================
359 //function : Continuity
361 //=======================================================================
362 GeomAbs_Shape BlockFix_SphereSpaceModifier::Continuity(const TopoDS_Edge& E,const TopoDS_Face& F1,
363 const TopoDS_Face& F2,const TopoDS_Edge& /*NewE*/,
364 const TopoDS_Face& /*NewF1*/,const TopoDS_Face& /*NewF2*/)
366 return BRep_Tool::Continuity(E,F1,F2);