From f7f80396500b003eadab25a5a0e9908355ec73f2 Mon Sep 17 00:00:00 2001 From: jfa Date: Thu, 26 Apr 2012 10:07:48 +0000 Subject: [PATCH] Mantis issue 0021466: Healing no effect, Glue faces no effect. A fix by JGV. --- src/GEOMAlgo_NEW/BlockFix.cxx | 210 ++++++++++++++++---- src/GEOMAlgo_NEW/BlockFix.hxx | 57 ++---- src/GEOMAlgo_NEW/BlockFix_BlockFixAPI.cxx | 20 +- src/GEOMAlgo_NEW/BlockFix_UnionEdges.cxx | 222 ++++++++++++++++++++-- 4 files changed, 409 insertions(+), 100 deletions(-) diff --git a/src/GEOMAlgo_NEW/BlockFix.cxx b/src/GEOMAlgo_NEW/BlockFix.cxx index 22f230b9d..0e4f9bb21 100644 --- a/src/GEOMAlgo_NEW/BlockFix.cxx +++ b/src/GEOMAlgo_NEW/BlockFix.cxx @@ -18,52 +18,71 @@ // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com -// // File: BlockFix.cxx // Created: Tue Dec 7 11:59:05 2004 // Author: Pavel DURANDIN -// + #include -#include -#include -#include -#include -#include -#include + +#include +#include + +#include #include -#include + #include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include +#include +#include + +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include +#include + +#include + #include #include #include -#include -#include -#include #include #include -#include -#include + #include -#include -#include -#include -#include -#include -#include #include -#include -#include -#include - -#include -#include -#include -#include - -#include - //======================================================================= //function : FixResult @@ -130,7 +149,6 @@ static void FixResult(const TopoDS_Shape& result, } } - if(isDone) { TopoDS_Wire ResWire = sfw->Wire(); Context->Replace(ex_w.Current(), ResWire); @@ -143,24 +161,17 @@ static void FixResult(const TopoDS_Shape& result, if(sff->FixOrientation()) Context->Replace(aFixedFace,sff->Face()); } - } } } - - - - //======================================================================= -//function : ConvertToAnalytical +//function : RotateSphereSpace //purpose : //======================================================================= - TopoDS_Shape BlockFix::RotateSphereSpace (const TopoDS_Shape& S, const Standard_Real Tol) { - // Create a modification description Handle(BlockFix_SphereSpaceModifier) SR = new BlockFix_SphereSpaceModifier; SR->SetTolerance(Tol); @@ -183,12 +194,129 @@ TopoDS_Shape BlockFix::RotateSphereSpace (const TopoDS_Shape& S, return result; } +//======================================================================= +//function : RefillProblemFaces +//purpose : +//======================================================================= +TopoDS_Shape BlockFix::RefillProblemFaces (const TopoDS_Shape& aShape) +{ + Standard_Integer NbSamples = 10; + + TopTools_ListOfShape theFaces; + + TopExp_Explorer Explo(aShape, TopAbs_FACE); + for (; Explo.More(); Explo.Next()) + { + TopoDS_Face aFace = TopoDS::Face(Explo.Current()); + BRepAdaptor_Surface BAsurf(aFace); + GeomAbs_SurfaceType SurfType = BAsurf.GetType(); + if (SurfType >= GeomAbs_BezierSurface) + { + TopExp_Explorer fexp(aFace, TopAbs_EDGE); + for (; fexp.More(); fexp.Next()) + { + const TopoDS_Edge& anEdge = TopoDS::Edge(fexp.Current()); + if (BRep_Tool::Degenerated(anEdge)) + { + TopoDS_Vertex V1, V2; + TopExp::Vertices(anEdge, V1, V2); + if (V1.IsSame(V2)) + { + gp_Pnt aPnt = BRep_Tool::Pnt(V1); + Standard_Real TolV = BRep_Tool::Tolerance(V1); + Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace); + Handle(ShapeAnalysis_Surface) Analyser = new ShapeAnalysis_Surface(aSurf); + if (Analyser->IsDegenerated(aPnt, TolV)) + { + theFaces.Append(aFace); + break; + } + } + } + } + } + } + + //Now all problem faces are collected in the list "theFaces" + BRepTools_Substitution aSubst; + TopTools_ListIteratorOfListOfShape itl(theFaces); + for (; itl.More(); itl.Next()) + { + const TopoDS_Face& aFace = TopoDS::Face(itl.Value()); + BRepOffsetAPI_MakeFilling Filler; + for (Explo.Init(aFace, TopAbs_EDGE); Explo.More(); Explo.Next()) + { + const TopoDS_Edge& anEdge = TopoDS::Edge(Explo.Current()); + if (!BRep_Tool::Degenerated(anEdge)) + Filler.Add(anEdge, GeomAbs_C0); + } + Standard_Real Umin, Umax, Vmin, Vmax; + BRepTools::UVBounds(aFace, Umin, Umax, Vmin, Vmax); + //Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace); + Standard_Integer i, j; + for (i = 1; i < NbSamples; i++) + for (j = 1; j < NbSamples; j++) { + /* + gp_Pnt aPoint = aSurf->Value(Umin + i*(Umax-Umin)/NbSamples, + Vmin + j*(Vmax-Vmin)/NbSamples); + Filler.Add(aPoint); + */ + Filler.Add(Umin + i*(Umax-Umin)/NbSamples, + Vmin + j*(Vmax-Vmin)/NbSamples, + aFace, GeomAbs_G1); + } + + Filler.Build(); + if (Filler.IsDone()) + { + for (Explo.Init(aFace, TopAbs_EDGE); Explo.More(); Explo.Next()) + { + const TopoDS_Edge& anEdge = TopoDS::Edge(Explo.Current()); + TopTools_ListOfShape Ledge; + if (!BRep_Tool::Degenerated(anEdge)) + { + const TopTools_ListOfShape& Ledges = Filler.Generated(anEdge); + if (!Ledges.IsEmpty()) { + TopoDS_Shape NewEdge = Ledges.First(); + Ledge.Append(NewEdge.Oriented(TopAbs_FORWARD)); + } + } + aSubst.Substitute(anEdge, Ledge); + } + TopTools_ListOfShape Lface; + TopoDS_Face NewFace = TopoDS::Face(Filler.Shape()); + NewFace.Orientation(TopAbs_FORWARD); + BRepAdaptor_Surface NewBAsurf(NewFace); + gp_Pnt MidPnt; + gp_Vec D1U, D1V, Normal, NewNormal; + Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace); + aSurf->D1((Umin+Umax)*0.5, (Vmin+Vmax)*0.5, MidPnt, D1U, D1V); + Normal = D1U ^ D1V; + NewBAsurf.D1((NewBAsurf.FirstUParameter() + NewBAsurf.LastUParameter())*0.5, + (NewBAsurf.FirstVParameter() + NewBAsurf.LastVParameter())*0.5, + MidPnt, D1U, D1V); + NewNormal = D1U ^ D1V; + if (Normal * NewNormal < 0.) + NewFace.Reverse(); + Lface.Append(NewFace); + aSubst.Substitute(aFace, Lface); + } + } + aSubst.Build(aShape); + + TopoDS_Shape Result = aShape; + if (aSubst.IsCopied(aShape)) + Result = aSubst.Copy(aShape).First(); + + BRepTools::RemoveUnusedPCurves(Result); + + return Result; +} //======================================================================= //function : FixRanges //purpose : //======================================================================= - TopoDS_Shape BlockFix::FixRanges (const TopoDS_Shape& S, const Standard_Real Tol) { diff --git a/src/GEOMAlgo_NEW/BlockFix.hxx b/src/GEOMAlgo_NEW/BlockFix.hxx index a6a357276..34007be5c 100644 --- a/src/GEOMAlgo_NEW/BlockFix.hxx +++ b/src/GEOMAlgo_NEW/BlockFix.hxx @@ -26,6 +26,7 @@ #ifndef _Standard_Real_HeaderFile #include #endif + class TopoDS_Shape; class BlockFix_SphereSpaceModifier; class BlockFix_UnionFaces; @@ -34,7 +35,6 @@ class BlockFix_BlockFixAPI; class BlockFix_PeriodicSurfaceModifier; class BlockFix_CheckTool; - #ifndef _Standard_HeaderFile #include #endif @@ -46,46 +46,27 @@ class BlockFix { public: - void* operator new(size_t,void* anAddress) - { - return anAddress; - } - void* operator new(size_t size) - { - return Standard::Allocate(size); - } - void operator delete(void *anAddress) - { - if (anAddress) Standard::Free((Standard_Address&)anAddress); - } - // Methods PUBLIC - // -Standard_EXPORT static TopoDS_Shape RotateSphereSpace(const TopoDS_Shape& S,const Standard_Real Tol) ; -Standard_EXPORT static TopoDS_Shape FixRanges(const TopoDS_Shape& S,const Standard_Real Tol) ; - - - + void* operator new(size_t,void* anAddress) + { + return anAddress; + } + void* operator new(size_t size) + { + return Standard::Allocate(size); + } + void operator delete(void *anAddress) + { + if (anAddress) Standard::Free((Standard_Address&)anAddress); + } + Standard_EXPORT static TopoDS_Shape RotateSphereSpace(const TopoDS_Shape& S,const Standard_Real Tol); + Standard_EXPORT static TopoDS_Shape RefillProblemFaces(const TopoDS_Shape& S); + Standard_EXPORT static TopoDS_Shape FixRanges(const TopoDS_Shape& S,const Standard_Real Tol); protected: - // Methods PROTECTED - // - - - // Fields PROTECTED - // - - private: - // Methods PRIVATE - // - - - // Fields PRIVATE - // - friend class BlockFix_SphereSpaceModifier; friend class BlockFix_UnionFaces; friend class BlockFix_UnionEdges; @@ -95,12 +76,6 @@ friend class BlockFix_CheckTool; }; - - - - // other Inline functions and methods (like "C++: function call" methods) -// - #endif diff --git a/src/GEOMAlgo_NEW/BlockFix_BlockFixAPI.cxx b/src/GEOMAlgo_NEW/BlockFix_BlockFixAPI.cxx index 2aefa654e..3c82e4a84 100644 --- a/src/GEOMAlgo_NEW/BlockFix_BlockFixAPI.cxx +++ b/src/GEOMAlgo_NEW/BlockFix_BlockFixAPI.cxx @@ -18,16 +18,21 @@ // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com -// // File: BlockFix_BlockFixAPI.cxx // Created: Tue Dec 7 11:59:05 2004 // Author: Pavel DURANDIN -// + #include + #include #include #include + +#include + +#include + #include //======================================================================= @@ -52,12 +57,23 @@ void BlockFix_BlockFixAPI::Perform() TopoDS_Shape aShape = Shape(); myShape = BlockFix::RotateSphereSpace(aShape,myTolerance); + // try to approximate non-canonic surfaces + // with singularities on boundaries by filling + myShape = BlockFix::RefillProblemFaces(myShape); + // faces unification BlockFix_UnionFaces aFaceUnifier; aFaceUnifier.GetTolerance() = myTolerance; aFaceUnifier.GetOptimumNbFaces() = myOptimumNbFaces; TopoDS_Shape aResult = aFaceUnifier.Perform(myShape); + // avoid problem with degenerated edges appearance + // due to shape quality regress + ShapeUpgrade_RemoveLocations RemLoc; + RemLoc.Remove(aResult); + aResult = RemLoc.GetResult(); + + // edges unification BlockFix_UnionEdges anEdgeUnifier; myShape = anEdgeUnifier.Perform(aResult,myTolerance); diff --git a/src/GEOMAlgo_NEW/BlockFix_UnionEdges.cxx b/src/GEOMAlgo_NEW/BlockFix_UnionEdges.cxx index 7c5d2a186..95a1a713e 100644 --- a/src/GEOMAlgo_NEW/BlockFix_UnionEdges.cxx +++ b/src/GEOMAlgo_NEW/BlockFix_UnionEdges.cxx @@ -18,7 +18,6 @@ // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com -// // File: BlockFix_UnionEdges.cxx // Created: 07.12.04 15:27:30 @@ -26,30 +25,31 @@ #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include + #include #include #include -#include -#include + +#include +#include +#include +#include +#include +#include +#include +#include + #include #include + #include #include #include #include #include #include + #include #include #include @@ -58,17 +58,206 @@ #include #include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + #include "utilities.h" //======================================================================= //function : BlockFix_UnionEdges() //purpose : Constructor //======================================================================= - BlockFix_UnionEdges::BlockFix_UnionEdges ( ) { } +//======================================================================= +//function : GlueEdgesWithPCurves +//purpose : Glues the pcurves of the sequence of edges +// and glues their 3d curves +//======================================================================= +static TopoDS_Edge GlueEdgesWithPCurves(const TopTools_SequenceOfShape& aChain, + const TopoDS_Vertex& FirstVertex, + const TopoDS_Vertex& LastVertex) +{ + Standard_Integer i, j; + + TopoDS_Edge FirstEdge = TopoDS::Edge(aChain(1)); + //TColGeom2d_SequenceOfCurve PCurveSeq; + TColGeom_SequenceOfSurface SurfSeq; + //TopTools_SequenceOfShape LocSeq; + + BRep_ListIteratorOfListOfCurveRepresentation itr( (Handle(BRep_TEdge)::DownCast(FirstEdge.TShape()))->Curves() ); + for (; itr.More(); itr.Next()) + { + Handle(BRep_CurveRepresentation) CurveRep = itr.Value(); + if (CurveRep->IsCurveOnSurface()) + { + //PCurveSeq.Append(CurveRep->PCurve()); + SurfSeq.Append(CurveRep->Surface()); + /* + TopoDS_Shape aLocShape; + aLocShape.Location(CurveRep->Location()); + LocSeq.Append(aLocShape); + */ + } + } + + Standard_Real fpar, lpar; + BRep_Tool::Range(FirstEdge, fpar, lpar); + TopoDS_Edge PrevEdge = FirstEdge; + TopoDS_Vertex CV; + Standard_Real MaxTol = 0.; + + TopoDS_Edge ResEdge; + BRep_Builder BB; + + Standard_Integer nb_curve = aChain.Length(); //number of curves + TColGeom_Array1OfBSplineCurve tab_c3d(0,nb_curve-1); //array of the curves + TColStd_Array1OfReal tabtolvertex(0,nb_curve-1); //(0,nb_curve-2); //array of the tolerances + + TopoDS_Vertex PrevVertex = FirstVertex; + for (i = 1; i <= nb_curve; i++) + { + TopoDS_Edge anEdge = TopoDS::Edge(aChain(i)); + TopoDS_Vertex VF, VL; + TopExp::Vertices(anEdge, VF, VL); + Standard_Boolean ToReverse = (!VF.IsSame(PrevVertex)); + + Standard_Real Tol1 = BRep_Tool::Tolerance(VF); + Standard_Real Tol2 = BRep_Tool::Tolerance(VL); + if (Tol1 > MaxTol) + MaxTol = Tol1; + if (Tol2 > MaxTol) + MaxTol = Tol2; + + if (i > 1) + { + TopExp::CommonVertex(PrevEdge, anEdge, CV); + Standard_Real Tol = BRep_Tool::Tolerance(CV); + tabtolvertex(i-2) = Tol; + } + + Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, fpar, lpar); + Handle(Geom_TrimmedCurve) aTrCurve = new Geom_TrimmedCurve(aCurve, fpar, lpar); + tab_c3d(i-1) = GeomConvert::CurveToBSplineCurve(aTrCurve); + GeomConvert::C0BSplineToC1BSplineCurve(tab_c3d(i-1), Precision::Confusion()); + if (ToReverse) + tab_c3d(i-1)->Reverse(); + PrevVertex = (ToReverse)? VF : VL; + PrevEdge = anEdge; + } + Handle(TColGeom_HArray1OfBSplineCurve) concatcurve; //array of the concatenated curves + Handle(TColStd_HArray1OfInteger) ArrayOfIndices; //array of the remining Vertex + GeomConvert::ConcatC1(tab_c3d, + tabtolvertex, + ArrayOfIndices, + concatcurve, + Standard_False, + Precision::Confusion()); //C1 concatenation + + if (concatcurve->Length() > 1) + { + GeomConvert_CompCurveToBSplineCurve Concat(concatcurve->Value(concatcurve->Lower())); + + for (i = concatcurve->Lower()+1; i <= concatcurve->Upper(); i++) + Concat.Add( concatcurve->Value(i), MaxTol, Standard_True ); + + concatcurve->SetValue(concatcurve->Lower(), Concat.BSplineCurve()); + } + Handle(Geom_BSplineCurve) ResCurve = concatcurve->Value(concatcurve->Lower()); + + TColGeom2d_SequenceOfBoundedCurve ResPCurves; + TopLoc_Location aLoc; + for (j = 1; j <= SurfSeq.Length(); j++) + { + TColGeom2d_Array1OfBSplineCurve tab_c2d(0,nb_curve-1); //array of the pcurves + + PrevVertex = FirstVertex; + PrevEdge = FirstEdge; + //TopLoc_Location theLoc = LocSeq(j).Location(); + for (i = 1; i <= nb_curve; i++) + { + TopoDS_Edge anEdge = TopoDS::Edge(aChain(i)); + TopoDS_Vertex VF, VL; + TopExp::Vertices(anEdge, VF, VL); + Standard_Boolean ToReverse = (!VF.IsSame(PrevVertex)); + + /* + Handle(Geom2d_Curve) aPCurve = + BRep_Tool::CurveOnSurface(anEdge, SurfSeq(j), anEdge.Location()*theLoc, fpar, lpar); + */ + Handle(Geom2d_Curve) aPCurve = + BRep_Tool::CurveOnSurface(anEdge, SurfSeq(j), aLoc, fpar, lpar); + Handle(Geom2d_TrimmedCurve) aTrPCurve = new Geom2d_TrimmedCurve(aPCurve, fpar, lpar); + tab_c2d(i-1) = Geom2dConvert::CurveToBSplineCurve(aTrPCurve); + Geom2dConvert::C0BSplineToC1BSplineCurve(tab_c2d(i-1), Precision::Confusion()); + if (ToReverse) + tab_c2d(i-1)->Reverse(); + PrevVertex = (ToReverse)? VF : VL; + PrevEdge = anEdge; + } + Handle(TColGeom2d_HArray1OfBSplineCurve) concatc2d; //array of the concatenated curves + Handle(TColStd_HArray1OfInteger) ArrayOfInd2d; //array of the remining Vertex + Geom2dConvert::ConcatC1(tab_c2d, + tabtolvertex, + ArrayOfInd2d, + concatc2d, + Standard_False, + Precision::Confusion()); //C1 concatenation + + if (concatc2d->Length() > 1) + { + Geom2dConvert_CompCurveToBSplineCurve Concat2d(concatc2d->Value(concatc2d->Lower())); + + for (i = concatc2d->Lower()+1; i <= concatc2d->Upper(); i++) + Concat2d.Add( concatc2d->Value(i), MaxTol, Standard_True ); + + concatc2d->SetValue(concatc2d->Lower(), Concat2d.BSplineCurve()); + } + Handle(Geom2d_BSplineCurve) aResPCurve = concatc2d->Value(concatc2d->Lower()); + ResPCurves.Append(aResPCurve); + } + + ResEdge = BRepLib_MakeEdge(ResCurve, + FirstVertex, LastVertex, + ResCurve->FirstParameter(), ResCurve->LastParameter()); + BB.SameRange(ResEdge, Standard_False); + BB.SameParameter(ResEdge, Standard_False); + for (j = 1; j <= ResPCurves.Length(); j++) + { + BB.UpdateEdge(ResEdge, ResPCurves(j), SurfSeq(j), aLoc, MaxTol); + BB.Range(ResEdge, SurfSeq(j), aLoc, ResPCurves(j)->FirstParameter(), ResPCurves(j)->LastParameter()); + } + + BRepLib::SameParameter(ResEdge, MaxTol, Standard_True); + + return ResEdge; +} //======================================================================= //function : MergeEdges @@ -252,6 +441,8 @@ static Standard_Boolean MergeEdges(const TopTools_SequenceOfShape& SeqEdges, } if(NeedUnion) { MESSAGE ("can not make analitical union => make approximation"); + TopoDS_Edge E = GlueEdgesWithPCurves(aChain, VF, VL); + /* TopoDS_Wire W; B.MakeWire(W); for(j=1; j<=aChain.Length(); j++) { @@ -265,6 +456,7 @@ static Standard_Boolean MergeEdges(const TopTools_SequenceOfShape& SeqEdges, B.MakeEdge (E,bc,Precision::Confusion()); B.Add (E,VF); B.Add (E,VL); + */ aChain.SetValue(1,E); } else { @@ -277,12 +469,10 @@ static Standard_Boolean MergeEdges(const TopTools_SequenceOfShape& SeqEdges, return Standard_True; } - //======================================================================= //function : Perform //purpose : //======================================================================= - TopoDS_Shape BlockFix_UnionEdges::Perform(const TopoDS_Shape& Shape, const Standard_Real Tol) {