0001137: Incomplete slices when using Part.slice on a torus

This commit is contained in:
wmayer 2013-08-25 17:31:04 +02:00
parent 1da39d014d
commit 348fcefb92
3 changed files with 99 additions and 42 deletions

View File

@ -24,6 +24,7 @@
#include "PreCompiled.h" #include "PreCompiled.h"
#ifndef _PreComp_ #ifndef _PreComp_
# include <BRepAdaptor_Surface.hxx> # include <BRepAdaptor_Surface.hxx>
# include <BRepAlgoAPI_Common.hxx>
# include <BRepAlgoAPI_Cut.hxx> # include <BRepAlgoAPI_Cut.hxx>
# include <BRepAlgoAPI_Section.hxx> # include <BRepAlgoAPI_Section.hxx>
# include <BRepBuilderAPI_MakeFace.hxx> # include <BRepBuilderAPI_MakeFace.hxx>
@ -33,9 +34,11 @@
# include <gp_Pln.hxx> # include <gp_Pln.hxx>
# include <Precision.hxx> # include <Precision.hxx>
# include <ShapeFix_Wire.hxx> # include <ShapeFix_Wire.hxx>
# include <ShapeAnalysis_FreeBounds.hxx>
# include <TopExp.hxx> # include <TopExp.hxx>
# include <TopExp_Explorer.hxx> # include <TopExp_Explorer.hxx>
# include <TopTools_IndexedMapOfShape.hxx> # include <TopTools_IndexedMapOfShape.hxx>
# include <TopTools_HSequenceOfShape.hxx>
# include <TopoDS.hxx> # include <TopoDS.hxx>
# include <TopoDS_Edge.hxx> # include <TopoDS_Edge.hxx>
# include <TopoDS_Wire.hxx> # include <TopoDS_Wire.hxx>
@ -51,54 +54,78 @@ CrossSection::CrossSection(double a, double b, double c, const TopoDS_Shape& s)
{ {
} }
std::list<TopoDS_Wire> CrossSection::section(double d) const std::list<TopoDS_Wire> CrossSection::slice(double d) const
{ {
std::list<TopoDS_Wire> wires; std::list<TopoDS_Wire> wires;
#if 0
// Fixes: 0001228: Cross section of Torus in Part Workbench fails or give wrong results // Fixes: 0001228: Cross section of Torus in Part Workbench fails or give wrong results
if (s.ShapeType() == TopAbs_SOLID) { // Fixes: 0001137: Incomplete slices when using Part.slice on a torus
gp_Pln slicePlane(a,b,c,-d); TopExp_Explorer xp;
BRepBuilderAPI_MakeFace mkFace(slicePlane); for (xp.Init(s, TopAbs_SOLID); xp.More(); xp.Next()) {
TopoDS_Face face = mkFace.Face(); sliceSolid(d, xp.Current(), wires);
BRepPrimAPI_MakeHalfSpace mkSolid(face, gp_Pnt(0,0,d-1)); }
TopoDS_Solid solid = mkSolid.Solid(); for (xp.Init(s, TopAbs_SHELL, TopAbs_SOLID); xp.More(); xp.Next()) {
BRepAlgoAPI_Cut mkCut(s,solid); sliceNonSolid(d, xp.Current(), wires);
}
for (xp.Init(s, TopAbs_FACE, TopAbs_SHELL); xp.More(); xp.Next()) {
sliceNonSolid(d, xp.Current(), wires);
}
if (mkCut.IsDone()) { return wires;
TopTools_IndexedMapOfShape mapOfFaces; }
TopExp::MapShapes(mkCut.Shape(), TopAbs_FACE, mapOfFaces);
for (int i=1; i<=mapOfFaces.Extent(); i++) { void CrossSection::sliceNonSolid(double d, const TopoDS_Shape& shape, std::list<TopoDS_Wire>& wires) const
const TopoDS_Face& face = TopoDS::Face(mapOfFaces.FindKey(i)); {
BRepAdaptor_Surface adapt(face); BRepAlgoAPI_Section cs(shape, gp_Pln(a,b,c,-d));
if (adapt.GetType() == GeomAbs_Plane) { if (cs.IsDone()) {
gp_Pln plane = adapt.Plane(); std::list<TopoDS_Edge> edges;
if (plane.Axis().IsParallel(slicePlane.Axis(), Precision::Confusion()) && TopExp_Explorer xp;
plane.Distance(slicePlane.Location()) < Precision::Confusion()) { for (xp.Init(cs.Shape(), TopAbs_EDGE); xp.More(); xp.Next())
TopTools_IndexedMapOfShape mapOfWires; edges.push_back(TopoDS::Edge(xp.Current()));
TopExp::MapShapes(face, TopAbs_WIRE, mapOfWires); connectEdges(edges, wires);
for (int j=1; j<=mapOfWires.Extent(); j++) { }
const TopoDS_Wire& wire = TopoDS::Wire(mapOfWires.FindKey(j)); }
wires.push_back(wire);
} void CrossSection::sliceSolid(double d, const TopoDS_Shape& shape, std::list<TopoDS_Wire>& wires) const
} {
#if 0
gp_Pln slicePlane(a,b,c,-d);
BRepBuilderAPI_MakeFace mkFace(slicePlane);
TopoDS_Face face = mkFace.Face();
BRepAlgoAPI_Common mkInt(shape, face);
if (mkInt.IsDone()) {
// sort and repair the wires
TopTools_IndexedMapOfShape mapOfWires;
TopExp::MapShapes(mkInt.Shape(), TopAbs_WIRE, mapOfWires);
connectWires(mapOfWires, wires);
}
#else
gp_Pln slicePlane(a,b,c,-d);
BRepBuilderAPI_MakeFace mkFace(slicePlane);
TopoDS_Face face = mkFace.Face();
BRepPrimAPI_MakeHalfSpace mkSolid(face, gp_Pnt(0,0,d-1));
TopoDS_Solid solid = mkSolid.Solid();
BRepAlgoAPI_Cut mkCut(shape, solid);
if (mkCut.IsDone()) {
TopTools_IndexedMapOfShape mapOfFaces;
TopExp::MapShapes(mkCut.Shape(), TopAbs_FACE, mapOfFaces);
for (int i=1; i<=mapOfFaces.Extent(); i++) {
const TopoDS_Face& face = TopoDS::Face(mapOfFaces.FindKey(i));
BRepAdaptor_Surface adapt(face);
if (adapt.GetType() == GeomAbs_Plane) {
gp_Pln plane = adapt.Plane();
if (plane.Axis().IsParallel(slicePlane.Axis(), Precision::Confusion()) &&
plane.Distance(slicePlane.Location()) < Precision::Confusion()) {
// sort and repair the wires
TopTools_IndexedMapOfShape mapOfWires;
TopExp::MapShapes(face, TopAbs_WIRE, mapOfWires);
connectWires(mapOfWires, wires);
} }
} }
} }
} }
else
#else
{
BRepAlgoAPI_Section cs(s, gp_Pln(a,b,c,-d));
if (cs.IsDone()) {
std::list<TopoDS_Edge> edges;
TopExp_Explorer xp;
for (xp.Init(cs.Shape(), TopAbs_EDGE); xp.More(); xp.Next())
edges.push_back(TopoDS::Edge(xp.Current()));
connectEdges(edges, wires);
}
}
#endif #endif
return wires;
} }
void CrossSection::connectEdges (const std::list<TopoDS_Edge>& edges, std::list<TopoDS_Wire>& wires) const void CrossSection::connectEdges (const std::list<TopoDS_Edge>& edges, std::list<TopoDS_Wire>& wires) const
@ -140,3 +167,27 @@ void CrossSection::connectEdges (const std::list<TopoDS_Edge>& edges, std::list<
wires.push_back(aFix.Wire()); wires.push_back(aFix.Wire());
} }
} }
void CrossSection::connectWires (const TopTools_IndexedMapOfShape& wireMap, std::list<TopoDS_Wire>& wires) const
{
Handle(TopTools_HSequenceOfShape) hWires = new TopTools_HSequenceOfShape();
for (int i=1; i<=wireMap.Extent(); i++) {
const TopoDS_Shape& wire = wireMap.FindKey(i);
hWires->Append(wire);
}
Handle(TopTools_HSequenceOfShape) hSorted = new TopTools_HSequenceOfShape();
ShapeAnalysis_FreeBounds::ConnectWiresToWires(hWires, Precision::Confusion(), false, hSorted);
for (int i=1; i<=hSorted->Length(); i++) {
const TopoDS_Wire& new_wire = TopoDS::Wire(hSorted->Value(i));
// Fix any topological issues of the wire
ShapeFix_Wire aFix;
aFix.SetPrecision(Precision::Confusion());
aFix.Load(new_wire);
aFix.FixReorder();
aFix.FixConnected();
aFix.FixClosed();
wires.push_back(aFix.Wire());
}
}

