Mantis issue 0021432: EDF GEOM: Faces with huge tolerance can be built in GEOM.

This commit is contained in:
jfa 2012-01-27 10:58:36 +00:00
parent d394961f4a
commit 0c1af31f54
4 changed files with 200 additions and 164 deletions

View File

@ -627,7 +627,8 @@ Please, select face, shell or solid and try again</translation>
</message> </message>
<message> <message>
<source>MAKE_FACE_TOLERANCE_TOO_BIG</source> <source>MAKE_FACE_TOLERANCE_TOO_BIG</source>
<translation>Tolerance of resulting face is too big</translation> <translation>Cannot build a planar face: required tolerance is
too big. Non-planar face is built.</translation>
</message> </message>
<message> <message>
<source>GEOM_FACE_OR_LCS</source> <source>GEOM_FACE_OR_LCS</source>

View File

@ -1202,67 +1202,67 @@ TCollection_AsciiString GEOMImpl_Block6Explorer::MakeFace (const TopoDS_Wire&
const Standard_Boolean isPlanarWanted, const Standard_Boolean isPlanarWanted,
TopoDS_Shape& theResult) TopoDS_Shape& theResult)
{ {
if (!isPlanarWanted)
return MakeAnyFace(theWire, theResult);
// Try to build a planar face.
// If required tolerance increase will be
// higher than PLANAR_FACE_MAX_TOLERANCE,
// we will try to build a non-planar face.
TCollection_AsciiString aWarning; TCollection_AsciiString aWarning;
// Workaround for Mantis issue 0020956 // Workaround for Mantis issue 0020956
if (isPlanarWanted) {
// Count the number of points in the wire.
// Collect the first three points.
gp_Pnt p1, p2, p3;
bool is3Pnts(false);
bool p1set(false), p2set(false), p3set(false);
BRepTools_WireExplorer wexpl(theWire);
for (; wexpl.More(); wexpl.Next()) {
if (!p1set) {
p1set = true;
p1 = BRep_Tool::Pnt(wexpl.CurrentVertex());
}
else if (!p2set) {
p2set = true;
p2 = BRep_Tool::Pnt(wexpl.CurrentVertex());
}
else if (!p3set) {
p3set = true;
is3Pnts = true;
p3 = BRep_Tool::Pnt(wexpl.CurrentVertex());
}
else {
is3Pnts = false;
break;
}
}
// Construct a plane for the case of three points in the wire. // Count the number of points in the wire.
gp_Pln plane; // Collect the first three points.
if (is3Pnts) { gp_Pnt p1, p2, p3;
gce_MakePln mkPln(p1, p2, p3); bool is3Pnts (false);
if (mkPln.IsDone()) { bool p1set(false), p2set(false), p3set(false);
plane = mkPln.Value(); BRepTools_WireExplorer wexpl (theWire);
} for (; wexpl.More(); wexpl.Next()) {
else { if (!p1set) {
is3Pnts = false; p1set = true;
} p1 = BRep_Tool::Pnt(wexpl.CurrentVertex());
} }
else if (!p2set) {
// Construct a face based on the plane (in case of three points in the wire) or p2set = true;
// allow MakeFace to build the plane itself (in case of the number of points is greater than 3). p2 = BRep_Tool::Pnt(wexpl.CurrentVertex());
if (is3Pnts) { }
BRepBuilderAPI_MakeFace MK (plane, theWire, isPlanarWanted); else if (!p3set) {
if (MK.IsDone()) { p3set = true;
theResult = MK.Shape(); is3Pnts = true;
return aWarning; p3 = BRep_Tool::Pnt(wexpl.CurrentVertex());
}
} }
else { else {
BRepBuilderAPI_MakeFace MK (theWire, isPlanarWanted); is3Pnts = false;
if (MK.IsDone()) { break;
theResult = MK.Shape(); }
return aWarning; }
}
// Construct a plane for the case of three points in the wire.
gp_Pln plane;
if (is3Pnts) {
gce_MakePln mkPln (p1, p2, p3);
if (mkPln.IsDone()) {
plane = mkPln.Value();
}
else {
is3Pnts = false;
}
}
// Construct a face based on the plane (in case of three points in the wire) or
// allow MakeFace to build the plane itself (in case of the number of points is greater than 3).
if (is3Pnts) {
BRepBuilderAPI_MakeFace MK (plane, theWire, isPlanarWanted);
if (MK.IsDone()) {
theResult = MK.Shape();
return aWarning;
} }
} }
else { else {
// try to build face on plane or on any surface under the edges of the wire
BRepBuilderAPI_MakeFace MK (theWire, isPlanarWanted); BRepBuilderAPI_MakeFace MK (theWire, isPlanarWanted);
if (MK.IsDone()) { if (MK.IsDone()) {
theResult = MK.Shape(); theResult = MK.Shape();
@ -1270,123 +1270,141 @@ TCollection_AsciiString GEOMImpl_Block6Explorer::MakeFace (const TopoDS_Wire&
} }
} }
if (!isPlanarWanted) { // try to update wire tolerances to build a planar face
// try to construct filling surface
BRepOffsetAPI_MakeFilling MF;
Standard_Integer nbEdges = 0; // Find a deviation
BRepTools_WireExplorer aWE (theWire); Standard_Real aToleranceReached, aTol;
for (; aWE.More(); aWE.Next(), nbEdges++) { BRepLib_FindSurface aFS;
MF.Add(TopoDS::Edge(aWE.Current()), GeomAbs_C0); aFS.Init(theWire, -1., isPlanarWanted);
} aToleranceReached = aFS.ToleranceReached();
aTol = aFS.Tolerance();
MF.Build(); if (!aFS.Found()) {
if (MF.IsDone()) { aFS.Init(theWire, aToleranceReached, isPlanarWanted);
// Result of filling if (!aFS.Found()) return aWarning;
TopoDS_Shape aFace = MF.Shape();
// 12.04.2006 for PAL12149 begin
Handle(Geom_Surface) aGS = BRep_Tool::Surface(TopoDS::Face(aFace));
BRepBuilderAPI_MakeFace MK1 (aGS, theWire);
if (MK1.IsDone()) {
TopoDS_Shape aFace1 = MK1.Shape();
BRepCheck_Analyzer ana (aFace1, false);
if (!ana.IsValid()) {
TopoDS_Shape aFace2;
ShHealOper_ShapeProcess aHealer;
aHealer.Perform(aFace1, aFace2);
if (aHealer.isDone())
theResult = aFace2;
}
}
// 12.04.2006 for PAL12149 end
if (theResult.IsNull()) { // try to deal with pure result of filling
// Update tolerance
Standard_Real aTol = MF.G0Error();
TColgp_Array1OfPnt aPnts (1,nbEdges); // points of the given wire
BRepTools_WireExplorer aWE1 (theWire);
Standard_Integer vi = 1;
for (; aWE1.More() && vi <= nbEdges; aWE1.Next(), vi++) {
aPnts(vi) = BRep_Tool::Pnt(TopoDS::Vertex(aWE1.CurrentVertex()));
}
// Find maximum deviation in vertices
TopExp_Explorer exp (aFace, TopAbs_VERTEX);
TopTools_MapOfShape mapShape;
for (; exp.More(); exp.Next()) {
if (mapShape.Add(exp.Current())) {
TopoDS_Vertex aV = TopoDS::Vertex(exp.Current());
Standard_Real aTolV = BRep_Tool::Tolerance(aV);
gp_Pnt aP = BRep_Tool::Pnt(aV);
Standard_Real min_dist = aP.Distance(aPnts(1));
for (vi = 2; vi <= nbEdges; vi++) {
min_dist = Min(min_dist, aP.Distance(aPnts(vi)));
}
aTol = Max(aTol, aTolV);
aTol = Max(aTol, min_dist);
}
}
if ((*((Handle(BRep_TFace)*)&aFace.TShape()))->Tolerance() < aTol) {
(*((Handle(BRep_TFace)*)&aFace.TShape()))->Tolerance(aTol);
}
theResult = aFace;
}
}
} else {
// try to update wire tolerances to build a planar face
#if 1 //(OCC_VERSION_MAJOR < 6) || (OCC_VERSION_MAJOR == 6 && OCC_VERSION_MINOR <= 1)
// Find a deviation
Standard_Real aToleranceReached, aTol;
BRepLib_FindSurface aFS;
aFS.Init(theWire, -1., isPlanarWanted);
aToleranceReached = aFS.ToleranceReached(); aToleranceReached = aFS.ToleranceReached();
aTol = aFS.Tolerance(); aTol = aFS.Tolerance();
}
aTol = Max(1.2 * aToleranceReached, aTol);
if (!aFS.Found()) { // Mantis issue 0021432: EDF GEOM: Faces with huge tolerance can be built in GEOM
aFS.Init(theWire, aToleranceReached, isPlanarWanted); if (aTol > PLANAR_FACE_MAX_TOLERANCE) {
if (!aFS.Found()) return aWarning; aWarning = MakeAnyFace(theWire, theResult);
aToleranceReached = aFS.ToleranceReached(); if (aWarning.IsEmpty() && !theResult.IsNull())
aTol = aFS.Tolerance(); aWarning = "MAKE_FACE_TOLERANCE_TOO_BIG";
} return aWarning;
aTol = Max(1.2 * aToleranceReached, aTol); }
// Copy the wire, bacause it can be updated with very-very big tolerance here // Copy the wire, bacause it can be updated with very-very big tolerance here
BRepBuilderAPI_Copy aMC (theWire); BRepBuilderAPI_Copy aMC (theWire);
if (!aMC.IsDone()) return aWarning; if (!aMC.IsDone()) return aWarning;
TopoDS_Wire aWire = TopoDS::Wire(aMC.Shape()); TopoDS_Wire aWire = TopoDS::Wire(aMC.Shape());
// Update tolerances to <aTol> // Update tolerances to <aTol>
BRep_Builder B; BRep_Builder B;
for (TopExp_Explorer expE (aWire, TopAbs_EDGE); expE.More(); expE.Next()) { for (TopExp_Explorer expE (aWire, TopAbs_EDGE); expE.More(); expE.Next()) {
TopoDS_Edge anE = TopoDS::Edge(expE.Current()); TopoDS_Edge anE = TopoDS::Edge(expE.Current());
B.UpdateEdge(anE, aTol); B.UpdateEdge(anE, aTol);
} }
for (TopExp_Explorer expV (aWire, TopAbs_VERTEX); expV.More(); expV.Next()) { for (TopExp_Explorer expV (aWire, TopAbs_VERTEX); expV.More(); expV.Next()) {
TopoDS_Vertex aV = TopoDS::Vertex(expV.Current()); TopoDS_Vertex aV = TopoDS::Vertex(expV.Current());
B.UpdateVertex(aV, aTol); B.UpdateVertex(aV, aTol);
} }
//BRepLib::UpdateTolerances(aWire); //BRepLib::UpdateTolerances(aWire);
// Build face // Build face
BRepBuilderAPI_MakeFace MK1 (aWire, isPlanarWanted); BRepBuilderAPI_MakeFace MK1 (aWire, isPlanarWanted);
if (MK1.IsDone()) { if (MK1.IsDone()) {
theResult = MK1.Shape(); theResult = MK1.Shape();
if (aTol > PLANAR_FACE_MAX_TOLERANCE) // Mantis issue 0021432: EDF GEOM: Faces with huge tolerance can be built in GEOM
aWarning = "MAKE_FACE_TOLERANCE_TOO_BIG"; //if (aTol > PLANAR_FACE_MAX_TOLERANCE)
return aWarning; // aWarning = "MAKE_FACE_TOLERANCE_TOO_BIG";
} }
#else // After migration on OCCT version, containing PKV's fix. See bug 8293 return aWarning;
BRepLib_MakeFace aBMF; }
aBMF.Init(theWire, isPlanarWanted, Standard_True);
if (aBMF.Error() == BRepLib_FaceDone) { //=======================================================================
theResult = aBMF.Shape(); //function : MakeAnyFace
return aWarning; //purpose :
} //=======================================================================
#endif TCollection_AsciiString GEOMImpl_Block6Explorer::MakeAnyFace (const TopoDS_Wire& theWire,
TopoDS_Shape& theResult)
{
TCollection_AsciiString aWarning;
// try to build a face on any surface under the edges of the wire
BRepBuilderAPI_MakeFace MK (theWire, Standard_False);
if (MK.IsDone()) {
theResult = MK.Shape();
return aWarning;
}
// try to construct filling surface
BRepOffsetAPI_MakeFilling MF;
Standard_Integer nbEdges = 0;
BRepTools_WireExplorer aWE (theWire);
for (; aWE.More(); aWE.Next(), nbEdges++) {
MF.Add(TopoDS::Edge(aWE.Current()), GeomAbs_C0);
}
MF.Build();
if (!MF.IsDone()) {
aWarning = "BRepOffsetAPI_MakeFilling failed";
return aWarning;
}
// Result of filling
TopoDS_Shape aFace = MF.Shape();
// 12.04.2006 for PAL12149 begin
Handle(Geom_Surface) aGS = BRep_Tool::Surface(TopoDS::Face(aFace));
BRepBuilderAPI_MakeFace MK1 (aGS, theWire);
if (MK1.IsDone()) {
TopoDS_Shape aFace1 = MK1.Shape();
BRepCheck_Analyzer ana (aFace1, false);
if (!ana.IsValid()) {
TopoDS_Shape aFace2;
ShHealOper_ShapeProcess aHealer;
aHealer.Perform(aFace1, aFace2);
if (aHealer.isDone())
theResult = aFace2;
}
}
// 12.04.2006 for PAL12149 end
if (theResult.IsNull()) { // try to deal with pure result of filling
// Update tolerance
Standard_Real aTol = MF.G0Error();
TColgp_Array1OfPnt aPnts (1,nbEdges); // points of the given wire
BRepTools_WireExplorer aWE1 (theWire);
Standard_Integer vi = 1;
for (; aWE1.More() && vi <= nbEdges; aWE1.Next(), vi++) {
aPnts(vi) = BRep_Tool::Pnt(TopoDS::Vertex(aWE1.CurrentVertex()));
}
// Find maximum deviation in vertices
TopExp_Explorer exp (aFace, TopAbs_VERTEX);
TopTools_MapOfShape mapShape;
for (; exp.More(); exp.Next()) {
if (mapShape.Add(exp.Current())) {
TopoDS_Vertex aV = TopoDS::Vertex(exp.Current());
Standard_Real aTolV = BRep_Tool::Tolerance(aV);
gp_Pnt aP = BRep_Tool::Pnt(aV);
Standard_Real min_dist = aP.Distance(aPnts(1));
for (vi = 2; vi <= nbEdges; vi++) {
min_dist = Min(min_dist, aP.Distance(aPnts(vi)));
}
aTol = Max(aTol, aTolV);
aTol = Max(aTol, min_dist);
}
}
if ((*((Handle(BRep_TFace)*)&aFace.TShape()))->Tolerance() < aTol) {
(*((Handle(BRep_TFace)*)&aFace.TShape()))->Tolerance(aTol);
}
theResult = aFace;
} }
return aWarning; return aWarning;

View File

@ -214,10 +214,26 @@ class GEOMImpl_Block6Explorer
const Standard_Boolean findAll = Standard_False); const Standard_Boolean findAll = Standard_False);
// returns number of found faces // returns number of found faces
/*!
* Build a face, bound by the given wire.
* \param theWire The initial wire to build the face on.
* \param isPlanarWanted. If true, try to build a planar face.
* \note If isPlanarWanted is true, but planar face cannot be built
* with acceptable tolerance, any face will be built.
* \return Error or warning description. Empty string in case of success.
*/
static TCollection_AsciiString MakeFace (const TopoDS_Wire& theWire, static TCollection_AsciiString MakeFace (const TopoDS_Wire& theWire,
const Standard_Boolean isPlanarWanted, const Standard_Boolean isPlanarWanted,
TopoDS_Shape& theResult); TopoDS_Shape& theResult);
/*!
* Build a face, bound by the given wire.
* \param theWire The initial wire to build the face on.
* \return Error or warning description. Empty string in case of success.
*/
static TCollection_AsciiString MakeAnyFace (const TopoDS_Wire& theWire,
TopoDS_Shape& theResult);
private: private:
// ---------- PRIVATE FIELDS ---------- // ---------- PRIVATE FIELDS ----------

View File

@ -1732,7 +1732,8 @@ class geompyDC(GEOM._objref_GEOM_Gen):
# Example: see GEOM_TestAll.py # Example: see GEOM_TestAll.py
anObj = self.ShapesOp.MakeFace(theWire, isPlanarWanted) anObj = self.ShapesOp.MakeFace(theWire, isPlanarWanted)
if anObj is not None and self.ShapesOp.GetErrorCode() == "MAKE_FACE_TOLERANCE_TOO_BIG": if anObj is not None and self.ShapesOp.GetErrorCode() == "MAKE_FACE_TOLERANCE_TOO_BIG":
print "WARNING: Tolerance of resulting face is too big." #print "WARNING: Tolerance of resulting face is too big."
print "WARNING: Cannot build a planar face: required tolerance is too big. Non-planar face is built."
else: else:
RaiseIfFailed("MakeFace", self.ShapesOp) RaiseIfFailed("MakeFace", self.ShapesOp)
return anObj return anObj