From 348fcefb92c3bb99f61931c0694d34b0c44cad54 Mon Sep 17 00:00:00 2001 From: wmayer Date: Sun, 25 Aug 2013 17:31:04 +0200 Subject: [PATCH] 0001137: Incomplete slices when using Part.slice on a torus --- src/Mod/Part/App/CrossSection.cpp | 129 +++++++++++++++++++++--------- src/Mod/Part/App/CrossSection.h | 8 +- src/Mod/Part/App/TopoShape.cpp | 4 +- 3 files changed, 99 insertions(+), 42 deletions(-) diff --git a/src/Mod/Part/App/CrossSection.cpp b/src/Mod/Part/App/CrossSection.cpp index 04ec25e28..28af55320 100644 --- a/src/Mod/Part/App/CrossSection.cpp +++ b/src/Mod/Part/App/CrossSection.cpp @@ -24,6 +24,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ # include +# include # include # include # include @@ -33,9 +34,11 @@ # include # include # include +# include # include # include # include +# include # include # include # include @@ -51,54 +54,78 @@ CrossSection::CrossSection(double a, double b, double c, const TopoDS_Shape& s) { } -std::list CrossSection::section(double d) const +std::list CrossSection::slice(double d) const { std::list wires; -#if 0 // Fixes: 0001228: Cross section of Torus in Part Workbench fails or give wrong results - if (s.ShapeType() == TopAbs_SOLID) { - 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(s,solid); + // Fixes: 0001137: Incomplete slices when using Part.slice on a torus + TopExp_Explorer xp; + for (xp.Init(s, TopAbs_SOLID); xp.More(); xp.Next()) { + sliceSolid(d, xp.Current(), wires); + } + for (xp.Init(s, TopAbs_SHELL, TopAbs_SOLID); xp.More(); xp.Next()) { + 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()) { - 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()) { - TopTools_IndexedMapOfShape mapOfWires; - TopExp::MapShapes(face, TopAbs_WIRE, mapOfWires); - for (int j=1; j<=mapOfWires.Extent(); j++) { - const TopoDS_Wire& wire = TopoDS::Wire(mapOfWires.FindKey(j)); - wires.push_back(wire); - } - } + return wires; +} + +void CrossSection::sliceNonSolid(double d, const TopoDS_Shape& shape, std::list& wires) const +{ + BRepAlgoAPI_Section cs(shape, gp_Pln(a,b,c,-d)); + if (cs.IsDone()) { + std::list 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); + } +} + +void CrossSection::sliceSolid(double d, const TopoDS_Shape& shape, std::list& 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 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 - return wires; } void CrossSection::connectEdges (const std::list& edges, std::list& wires) const @@ -140,3 +167,27 @@ void CrossSection::connectEdges (const std::list& edges, std::list< wires.push_back(aFix.Wire()); } } + +void CrossSection::connectWires (const TopTools_IndexedMapOfShape& wireMap, std::list& 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()); + } +} diff --git a/src/Mod/Part/App/CrossSection.h b/src/Mod/Part/App/CrossSection.h index a8a141ca0..56fc90fdd 100644 --- a/src/Mod/Part/App/CrossSection.h +++ b/src/Mod/Part/App/CrossSection.h @@ -28,6 +28,7 @@ class TopoDS_Shape; class TopoDS_Wire; +class TopTools_IndexedMapOfShape; namespace Part { @@ -35,8 +36,13 @@ class PartExport CrossSection { public: CrossSection(double a, double b, double c, const TopoDS_Shape& s); - std::list section(double d) const; + std::list slice(double d) const; + +private: + void sliceNonSolid(double d, const TopoDS_Shape&, std::list& wires) const; + void sliceSolid(double d, const TopoDS_Shape&, std::list& wires) const; void connectEdges (const std::list& edges, std::list& wires) const; + void connectWires (const TopTools_IndexedMapOfShape& wireMap, std::list& wires) const; private: double a,b,c; diff --git a/src/Mod/Part/App/TopoShape.cpp b/src/Mod/Part/App/TopoShape.cpp index b41d0c9e6..85fc2ca18 100644 --- a/src/Mod/Part/App/TopoShape.cpp +++ b/src/Mod/Part/App/TopoShape.cpp @@ -1306,7 +1306,7 @@ TopoDS_Shape TopoShape::section(TopoDS_Shape shape) const std::list TopoShape::slice(const Base::Vector3d& dir, double d) const { 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& d) const @@ -1314,7 +1314,7 @@ TopoDS_Compound TopoShape::slices(const Base::Vector3d& dir, const std::vector > wire_list; CrossSection cs(dir.x, dir.y, dir.z, this->_Shape); for (std::vector::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 >::const_iterator ft;