-// Copyright (C) 2007-2015 CEA/DEN, EDF R&D, OPEN CASCADE
+// Copyright (C) 2007-2021 CEA/DEN, EDF R&D, OPEN CASCADE
//
// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
#include <Geom_SurfaceOfRevolution.hxx>
#include <Geom_SurfaceOfLinearExtrusion.hxx>
#include <Geom_RectangularTrimmedSurface.hxx>
+#include <BRepAdaptor_Surface.hxx>
+#include <BRepAdaptor_HSurface.hxx>
+#include <LocalAnalysis_SurfaceContinuity.hxx>
+#include <GeomConvert_ApproxSurface.hxx>
+#include <Bnd_Box.hxx>
+#include <BRepBndLib.hxx>
#include <Geom_Curve.hxx>
#include <Geom_Line.hxx>
//=======================================================================
//function : AddOrdinaryEdges
-//purpose : auxilary
+//purpose : auxiliary
// adds edges from the shape to the sequence
// seams and equal edges are dropped
// Returns true if one of original edges dropped
{
//map of edges
TopTools_MapOfShape aNewEdges;
+ TopExp_Explorer exp(aShape,TopAbs_EDGE);
//add edges without seams
- for(TopExp_Explorer exp(aShape,TopAbs_EDGE); exp.More(); exp.Next()) {
+ for(; exp.More(); exp.Next()) {
TopoDS_Shape edge = exp.Current();
if(aNewEdges.Contains(edge))
aNewEdges.Remove(edge);
}
}
- //add edges to the sequemce
- for(TopTools_MapIteratorOfMapOfShape anIter(aNewEdges); anIter.More(); anIter.Next())
- edges.Append(anIter.Key());
+ //add edges to the sequence
+ for(exp.ReInit(); exp.More(); exp.Next()) {
+ const TopoDS_Shape &anEdge = exp.Current();
+
+ if (aNewEdges.Contains(anEdge)) {
+ edges.Append(anEdge);
+ }
+ }
return isDropped;
}
//=======================================================================
//function : ClearRts
-//purpose : auxilary
+//purpose : auxiliary
//=======================================================================
static Handle(Geom_Surface) ClearRts(const Handle(Geom_Surface)& aSurface)
{
//=======================================================================
//function : IsFacesOfSameSolids
-//purpose : auxilary
+//purpose : auxiliary
//=======================================================================
static Standard_Boolean IsFacesOfSameSolids
(const TopoDS_Face &theFace1,
return isSame;
}
+//=======================================================================
+//function : DefineMaxTolerance
+//purpose : calculates maximum possible tolerance on edges of shape
+//=======================================================================
+static Standard_Real DefineMaxTolerance(const TopoDS_Shape& theShape)
+{
+ Standard_Real aTol = Precision::Confusion();
+
+ Standard_Real MinSize = RealLast();
+ TopExp_Explorer Explo(theShape, TopAbs_EDGE);
+ for (; Explo.More(); Explo.Next())
+ {
+ const TopoDS_Edge& anEdge = TopoDS::Edge(Explo.Current());
+ Bnd_Box aBox;
+ BRepBndLib::Add(anEdge, aBox);
+ Standard_Real Xmin, Ymin, Zmin, Xmax, Ymax, Zmax;
+ aBox.Get(Xmin, Ymin, Zmin, Xmax, Ymax, Zmax);
+ Standard_Real MaxSize = Max(Xmax - Xmin, Max(Ymax - Ymin, Zmax - Zmin));
+ if (MaxSize < MinSize)
+ MinSize = MaxSize;
+ }
+
+ if (!Precision::IsInfinite(MinSize))
+ aTol = 0.1 * MinSize;
+
+ return aTol;
+}
+
+//=======================================================================
+//function : IsTangentFaces
+//purpose : decides: is edge on closed surface tangent or not
+//=======================================================================
+static Standard_Boolean IsTangentFaces(const TopoDS_Edge& theEdge,
+ const TopoDS_Face& theFace)
+{
+ Standard_Real TolC0 = Max(0.001, 1.5*BRep_Tool::Tolerance(theEdge));
+
+ Standard_Real aFirst;
+ Standard_Real aLast;
+
+// Obtaining of pcurves of edge on two faces.
+ const Handle(Geom2d_Curve) aC2d1 = BRep_Tool::CurveOnSurface
+ (theEdge, theFace, aFirst, aLast);
+ TopoDS_Edge ReversedEdge = theEdge;
+ ReversedEdge.Reverse();
+ const Handle(Geom2d_Curve) aC2d2 = BRep_Tool::CurveOnSurface
+ (ReversedEdge, theFace, aFirst, aLast);
+ if (aC2d1.IsNull() || aC2d2.IsNull())
+ return Standard_False;
+
+// Obtaining of two surfaces from adjacent faces.
+ Handle(Geom_Surface) aSurf = BRep_Tool::Surface(theFace);
+
+ if (aSurf.IsNull())
+ return Standard_False;
+
+// Computation of the number of samples on the edge.
+ BRepAdaptor_Surface aBAS(theFace);
+ Handle(BRepAdaptor_HSurface) aBAHS = new BRepAdaptor_HSurface(aBAS);
+ Handle(BRepTopAdaptor_TopolTool) aTool = new BRepTopAdaptor_TopolTool(aBAHS);
+ Standard_Integer aNbSamples = aTool->NbSamples();
+ const Standard_Integer aNbSamplesMax = 23;
+ aNbSamples = Min(aNbSamplesMax, aNbSamples);
+ const Standard_Real aTolAngle = M_PI/18;
+
+
+// Computation of the continuity.
+ Standard_Real aPar;
+ Standard_Real aDelta = (aLast - aFirst)/(aNbSamples - 1);
+ Standard_Integer i, nbNotDone = 0;
+
+ for (i = 1, aPar = aFirst; i <= aNbSamples; i++, aPar += aDelta) {
+ if (i == aNbSamples) aPar = aLast;
+
+ LocalAnalysis_SurfaceContinuity aCont(aC2d1, aC2d2, aPar,
+ aSurf, aSurf, GeomAbs_G1,
+ 0.001, TolC0, aTolAngle, 0.1, 0.1);
+ if (!aCont.IsDone())
+ {
+ nbNotDone++;
+ continue;
+ }
+
+ if (!aCont.IsG1())
+ return Standard_False;
+ }
+
+ if (nbNotDone == aNbSamples)
+ return Standard_False;
+
+ return Standard_True;
+}
+
+//=======================================================================
+//function : HasSeamEdge
+//purpose : Detects if a face contains a seam edge
+//=======================================================================
+static Standard_Boolean HasSeamEdge(const TopoDS_Face& theFace)
+{
+ TopExp_Explorer Explo(theFace, TopAbs_EDGE);
+ for (; Explo.More(); Explo.Next())
+ {
+ const TopoDS_Edge& anEdge = TopoDS::Edge(Explo.Current());
+ if (BRepTools::IsReallyClosed(anEdge, theFace))
+ return Standard_True;
+ }
+
+ return Standard_False;
+}
+
+
//=======================================================================
//function : IsEdgeValidToMerge
//purpose : Edge is valid if it is not seam or if it is a seam and the face
// has another seam edge.
//=======================================================================
-static Standard_Boolean IsEdgeValidToMerge(const TopoDS_Edge &theEdge,
- const TopoDS_Face &theFace)
+static Standard_Boolean IsEdgeValidToMerge(const TopoDS_Edge& theEdge,
+ const TopoDS_Face& theFace,
+ const Handle(Geom_Surface)& theSurface,
+ Standard_Boolean& theIsEdgeOnSeam,
+ Standard_Boolean& theToMakeUPeriodic,
+ Standard_Boolean& theToMakeVPeriodic)
{
Standard_Boolean isValid = Standard_True;
- if (BRep_Tool::IsClosed(theEdge, theFace)) {
+ theIsEdgeOnSeam |= BRep_Tool::IsClosed(theEdge, theFace);
+
+ if (BRepTools::IsReallyClosed(theEdge, theFace)) {
+ // Mantis issue 0023451, now code corresponds to the comment to this method
+ isValid = Standard_False;
+
// This is a seam edge. Check if there are another seam edges on the face.
TopExp_Explorer anExp(theFace, TopAbs_EDGE);
TopoDS_Edge anEdge = TopoDS::Edge(aShEdge);
if (BRep_Tool::IsClosed(anEdge, theFace)) {
- isValid = Standard_False;
+ // Mantis issue 0023451, now code corresponds to the comment to this method
+ //isValid = Standard_False;
+ isValid = Standard_True;
break;
}
}
}
+ else if (theIsEdgeOnSeam)
+ {
+ Standard_Real fpar, lpar;
+ Handle(Geom2d_Curve) aPCurve = BRep_Tool::CurveOnSurface(theEdge, theFace, fpar, lpar);
+ gp_Pnt2d P2d1 = aPCurve->Value(fpar);
+ gp_Pnt2d P2d2 = aPCurve->Value(lpar);
+ if (!theSurface->IsUPeriodic() &&
+ theSurface->IsUClosed() &&
+ Abs(P2d1.X() - P2d2.X()) < Abs(P2d1.Y() - P2d2.Y()))
+ {
+ if (IsTangentFaces(theEdge, theFace))
+ theToMakeUPeriodic = Standard_True;
+ else
+ isValid = Standard_False;
+ }
+ if (!theSurface->IsVPeriodic() &&
+ theSurface->IsVClosed() &&
+ Abs(P2d1.Y() - P2d2.Y()) < Abs(P2d1.X() - P2d2.X()))
+ {
+ if (IsTangentFaces(theEdge, theFace))
+ theToMakeVPeriodic = Standard_True;
+ else
+ isValid = Standard_False;
+ }
+ }
return isValid;
}
Handle(Geom_Surface) aBaseSurface = BRep_Tool::Surface(aFace,aBaseLocation);
aBaseSurface = ClearRts(aBaseSurface);
aBaseSurface = Handle(Geom_Surface)::DownCast(aBaseSurface->Copy());
+ Standard_Boolean ToMakeUPeriodic = Standard_False, ToMakeVPeriodic = Standard_False;
// find adjacent faces to union
Standard_Integer i;
for (i = 1; i <= edges.Length(); i++) {
TopoDS_Edge edge = TopoDS::Edge(edges(i));
- if (BRep_Tool::Degenerated(edge) || !IsEdgeValidToMerge(edge, aFace))
+ Standard_Boolean IsEdgeOnSeam = Standard_False;
+ if (BRep_Tool::Degenerated(edge) ||
+ !IsEdgeValidToMerge(edge, aFace, aBaseSurface,
+ IsEdgeOnSeam, ToMakeUPeriodic, ToMakeVPeriodic))
continue;
const TopTools_ListOfShape& aList = aMapEdgeFaces.FindFromKey(edge);
if (aProcessed.Contains(anCheckedFace))
continue;
- if (!IsEdgeValidToMerge(edge, anCheckedFace)) {
+ if (!IsEdgeValidToMerge(edge, anCheckedFace, aBaseSurface,
+ IsEdgeOnSeam, ToMakeUPeriodic, ToMakeVPeriodic)) {
// Skip seam edge.
continue;
}
continue;
}
+ //Prevent creating a face with parametric range more than period
+ if (IsEdgeOnSeam &&
+ (HasSeamEdge(aFace) || HasSeamEdge(anCheckedFace)))
+ continue;
+
// replacing pcurves
TopoDS_Face aMockUpFace;
BRep_Builder B;
NbModif++;
TopoDS_Face aResult;
BRep_Builder B;
+ if (ToMakeUPeriodic || ToMakeVPeriodic)
+ {
+ Handle(Geom_BSplineSurface) aBSplineSurface = Handle(Geom_BSplineSurface)::DownCast(aBaseSurface);
+ if (aBSplineSurface.IsNull())
+ {
+ Standard_Real aTol = 1.e-4;
+ GeomAbs_Shape aUCont = GeomAbs_C1, aVCont = GeomAbs_C1;
+ Standard_Integer degU = 14, degV = 14;
+ Standard_Integer nmax = 16;
+ Standard_Integer aPrec = 1;
+ GeomConvert_ApproxSurface Approximator(aBaseSurface,aTol,aUCont,aVCont,degU,degV,nmax,aPrec);
+ aBSplineSurface = Approximator.Surface();
+ }
+
+ if (ToMakeUPeriodic)
+ aBSplineSurface->SetUPeriodic();
+ if (ToMakeVPeriodic)
+ aBSplineSurface->SetVPeriodic();
+
+ aBaseSurface = aBSplineSurface;
+ }
B.MakeFace(aResult,aBaseSurface,aBaseLocation,0);
Standard_Integer nbWires = 0;
TopoDS_Wire aWireFixed = sfw->Wire();
aContext->Replace(aWire,aWireFixed);
// add resulting wire
- if(isEdge3d) {
+ if (isEdge3d) {
B.Add(aResult,aWireFixed);
}
else {
ShapeAnalysis_WireOrder sawo(Standard_False, 0);
ShapeAnalysis_Edge sae;
Standard_Integer aLastEdge = nbEdges;
- for(Standard_Integer j = 1; j <= nbEdges; j++) {
+ for (Standard_Integer j = 1; j <= nbEdges; j++) {
Standard_Real f,l;
//smh protection on NULL pcurve
Handle(Geom2d_Curve) c2d;
- if(!sae.PCurve(sbwd->Edge(j),aResult,c2d,f,l)) {
+ if (!sae.PCurve(sbwd->Edge(j),aResult,c2d,f,l)) {
aLastEdge--;
continue;
}
sawo.Add(c2d->Value(f).XY(),c2d->Value(l).XY());
}
- sawo.Perform();
-
- // constructind one degenerative edge
- gp_XY aStart, anEnd, tmp;
- Standard_Integer nbFirst = sawo.Ordered(1);
- TopoDS_Edge anOrigE = TopoDS::Edge(sbwd->Edge(nbFirst).Oriented(TopAbs_FORWARD));
- ShapeBuild_Edge sbe;
- TopoDS_Vertex aDummyV;
- TopoDS_Edge E = sbe.CopyReplaceVertices(anOrigE,aDummyV,aDummyV);
- sawo.XY(nbFirst,aStart,tmp);
- sawo.XY(sawo.Ordered(aLastEdge),tmp,anEnd);
-
- gp_XY aVec = anEnd-aStart;
- Handle(Geom2d_Line) aLine = new Geom2d_Line(aStart,gp_Dir2d(anEnd-aStart));
-
- B.UpdateEdge(E,aLine,aResult,0.);
- B.Range(E,aResult,0.,aVec.Modulus());
- Handle(Geom_Curve) C3d;
- B.UpdateEdge(E,C3d,0.);
- B.Degenerated(E,Standard_True);
- TopoDS_Wire aW;
- B.MakeWire(aW);
- B.Add(aW,E);
- B.Add(aResult,aW);
+ if (aLastEdge > 0) {
+ sawo.Perform();
+
+ // constructing one degenerative edge
+ gp_XY aStart, anEnd, tmp;
+ Standard_Integer nbFirst = sawo.Ordered(1);
+ TopoDS_Edge anOrigE = TopoDS::Edge(sbwd->Edge(nbFirst).Oriented(TopAbs_FORWARD));
+ ShapeBuild_Edge sbe;
+ TopoDS_Vertex aDummyV;
+ TopoDS_Edge E = sbe.CopyReplaceVertices(anOrigE,aDummyV,aDummyV);
+ sawo.XY(nbFirst,aStart,tmp);
+ sawo.XY(sawo.Ordered(aLastEdge),tmp,anEnd);
+
+ gp_XY aVec = anEnd-aStart;
+ Handle(Geom2d_Line) aLine = new Geom2d_Line(aStart,gp_Dir2d(anEnd-aStart));
+
+ B.UpdateEdge(E,aLine,aResult,0.);
+ B.Range(E,aResult,0.,aVec.Modulus());
+ Handle(Geom_Curve) C3d;
+ B.UpdateEdge(E,C3d,0.);
+ B.Degenerated(E,Standard_True);
+ TopoDS_Wire aW;
+ B.MakeWire(aW);
+ B.Add(aW,E);
+ B.Add(aResult,aW);
+ }
}
}
aContext->Replace(aContext->Apply(aFace),aResult);
ShapeFix_Face sff (aResult);
- //Intializing by tolerances
+ //Initializing by tolerances
sff.SetPrecision(myTolerance);
sff.SetMinTolerance(tol);
- sff.SetMaxTolerance(Max(1.,myTolerance*1000.));
+ Standard_Real MaxTol = DefineMaxTolerance(aResult);
+ sff.SetMaxTolerance(MaxTol);
//Setting modes
sff.FixOrientationMode() = 0;
//sff.FixWireMode() = 0;
sfw->SetMaxTolerance(Max(1.,myTolerance*1000.));
sfw->SetFace(aFace);
for (TopoDS_Iterator iter (aFace,Standard_False); iter.More(); iter.Next()) {
- TopoDS_Wire wire = TopoDS::Wire(iter.Value());
- sfw->Load(wire);
- sfw->FixReorder();
- sfw->FixShifted();
+ TopoDS_Shape aFaceCont = iter.Value();
+ if (!aFaceCont.IsNull() && aFaceCont.ShapeType() == TopAbs_WIRE) {
+ TopoDS_Wire wire = TopoDS::Wire(iter.Value());
+ sfw->Load(wire);
+ sfw->FixReorder();
+ sfw->FixShifted();
+ }
}
}
} // end processing each solid
return anIIInt.TangentFaces();
}
- catch (Standard_Failure) {
+ catch (Standard_Failure&) {
return false;
}
}