View File

@ -28,6 +28,7 @@
class TopoDS_Shape; class TopoDS_Shape;
class TopoDS_Wire; class TopoDS_Wire;
class TopTools_IndexedMapOfShape;
namespace Part { namespace Part {
@ -35,8 +36,13 @@ class PartExport CrossSection
{ {
public: public:
CrossSection(double a, double b, double c, const TopoDS_Shape& s); CrossSection(double a, double b, double c, const TopoDS_Shape& s);
std::list<TopoDS_Wire> section(double d) const; std::list<TopoDS_Wire> slice(double d) const;
private:
void sliceNonSolid(double d, const TopoDS_Shape&, std::list<TopoDS_Wire>& wires) const;
void sliceSolid(double d, const TopoDS_Shape&, std::list<TopoDS_Wire>& wires) const;
void connectEdges (const std::list<TopoDS_Edge>& edges, std::list<TopoDS_Wire>& wires) const; void connectEdges (const std::list<TopoDS_Edge>& edges, std::list<TopoDS_Wire>& wires) const;
void connectWires (const TopTools_IndexedMapOfShape& wireMap, std::list<TopoDS_Wire>& wires) const;
private: private:
double a,b,c; double a,b,c;

View File

@ -1306,7 +1306,7 @@ TopoDS_Shape TopoShape::section(TopoDS_Shape shape) const
std::list<TopoDS_Wire> TopoShape::slice(const Base::Vector3d& dir, double d) const std::list<TopoDS_Wire> TopoShape::slice(const Base::Vector3d& dir, double d) const
{ {
CrossSection cs(dir.x, dir.y, dir.z, this->_Shape); CrossSection cs(dir.x, dir.y, dir.z, this->_Shape);
return cs.section(d); return cs.slice(d);
} }
TopoDS_Compound TopoShape::slices(const Base::Vector3d& dir, const std::vector<double>& d) const TopoDS_Compound TopoShape::slices(const Base::Vector3d& dir, const std::vector<double>& d) const
@ -1314,7 +1314,7 @@ TopoDS_Compound TopoShape::slices(const Base::Vector3d& dir, const std::vector<d
std::vector< std::list<TopoDS_Wire> > wire_list; std::vector< std::list<TopoDS_Wire> > wire_list;
CrossSection cs(dir.x, dir.y, dir.z, this->_Shape); CrossSection cs(dir.x, dir.y, dir.z, this->_Shape);
for (std::vector<double>::const_iterator jt = d.begin(); jt != d.end(); ++jt) { for (std::vector<double>::const_iterator jt = d.begin(); jt != d.end(); ++jt) {
wire_list.push_back(cs.section(*jt)); wire_list.push_back(cs.slice(*jt));
} }
std::vector< std::list<TopoDS_Wire> >::const_iterator ft; std::vector< std::list<TopoDS_Wire> >::const_iterator ft;