Path.Area: fix self intersect wire issue

Self intersected wire may cause a loop, and BRepBuilderAPI_MakeWire may
mistakenly consider the wire to be closed. And this makes
BrepTools_WireExplorer unhappy and cause it to skip edges.  We now use
ShapeAnalysis_FreeBounds to connect edges to wires.
This commit is contained in:
Zheng, Lei
2018-03-02 12:51:15 +08:00
committed by Yorik van Havre
parent 6720be82bf
commit ff21f64385
2 changed files with 30 additions and 14 deletions

View File

@@ -81,6 +81,7 @@
#include <ShapeFix_ShapeTolerance.hxx>
#include <ShapeExtend_WireData.hxx>
#include <ShapeFix_Wire.hxx>
#include <ShapeAnalysis_FreeBounds.hxx>
#include <Base/Exception.h>
#include <Base/Tools.h>
@@ -1610,7 +1611,7 @@ void Area::build() {
WireJoiner joiner;
gp_Trsf trsf(myTrsf.Inverted());
for(const auto &c : myArea->m_curves) {
TopoDS_Wire wire = toShape(c,&trsf);
auto wire = toShape(c,&trsf);
if(!wire.IsNull())
joiner.add(wire);
}
@@ -2045,8 +2046,9 @@ static inline bool IsLeft(const gp_Pnt &a, const gp_Pnt &b, const gp_Pnt &c) {
return ((b.X() - a.X())*(c.Y() - a.Y()) - (b.Y() - a.Y())*(c.X() - a.X())) > 0;
}
TopoDS_Wire Area::toShape(const CCurve &_c, const gp_Trsf *trsf, int reorient) {
BRepBuilderAPI_MakeWire mkWire;
TopoDS_Shape Area::toShape(const CCurve &_c, const gp_Trsf *trsf, int reorient) {
Handle(TopTools_HSequenceOfShape) hEdges = new TopTools_HSequenceOfShape();
Handle(TopTools_HSequenceOfShape) hWires = new TopTools_HSequenceOfShape();
CCurve cReversed;
if(reorient) {
@@ -2061,6 +2063,7 @@ TopoDS_Wire Area::toShape(const CCurve &_c, const gp_Trsf *trsf, int reorient) {
}
const CCurve &c = reorient?cReversed:_c;
TopoDS_Shape shape;
gp_Pnt pstart,pt;
bool first = true;
for(const CVertex &v : c.m_vertices){
@@ -2074,7 +2077,7 @@ TopoDS_Wire Area::toShape(const CCurve &_c, const gp_Trsf *trsf, int reorient) {
continue;
if(v.m_type == 0) {
auto edge = BRepBuilderAPI_MakeEdge(pt,pnext).Edge();
mkWire.Add(edge);
hEdges->Append(edge);
} else {
gp_Pnt center(v.m_c.x,v.m_c.y,0);
double r = center.Distance(pt);
@@ -2102,7 +2105,7 @@ TopoDS_Wire Area::toShape(const CCurve &_c, const gp_Trsf *trsf, int reorient) {
gp_Ax2 axis(center, gp_Dir(0,0,v.m_type));
try {
auto edge = BRepBuilderAPI_MakeEdge(gp_Circ(axis,r),pt,pnext).Edge();
mkWire.Add(edge);
hEdges->Append(edge);
break;
} catch(Standard_Failure &e) {
if(!fix_arc) {
@@ -2117,11 +2120,8 @@ TopoDS_Wire Area::toShape(const CCurve &_c, const gp_Trsf *trsf, int reorient) {
}
pt = pnext;
}
if(!mkWire.IsDone()) {
AREA_WARN("failed to make wire " << mkWire.Error());
return TopoDS_Wire();
}
#if 0
if(c.IsClosed() && !BRep_Tool::IsClosed(mkWire.Wire())){
// This should never happen after changing libarea's
// Point::tolerance to be the same as Precision::Confusion().
@@ -2134,10 +2134,26 @@ TopoDS_Wire Area::toShape(const CCurve &_c, const gp_Trsf *trsf, int reorient) {
AREA_XYZ(p2)<<endl<<AREA_XYZ(pt)<<endl<<AREA_XYZ(pstart));
mkWire.Add(BRepBuilderAPI_MakeEdge(pt,pstart).Edge());
}
#endif
ShapeAnalysis_FreeBounds::ConnectEdgesToWires(
hEdges, Precision::Confusion(), Standard_False, hWires);
if(!hWires->Length())
return shape;
if(hWires->Length()==1)
shape = hWires->Value(1);
else {
BRep_Builder builder;
TopoDS_Compound compound;
builder.MakeCompound(compound);
for(int i=1;i<=hWires->Length();++i)
builder.Add(compound,hWires->Value(i));
shape = compound;
}
if(trsf)
return TopoDS::Wire(mkWire.Wire().Moved(TopLoc_Location(*trsf)));
else
return mkWire.Wire();
shape.Move(TopLoc_Location(*trsf));
return shape;
}
TopoDS_Shape Area::toShape(const CArea &area, bool fill, const gp_Trsf *trsf, int reorient) {
@@ -2146,7 +2162,7 @@ TopoDS_Shape Area::toShape(const CArea &area, bool fill, const gp_Trsf *trsf, in
builder.MakeCompound(compound);
for(const CCurve &c : area.m_curves) {
const TopoDS_Wire &wire = toShape(c,trsf,reorient);
const auto &wire = toShape(c,trsf,reorient);
if(!wire.IsNull())
builder.Add(compound,wire);
}

View File

@@ -329,7 +329,7 @@ public:
* \arg \c trsf: optional transform matrix to transform the shape back into
* its original position.
* */
static TopoDS_Wire toShape(const CCurve &curve, const gp_Trsf *trsf=NULL, int reorient=0);
static TopoDS_Shape toShape(const CCurve &curve, const gp_Trsf *trsf=NULL, int reorient=0);
/** Check if two OCC shape is coplanar */
static bool isCoplanar(const TopoDS_Shape &s1, const TopoDS_Shape &s2);