23
#include "PreCompiled.h"
26
# include <BRepAdaptor_Surface.hxx>
27
# include <BRepAlgoAPI_Common.hxx>
28
# include <BRepAlgoAPI_Cut.hxx>
29
# include <BRepAlgoAPI_Section.hxx>
30
# include <BRepBuilderAPI_MakeFace.hxx>
31
# include <BRepBuilderAPI_MakeWire.hxx>
32
# include <BRepPrimAPI_MakeHalfSpace.hxx>
34
# include <Precision.hxx>
35
# include <ShapeAnalysis_FreeBounds.hxx>
36
# include <ShapeFix_Wire.hxx>
38
# include <TopExp_Explorer.hxx>
39
# include <TopTools_HSequenceOfShape.hxx>
40
# include <TopTools_IndexedMapOfShape.hxx>
42
# include <TopoDS_Edge.hxx>
43
# include <TopoDS_Wire.hxx>
46
#include "CrossSection.h"
47
#include "TopoShapeOpCode.h"
52
CrossSection::CrossSection(double a, double b, double c, const TopoDS_Shape& s)
53
: a(a), b(b), c(c), s(s)
57
std::list<TopoDS_Wire> CrossSection::slice(double d) const
59
std::list<TopoDS_Wire> wires;
63
for (xp.Init(s, TopAbs_SOLID); xp.More(); xp.Next()) {
64
sliceSolid(d, xp.Current(), wires);
66
for (xp.Init(s, TopAbs_SHELL, TopAbs_SOLID); xp.More(); xp.Next()) {
67
sliceNonSolid(d, xp.Current(), wires);
69
for (xp.Init(s, TopAbs_FACE, TopAbs_SHELL); xp.More(); xp.Next()) {
70
sliceNonSolid(d, xp.Current(), wires);
73
return removeDuplicates(wires);
76
std::list<TopoDS_Wire> CrossSection::removeDuplicates(const std::list<TopoDS_Wire>& wires) const
78
std::list<TopoDS_Wire> wires_reduce;
79
for (const auto& wire : wires) {
80
TopTools_IndexedMapOfShape mapOfEdges1;
81
TopExp::MapShapes(wire, TopAbs_EDGE, mapOfEdges1);
84
auto it = std::find_if(wires_reduce.begin(), wires_reduce.end(), [&mapOfEdges1](const TopoDS_Wire& w) {
86
TopTools_IndexedMapOfShape mapOfEdges2;
87
TopExp::MapShapes(w, TopAbs_EDGE, mapOfEdges2);
88
int numEdges1 = mapOfEdges1.Extent();
89
int numEdges2 = mapOfEdges2.Extent();
90
if (numEdges1 != numEdges2)
93
TopTools_IndexedMapOfShape::Iterator it1(mapOfEdges1);
94
TopTools_IndexedMapOfShape::Iterator it2(mapOfEdges2);
95
for (; it1.More() && it2.More(); it1.Next(), it2.Next()) {
96
if (!it1.Value().IsSame(it2.Value()))
103
if (it == wires_reduce.end()) {
104
wires_reduce.push_back(wire);
110
void CrossSection::sliceNonSolid(double d, const TopoDS_Shape& shape, std::list<TopoDS_Wire>& wires) const
112
BRepAlgoAPI_Section cs(shape, gp_Pln(a,b,c,-d));
114
std::list<TopoDS_Edge> edges;
116
for (xp.Init(cs.Shape(), TopAbs_EDGE); xp.More(); xp.Next())
117
edges.push_back(TopoDS::Edge(xp.Current()));
118
connectEdges(edges, wires);
122
void CrossSection::sliceSolid(double d, const TopoDS_Shape& shape, std::list<TopoDS_Wire>& wires) const
124
gp_Pln slicePlane(a,b,c,-d);
125
BRepBuilderAPI_MakeFace mkFace(slicePlane);
126
TopoDS_Face face = mkFace.Face();
129
gp_Vec tempVector(a,b,c);
130
tempVector.Normalize();
131
tempVector *= (d+1.0);
132
gp_Pnt refPoint(0.0, 0.0, 0.0);
133
refPoint.Translate(tempVector);
135
BRepPrimAPI_MakeHalfSpace mkSolid(face, refPoint);
136
TopoDS_Solid solid = mkSolid.Solid();
137
BRepAlgoAPI_Cut mkCut(shape, solid);
139
if (mkCut.IsDone()) {
140
TopTools_IndexedMapOfShape mapOfFaces;
141
TopExp::MapShapes(mkCut.Shape(), TopAbs_FACE, mapOfFaces);
142
for (int i=1; i<=mapOfFaces.Extent(); i++) {
143
const TopoDS_Face& face = TopoDS::Face(mapOfFaces.FindKey(i));
144
BRepAdaptor_Surface adapt(face);
145
if (adapt.GetType() == GeomAbs_Plane) {
146
gp_Pln plane = adapt.Plane();
147
if (plane.Axis().IsParallel(slicePlane.Axis(), Precision::Confusion()) &&
148
plane.Distance(slicePlane.Location()) < Precision::Confusion()) {
150
TopTools_IndexedMapOfShape mapOfWires;
151
TopExp::MapShapes(face, TopAbs_WIRE, mapOfWires);
152
connectWires(mapOfWires, wires);
159
void CrossSection::connectEdges (const std::list<TopoDS_Edge>& edges, std::list<TopoDS_Wire>& wires) const
162
std::list<TopoDS_Edge> edge_list = edges;
163
while (!edge_list.empty()) {
164
BRepBuilderAPI_MakeWire mkWire;
166
mkWire.Add(edge_list.front());
167
edge_list.erase(edge_list.begin());
169
TopoDS_Wire new_wire = mkWire.Wire();
175
for (std::list<TopoDS_Edge>::iterator pE = edge_list.begin(); pE != edge_list.end();++pE) {
177
if (mkWire.Error() != BRepBuilderAPI_DisconnectedWire) {
181
new_wire = mkWire.Wire();
189
wires.push_back(fixWire(new_wire));
193
void CrossSection::connectWires (const TopTools_IndexedMapOfShape& wireMap, std::list<TopoDS_Wire>& wires) const
195
Handle(TopTools_HSequenceOfShape) hWires = new TopTools_HSequenceOfShape();
196
for (int i=1; i<=wireMap.Extent(); i++) {
197
const TopoDS_Shape& wire = wireMap.FindKey(i);
198
hWires->Append(wire);
201
Handle(TopTools_HSequenceOfShape) hSorted = new TopTools_HSequenceOfShape();
202
ShapeAnalysis_FreeBounds::ConnectWiresToWires(hWires, Precision::Confusion(), false, hSorted);
204
for (int i=1; i<=hSorted->Length(); i++) {
205
const TopoDS_Wire& new_wire = TopoDS::Wire(hSorted->Value(i));
207
wires.push_back(fixWire(new_wire));
211
TopoDS_Wire CrossSection::fixWire(const TopoDS_Wire& wire) const
215
aFix.SetPrecision(Precision::Confusion());
223
TopoCrossSection::TopoCrossSection(double a, double b, double c, const TopoShape& s, const char *op)
224
: a(a), b(b), c(c), shape(s), op(op?op:Part::OpCodes::Slice)
228
void TopoCrossSection::slice(int idx, double d, std::vector<TopoShape>& wires) const
233
for (auto& s : shape.getSubTopoShapes(TopAbs_SOLID)) {
234
sliceSolid(idx, d, s, wires);
238
for (auto& s : shape.getSubTopoShapes(TopAbs_SHELL)) {
239
sliceNonSolid(idx, d, s, wires);
243
for (auto& s : shape.getSubTopoShapes(TopAbs_FACE)) {
244
sliceNonSolid(idx, d, s, wires);
250
TopoShape TopoCrossSection::slice(int idx, double d) const
252
std::vector<TopoShape> wires;
253
slice(idx, d, wires);
254
return TopoShape().makeElementCompound(
257
TopoShape::SingleShapeCompoundCreationPolicy::returnShape);
260
void TopoCrossSection::sliceNonSolid(int idx,
262
const TopoShape& shape,
263
std::vector<TopoShape>& wires) const
265
BRepAlgoAPI_Section cs(shape.getShape(), gp_Pln(a, b, c, -d));
267
std::string prefix(op);
268
prefix += Data::indexSuffix(idx);
269
auto res = TopoShape()
270
.makeElementShape(cs, shape, prefix.c_str())
272
.getSubTopoShapes(TopAbs_WIRE);
273
wires.insert(wires.end(), res.begin(), res.end());
277
void TopoCrossSection::sliceSolid(int idx,
279
const TopoShape& shape,
280
std::vector<TopoShape>& wires) const
282
gp_Pln slicePlane(a, b, c, -d);
283
BRepBuilderAPI_MakeFace mkFace(slicePlane);
285
face.setShape(mkFace.Face());
288
gp_Vec tempVector(a, b, c);
289
tempVector.Normalize();
290
tempVector *= (d + 1.0);
291
gp_Pnt refPoint(0.0, 0.0, 0.0);
292
refPoint.Translate(tempVector);
294
BRepPrimAPI_MakeHalfSpace mkSolid(TopoDS::Face(face.getShape()), refPoint);
295
TopoShape solid(idx);
296
std::string prefix(op);
297
prefix += Data::indexSuffix(idx);
298
solid.makeElementShape(mkSolid, face, prefix.c_str());
299
BRepAlgoAPI_Cut mkCut(shape.getShape(), solid.getShape());
301
if (mkCut.IsDone()) {
302
TopoShape res(shape.Tag, shape.Hasher);
303
std::vector<TopoShape> shapes;
304
shapes.push_back(shape);
305
shapes.push_back(solid);
306
res.makeElementShape(mkCut, shapes, prefix.c_str());
307
for (auto& face : res.getSubTopoShapes(TopAbs_FACE)) {
308
BRepAdaptor_Surface adapt(TopoDS::Face(face.getShape()));
309
if (adapt.GetType() == GeomAbs_Plane) {
310
gp_Pln plane = adapt.Plane();
311
if (plane.Axis().IsParallel(slicePlane.Axis(), Precision::Confusion())
312
&& plane.Distance(slicePlane.Location()) < Precision::Confusion()) {
313
auto repaired_wires = TopoShape(face.Tag)
314
.makeElementWires(face.getSubTopoShapes(TopAbs_EDGE),
317
.getSubTopoShapes(TopAbs_WIRE);
318
wires.insert(wires.end(), repaired_wires.begin(), repaired_wires.end());