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.hxx>
29 #include <BlockFix_SphereSpaceModifier.hxx>
30 #include <BlockFix_PeriodicSurfaceModifier.hxx>
33 #include <TopExp_Explorer.hxx>
35 #include <TopLoc_Location.hxx>
38 #include <TopoDS_Edge.hxx>
39 #include <TopoDS_Face.hxx>
40 #include <TopoDS_Wire.hxx>
41 #include <TopoDS_Shape.hxx>
42 #include <TopoDS_Solid.hxx>
43 #include <TopoDS_Vertex.hxx>
45 #include <TopTools_ListOfShape.hxx>
46 #include <TopTools_ListIteratorOfListOfShape.hxx>
47 #include <TopTools_MapOfShape.hxx>
48 #include <TopTools_DataMapOfShapeShape.hxx>
49 #include <TopTools_DataMapIteratorOfDataMapOfShapeShape.hxx>
51 #include <BRep_Tool.hxx>
52 #include <BRep_Builder.hxx>
54 #include <BRepAdaptor_Surface.hxx>
55 #include <BRepBndLib.hxx>
57 #include <BRepTools.hxx>
58 #include <BRepTools_Modifier.hxx>
59 #include <BRepTools_Substitution.hxx>
61 #include <BRepOffsetAPI_MakeFilling.hxx>
63 #include <ShapeFix.hxx>
64 #include <ShapeFix_Edge.hxx>
65 #include <ShapeFix_Face.hxx>
67 #include <ShapeAnalysis.hxx>
68 #include <ShapeAnalysis_Edge.hxx>
69 #include <ShapeAnalysis_Curve.hxx>
70 #include <ShapeAnalysis_Surface.hxx>
72 #include <ShapeCustom.hxx>
74 #include <ShapeBuild_Edge.hxx>
75 #include <ShapeBuild_ReShape.hxx>
77 #include <ShapeFix_Wire.hxx>
79 #include <Geom_Surface.hxx>
80 #include <Geom_CylindricalSurface.hxx>
81 #include <Geom_ConicalSurface.hxx>
82 #include <Geom_SphericalSurface.hxx>
83 #include <Geom_ToroidalSurface.hxx>
85 #include <Geom2d_Curve.hxx>
87 #include <TColgp_SequenceOfPnt2d.hxx>
89 #include <Basics_OCCTVersion.hxx>
91 static Standard_Real ComputeMaxTolOfFace(const TopoDS_Face& theFace)
93 Standard_Real MaxTol = BRep_Tool::Tolerance(theFace);
95 TopTools_IndexedMapOfShape aMap;
96 TopExp::MapShapes(theFace, TopAbs_EDGE, aMap);
97 for (Standard_Integer i = 1; i <= aMap.Extent(); i++)
99 const TopoDS_Edge& anEdge = TopoDS::Edge(aMap(i));
100 Standard_Real aTol = BRep_Tool::Tolerance(anEdge);
106 TopExp::MapShapes(theFace, TopAbs_VERTEX, aMap);
107 for (Standard_Integer i = 1; i <= aMap.Extent(); i++)
109 const TopoDS_Vertex& aVertex = TopoDS::Vertex(aMap(i));
110 Standard_Real aTol = BRep_Tool::Tolerance(aVertex);
118 //=======================================================================
119 //function : FixResult
120 //purpose : auxiliary
121 //=======================================================================
122 static void FixResult(const TopoDS_Shape& result,
123 Handle(ShapeBuild_ReShape)& Context,
124 const Standard_Real Tol)
126 for (TopExp_Explorer ex_f(result,TopAbs_FACE); ex_f.More(); ex_f.Next()) {
127 TopoDS_Shape aShape = Context->Apply(ex_f.Current().Oriented(TopAbs_FORWARD));
128 // face could not be dropped or split on this step
129 TopoDS_Face aFace = TopoDS::Face(aShape);
131 Handle(Geom_Surface) Surf = BRep_Tool::Surface(aFace,L);
133 if( Surf->IsKind(STANDARD_TYPE(Geom_SphericalSurface)) ||
134 Surf->IsKind(STANDARD_TYPE(Geom_CylindricalSurface)) ) {
136 Standard_Integer nbWires = 0;
137 for (TopExp_Explorer ex_w(aFace,TopAbs_WIRE); ex_w.More(); ex_w.Next()) {
139 Handle(ShapeFix_Wire) sfw = new ShapeFix_Wire(TopoDS::Wire(ex_w.Current()),
141 Precision::Confusion());
143 if(sfw->StatusReorder ( ShapeExtend_FAIL ))
146 sfw->SetPrecision(2.*Tol);
149 Standard_Boolean isDone = sfw->LastFixStatus ( ShapeExtend_DONE );
150 isDone |= sfw->FixDegenerated();
152 // remove degenerated edges from not degenerated points
153 ShapeAnalysis_Edge sae;
154 Handle(ShapeExtend_WireData) sewd = sfw->WireData();
156 for( i = 1; i<=sewd->NbEdges();i++) {
157 TopoDS_Edge E = sewd->Edge(i);
158 if(BRep_Tool::Degenerated(E)&&!sae.HasPCurve(E,aFace)) {
160 isDone = Standard_True;
165 //isDone |= sfw->FixLacking(); // commented by skl 22.03.2005 (PAL8395)
167 // remove neighbour seam edges
169 for( i = 1; i<sewd->NbEdges();i++) {
170 if(sewd->IsSeam(i) && sewd->IsSeam(i+1)) {
171 isDone = Standard_True;
177 if(sewd->IsSeam(1) && sewd->IsSeam(sewd->NbEdges())) {
179 sewd->Remove(sewd->NbEdges());
184 TopoDS_Wire ResWire = sfw->Wire();
185 Context->Replace(ex_w.Current(), ResWire);
188 // Implement fix orientation in case of several wires
190 TopoDS_Face aFixedFace = TopoDS::Face(Context->Apply(aFace));
191 Handle(ShapeFix_Face) sff = new ShapeFix_Face(aFixedFace);
192 if(sff->FixOrientation())
193 Context->Replace(aFixedFace,sff->Face());
199 //=======================================================================
200 //function : RotateSphereSpace
202 //=======================================================================
203 TopoDS_Shape BlockFix::RotateSphereSpace (const TopoDS_Shape& S,
204 const Standard_Real Tol)
206 // Create a modification description
207 Handle(BlockFix_SphereSpaceModifier) SR = new BlockFix_SphereSpaceModifier;
208 SR->SetTolerance(Tol);
210 TopTools_DataMapOfShapeShape context;
211 BRepTools_Modifier MD;
212 TopoDS_Shape result = ShapeCustom::ApplyModifier ( S, SR, context,MD );
214 Handle(ShapeBuild_ReShape) RS = new ShapeBuild_ReShape;
215 FixResult(result,RS,Tol);
216 result = RS->Apply(result);
219 for(TopExp_Explorer exp(result,TopAbs_EDGE); exp.More(); exp.Next()) {
220 TopoDS_Edge E = TopoDS::Edge(exp.Current());
221 sfe.FixVertexTolerance (E);
224 ShapeFix::SameParameter(result,Standard_False);
228 //=======================================================================
229 //function : RefillProblemFaces
231 //=======================================================================
232 TopoDS_Shape BlockFix::RefillProblemFaces (const TopoDS_Shape& aShape)
234 Standard_Integer NbSamples = 10;
236 #if OCC_VERSION_LARGE > 0x07040000
237 TopTools_IndexedDataMapOfShapeListOfShape VFmap;
238 TopExp::MapShapesAndUniqueAncestors(aShape, TopAbs_VERTEX, TopAbs_FACE, VFmap);
241 TopTools_ListOfShape theFaces;
243 TopExp_Explorer Explo(aShape, TopAbs_FACE);
244 for (; Explo.More(); Explo.Next())
246 TopoDS_Face aFace = TopoDS::Face(Explo.Current());
247 BRepAdaptor_Surface BAsurf(aFace);
248 GeomAbs_SurfaceType SurfType = BAsurf.GetType();
249 if (SurfType >= GeomAbs_BezierSurface)
251 TopExp_Explorer fexp(aFace, TopAbs_EDGE);
252 for (; fexp.More(); fexp.Next())
254 const TopoDS_Edge& anEdge = TopoDS::Edge(fexp.Current());
255 if (BRep_Tool::Degenerated(anEdge))
257 TopoDS_Vertex V1, V2;
258 TopExp::Vertices(anEdge, V1, V2);
261 gp_Pnt aPnt = BRep_Tool::Pnt(V1);
262 Standard_Real TolV = BRep_Tool::Tolerance(V1);
263 Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace);
264 Handle(ShapeAnalysis_Surface) Analyser = new ShapeAnalysis_Surface(aSurf);
265 if (Analyser->IsDegenerated(aPnt, TolV))
267 theFaces.Append(aFace);
276 //Now all problem faces are collected in the list "theFaces"
277 BRepTools_Substitution aSubst;
278 TopTools_ListIteratorOfListOfShape itl(theFaces);
279 for (; itl.More(); itl.Next())
281 TopoDS_Face aFace = TopoDS::Face(itl.Value());
282 aFace.Orientation(TopAbs_FORWARD);
284 //Compute proper tolerance
285 Standard_Real MaxTolOfFace = ComputeMaxTolOfFace(aFace);
286 #if OCC_VERSION_LARGE > 0x07040000
288 BRepBndLib::Add(aFace, aBndBox);
289 Standard_Real Xmin, Ymin, Zmin, Xmax, Ymax, Zmax;
290 aBndBox.Get(Xmin, Ymin, Zmin, Xmax, Ymax, Zmax);
291 Standard_Real LinSize = Min(Xmax - Xmin, Min(Ymax - Ymin, Zmax - Zmin));
292 Standard_Real LinTol = Max(0.001*LinSize, 1.5*MaxTolOfFace);
295 BRepAdaptor_Surface BAsurf(aFace, Standard_False);
296 BRepOffsetAPI_MakeFilling Filler(3, 10);
297 TopExp_Explorer Explo(aFace, TopAbs_EDGE);
298 for (; Explo.More(); Explo.Next())
300 const TopoDS_Edge& anEdge = TopoDS::Edge(Explo.Current());
301 if (BRep_Tool::Degenerated(anEdge) ||
302 BRepTools::IsReallyClosed(anEdge, aFace))
305 Filler.Add(anEdge, GeomAbs_C0);
306 //Filler.Add(anEdge, aFace, GeomAbs_G1);
308 Standard_Real Umin, Umax, Vmin, Vmax;
309 BRepTools::UVBounds(aFace, Umin, Umax, Vmin, Vmax);
310 Standard_Real DeltaU = (Umax - Umin)/NbSamples,
311 DeltaV = (Vmax - Vmin)/NbSamples;
312 for (Standard_Integer i = 1; i < NbSamples; i++)
313 for (Standard_Integer j = 1; j < NbSamples; j++) {
314 Filler.Add(Umin + i*DeltaU, Vmin + j*DeltaV, aFace, GeomAbs_G1);
320 TopoDS_Face aNewFace = TopoDS::Face(Filler.Shape());
321 aNewFace.Orientation(TopAbs_FORWARD);
322 Handle(Geom_Surface) aNewSurf = BRep_Tool::Surface(aNewFace);
323 GeomAdaptor_Surface GAnewsurf(aNewSurf);
324 Extrema_ExtPS Projector;
325 Projector.Initialize(GAnewsurf, GAnewsurf.FirstUParameter(), GAnewsurf.LastUParameter(),
326 GAnewsurf.FirstVParameter(), GAnewsurf.LastVParameter(),
327 Precision::Confusion(), Precision::Confusion());
328 Standard_Real MaxSqDist = 0.;
329 for (Standard_Integer i = 0; i < NbSamples; i++)
330 for (Standard_Integer j = 0; j < NbSamples; j++)
332 gp_Pnt aPoint = BAsurf.Value(Umin + DeltaU/2 + i*DeltaU,
333 Vmin + DeltaV/2 + j*DeltaV);
334 Projector.Perform(aPoint);
335 if (Projector.IsDone())
337 Standard_Real LocalMinSqDist = RealLast();
338 for (Standard_Integer ind = 1; ind <= Projector.NbExt(); ind++)
340 Standard_Real aSqDist = Projector.SquareDistance(ind);
341 if (aSqDist < LocalMinSqDist)
342 LocalMinSqDist = aSqDist;
344 if (!Precision::IsInfinite(LocalMinSqDist) &&
345 LocalMinSqDist > MaxSqDist)
346 MaxSqDist = LocalMinSqDist;
349 Standard_Real MaxDist = Sqrt(MaxSqDist);
350 #if OCC_VERSION_LARGE > 0x07040000
351 if (MaxDist < LinTol)
353 if (MaxDist < Max(1.e-4, 1.5*MaxTolOfFace))
356 TopTools_IndexedMapOfShape Emap;
357 #if OCC_VERSION_LARGE > 0x07040000
358 TopTools_MapOfShape Vmap;
360 TopExp::MapShapes(aFace, TopAbs_EDGE, Emap);
361 for (Standard_Integer i = 1; i <= Emap.Extent(); i++)
363 TopoDS_Edge anEdge = TopoDS::Edge(Emap(i));
364 anEdge.Orientation(TopAbs_FORWARD);
365 #if OCC_VERSION_LARGE > 0x07040000
366 TopoDS_Vertex V1, V2;
367 TopExp::Vertices(anEdge, V1, V2);
368 TopTools_ListOfShape ListV1, ListV2;
370 TopTools_ListOfShape Ledge;
371 if (!BRep_Tool::Degenerated(anEdge) &&
372 !BRepTools::IsReallyClosed(anEdge, aFace))
374 const TopTools_ListOfShape& Ledges = Filler.Generated(anEdge);
375 if (!Ledges.IsEmpty()) {
376 TopoDS_Edge NewEdge = TopoDS::Edge(Ledges.First());
377 Ledge.Append(NewEdge.Oriented(TopAbs_FORWARD));
380 #if OCC_VERSION_LARGE > 0x07040000
381 TopoDS_Vertex NewV1 = TopoDS::Vertex(Filler.Generated(V1).First());
382 ListV1.Append(NewV1.Oriented(TopAbs_FORWARD));
384 if (!V1.IsSame(V2)) {
385 TopoDS_Vertex NewV2 = TopoDS::Vertex(Filler.Generated(V2).First());
386 ListV2.Append(NewV2.Oriented(TopAbs_FORWARD));
390 aSubst.Substitute(anEdge, Ledge);
391 #if OCC_VERSION_LARGE > 0x07040000
392 if (!Vmap.Contains(V1) &&
393 (!ListV1.IsEmpty() || VFmap.FindFromKey(V1).Extent() == 1))
395 aSubst.Substitute(V1, ListV1);
398 if (!Vmap.Contains(V2) &&
399 (!ListV2.IsEmpty() || VFmap.FindFromKey(V2).Extent() == 1))
401 aSubst.Substitute(V2.Oriented(TopAbs_FORWARD), ListV2);
406 TopTools_ListOfShape Lface;
407 BRepAdaptor_Surface NewBAsurf(aNewFace);
409 gp_Vec D1U, D1V, Normal, NewNormal;
410 Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace);
411 aSurf->D1((Umin+Umax)*0.5, (Vmin+Vmax)*0.5, MidPnt, D1U, D1V);
413 NewBAsurf.D1((NewBAsurf.FirstUParameter() + NewBAsurf.LastUParameter())*0.5,
414 (NewBAsurf.FirstVParameter() + NewBAsurf.LastVParameter())*0.5,
416 NewNormal = D1U ^ D1V;
417 if (Normal * NewNormal < 0.)
419 Lface.Append(aNewFace);
420 aSubst.Substitute(aFace, Lface);
424 aSubst.Build(aShape);
426 TopoDS_Shape Result = aShape;
427 if (aSubst.IsCopied(aShape))
428 Result = aSubst.Copy(aShape).First();
430 BRepTools::RemoveUnusedPCurves(Result);
435 //=======================================================================
436 //function : FixRanges
438 //=======================================================================
439 TopoDS_Shape BlockFix::FixRanges (const TopoDS_Shape& S,
440 const Standard_Real Tol)
442 // Create a modification description
443 Handle(BlockFix_PeriodicSurfaceModifier) SR = new BlockFix_PeriodicSurfaceModifier;
444 SR->SetTolerance(Tol);
446 TopTools_DataMapOfShapeShape context;
447 BRepTools_Modifier MD;
448 TopoDS_Shape result = ShapeCustom::ApplyModifier ( S, SR, context,MD );
450 Handle(ShapeBuild_ReShape) RS = new ShapeBuild_ReShape;
451 FixResult(result,RS,Tol);
452 result = RS->Apply(result);
455 for(TopExp_Explorer exp(result,TopAbs_EDGE); exp.More(); exp.Next()) {
456 TopoDS_Edge E = TopoDS::Edge(exp.Current());
457 sfe.FixVertexTolerance (E);
460 ShapeFix::SameParameter(result,Standard_False);