1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
|
#include <BRepProj_Projection.ixx>
#include <BRepAlgo_Section.hxx>
#include <Precision.hxx>
#include <BRepBndLib.hxx>
#include <BRepTools_TrsfModification.hxx>
#include <BRepTools_Modifier.hxx>
#include <BRepLib_MakeEdge.hxx>
#include <BRepLib_MakeWire.hxx>
#include <BRep_Tool.hxx>
#include <Bnd_Box.hxx>
#include <BRepSweep_Prism.hxx>
#include <BRepFill_Generator.hxx>
#include <TopExp.hxx>
#include <TopExp_Explorer.hxx>
#include <TopLoc_Location.hxx>
#include <gp_Dir.hxx>
#include <gp_Pnt.hxx>
#include <gp_Vec.hxx>
#include <gp_Trsf.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Iterator.hxx>
#include <TopoDS_Shape.hxx>
#include <TopTools_ListOfShape.hxx>
#include <TopTools_ListIteratorOfListOfShape.hxx>
#include <BRep_Builder.hxx>
#include <ShapeAnalysis_FreeBounds.hxx>
#include <Standard_NullObject.hxx>
#include <Standard_ConstructionError.hxx>
//=======================================================================
//function : DistanceOut
//purpose : Compute the minimum distance between input shapes
// (using Bounding Boxes of each Shape)
//=======================================================================
static Standard_Real DistanceOut (const TopoDS_Shape& S1, const TopoDS_Shape& S2)
{
Bnd_Box BBox1, BBox2;
BRepBndLib::Add(S1,BBox1);
BRepBndLib::Add(S2,BBox2);
return BBox1.Distance(BBox2);
}
//=======================================================================
//function : DistanceIn
//purpose : Compute the maximum distance between input Shapes
// we compute the maximum dimension of each Bounding Box and then
// add each other with the minimum distance of shapes.
//=======================================================================
static Standard_Real DistanceIn (const TopoDS_Shape& S1, const TopoDS_Shape& S2)
{
Bnd_Box LBBox,SBBox;
BRepBndLib::Add(S1,SBBox);
BRepBndLib::Add(S2,LBBox);
Standard_Real LXmin, LYmin, LZmin, LXmax, LYmax, LZmax,
SXmin, SYmin, SZmin, SXmax, SYmax, SZmax;
SBBox.Get(SXmin, SYmin, SZmin,
SXmax, SYmax, SZmax);
LBBox.Get(LXmin, LYmin, LZmin,
LXmax, LYmax, LZmax);
//Compute the max distance between input shapes------------//
gp_XYZ Lmin(LXmin, LYmin, LZmin),
Lmax(LXmax, LYmax, LZmax);
gp_XYZ Smin(SXmin, SYmin, SZmin),
Smax(SXmax, SYmax, SZmax);
Lmax.Subtract(Lmin);
Smax.Subtract(Smin);
return Lmax.Modulus() + Smax.Modulus() + DistanceOut(S1, S2);
}
//=======================================================================
//function : BuildSection
//purpose : Cuts theShape by theTool using BRepAlgoAPI_Section and
// stores result as set of connected wires and compound
//=======================================================================
void BRepProj_Projection::BuildSection (const TopoDS_Shape& theShape,
const TopoDS_Shape& theTool)
{
myIsDone = Standard_False;
mySection.Nullify();
myShape.Nullify();
myItr = 0;
// if theShape is compound, extract only faces -- section algorithm
// may refuse to work if e.g. vertex is present
TopoDS_Shape aShape;
if (theShape.ShapeType() == TopAbs_FACE ||
theShape.ShapeType() == TopAbs_SHELL ||
theShape.ShapeType() == TopAbs_SOLID ||
theShape.ShapeType() == TopAbs_COMPSOLID)
aShape = theShape;
else if (theShape.ShapeType() == TopAbs_COMPOUND)
{
TopoDS_Compound C;
BRep_Builder B;
TopExp_Explorer exp (theShape, TopAbs_FACE);
for (; exp.More(); exp.Next())
{
if ( C.IsNull() )
B.MakeCompound (C);
B.Add (C, exp.Current());
}
aShape = C;
}
if ( aShape.IsNull() )
Standard_ConstructionError::Raise(__FILE__": target shape has no faces");
// build section computing pcurves on the shape
// BRepAlgoAPI_Section aSectionTool (aShape, theTool, Standard_False);
BRepAlgo_Section aSectionTool (aShape, theTool, Standard_False);
aSectionTool.Approximation (Standard_True);
aSectionTool.ComputePCurveOn1 (Standard_True);
aSectionTool.Build();
// check for successful work of the section tool
if (! aSectionTool.IsDone())
return;
// get edges of the result
Handle(TopTools_HSequenceOfShape) anEdges = new TopTools_HSequenceOfShape;
TopExp_Explorer exp(aSectionTool.Shape(), TopAbs_EDGE);
for (; exp.More(); exp.Next())
anEdges->Append (exp.Current());
// if no edges are found, this means that this section yields no result
if (anEdges->Length() <= 0)
return;
// connect edges to wires using ShapeAnalysis functionality
ShapeAnalysis_FreeBounds::ConnectEdgesToWires (anEdges, Precision::Confusion(),
Standard_True, mySection);
myIsDone = (! mySection.IsNull() && mySection->Length() > 0);
// collect all resulting wires to compound
if ( myIsDone )
{
BRep_Builder B;
B.MakeCompound (myShape);
for (Standard_Integer i=1; i <= mySection->Length(); i++)
B.Add (myShape, mySection->Value(i));
// initialize iteration (for compatibility with previous versions)
myItr = 1;
}
}
//=======================================================================
//function : BRepProj_Projection
//purpose : Cylindrical Projection
//=======================================================================
BRepProj_Projection::BRepProj_Projection(const TopoDS_Shape& Wire,
const TopoDS_Shape& Shape,
const gp_Dir& D)
: myIsDone(Standard_False), myItr(0)
{
// Check the input
Standard_NullObject_Raise_if((Wire.IsNull() || Shape.IsNull()),__FILE__": null input shape");
if (Wire.ShapeType() != TopAbs_EDGE &&
Wire.ShapeType() != TopAbs_WIRE )
Standard_ConstructionError::Raise(__FILE__": projected shape is neither wire nor edge");
// compute the "length" of the cylindrical surface to build
Standard_Real mdis = DistanceIn(Wire, Shape);
gp_Vec Vsup (D.XYZ() * 2 * mdis);
gp_Vec Vinf (D.XYZ() * -mdis);
// move the base of the cylindrical surface by translating it by -mdis
gp_Trsf T;
T.SetTranslation(Vinf);
// Note: it is necessary to create copy of wire to avoid adding new pcurves into it
Handle(BRepTools_TrsfModification) Trsf = new BRepTools_TrsfModification(T);
BRepTools_Modifier Modif (Wire, Trsf);
TopoDS_Shape WireBase = Modif.ModifiedShape(Wire);
// Creation of a cylindrical surface
BRepSweep_Prism CylSurf (WireBase, Vsup, Standard_False);
// Perform section
BuildSection (Shape, CylSurf.Shape());
}
//=======================================================================
//function : BRepProj_Projection
//purpose : Conical projection
//=======================================================================
BRepProj_Projection::BRepProj_Projection (const TopoDS_Shape& Wire,
const TopoDS_Shape& Shape,
const gp_Pnt& P)
: myIsDone(Standard_False), myItr(0)
{
// Check the input
Standard_NullObject_Raise_if((Wire.IsNull() || Shape.IsNull()),__FILE__": null input shape");
if (Wire.ShapeType() != TopAbs_EDGE &&
Wire.ShapeType() != TopAbs_WIRE )
Standard_ConstructionError::Raise(__FILE__": projected shape is neither wire nor edge");
// if Wire is only an edge, transform it into a Wire
TopoDS_Wire aWire;
if (Wire.ShapeType() == TopAbs_EDGE)
{
BRep_Builder BB;
BB.MakeWire(aWire);
BB.Add(aWire, Wire);
}
else
aWire = TopoDS::Wire(Wire);
// compute the "length" of the conical surface to build
Standard_Real mdis = DistanceIn(Wire, Shape);
// Initialize iterator to get first sub-shape of Wire
TopExp_Explorer ExpWire;
ExpWire.Init (aWire, TopAbs_VERTEX);
// get the first Point of the first sub-shape os the Wire
gp_Pnt PC = BRep_Tool::Pnt(TopoDS::Vertex(ExpWire.Current()));
// compute the ratio of the scale transformation
Standard_Real Scale = PC.Distance(P);
if ( Abs (Scale) < Precision::Confusion() )
Standard_ConstructionError::Raise("Projection");
Scale = 1. + mdis / Scale;
// move the base of the conical surface by scaling it with ratio Scale
// then we do a symmetric relative to a point. So we have two generators
// for building a "semi-infinite" conic surface
gp_Trsf T;
T.SetScale(P, Scale);
Handle(BRepTools_TrsfModification) Tsca = new BRepTools_TrsfModification(T);
BRepTools_Modifier ModifScale(aWire,Tsca);
TopoDS_Shape ShapeGen1 = ModifScale.ModifiedShape(aWire);
T.SetMirror(P);
Handle(BRepTools_TrsfModification) Tmir = new BRepTools_TrsfModification(T);
BRepTools_Modifier ModifMirror(ShapeGen1,Tmir);
TopoDS_Shape ShapeGen2 = ModifMirror.ModifiedShape(ShapeGen1);
// Build the Ruled surface based shape
BRepFill_Generator RuledSurf;
RuledSurf.AddWire(TopoDS::Wire(ShapeGen1));
RuledSurf.AddWire(TopoDS::Wire(ShapeGen2));
RuledSurf.Perform();
TopoDS_Shell SurfShell = RuledSurf.Shell();
// Perform section
BuildSection (Shape, SurfShell);
}
|