0029814: Modeling Data - add method TopoDS_Shape::NbChildren() for simple check of...
[occt.git] / src / BRepProj / BRepProj_Projection.cxx
CommitLineData
b311480e 1// Copyright (c) 1998-1999 Matra Datavision
973c2be1 2// Copyright (c) 1999-2014 OPEN CASCADE SAS
b311480e 3//
973c2be1 4// This file is part of Open CASCADE Technology software library.
b311480e 5//
d5f74e42 6// This library is free software; you can redistribute it and/or modify it under
7// the terms of the GNU Lesser General Public License version 2.1 as published
973c2be1 8// by the Free Software Foundation, with special exception defined in the file
9// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
10// distribution for complete text of the license and disclaimer of any warranty.
b311480e 11//
973c2be1 12// Alternatively, this file may be used under the terms of Open CASCADE
13// commercial license or contractual agreement.
b311480e 14
7fd59977 15
42cf5bc1 16#include <Bnd_Box.hxx>
17#include <BRep_Builder.hxx>
18#include <BRep_Tool.hxx>
03cca6f7 19#include <BRepAlgoAPI_Section.hxx>
7fd59977 20#include <BRepBndLib.hxx>
42cf5bc1 21#include <BRepFill_Generator.hxx>
7fd59977 22#include <BRepLib_MakeEdge.hxx>
42cf5bc1 23#include <BRepLib_MakeVertex.hxx>
7fd59977 24#include <BRepLib_MakeWire.hxx>
42cf5bc1 25#include <BRepProj_Projection.hxx>
7fd59977 26#include <BRepSweep_Prism.hxx>
42cf5bc1 27#include <BRepTools_Modifier.hxx>
28#include <BRepTools_TrsfModification.hxx>
7fd59977 29#include <gp_Dir.hxx>
30#include <gp_Pnt.hxx>
7fd59977 31#include <gp_Trsf.hxx>
42cf5bc1 32#include <gp_Vec.hxx>
33#include <Precision.hxx>
34#include <ShapeAnalysis_FreeBounds.hxx>
35#include <Standard_ConstructionError.hxx>
36#include <Standard_NoSuchObject.hxx>
37#include <Standard_NullObject.hxx>
38#include <TopExp.hxx>
39#include <TopExp_Explorer.hxx>
40#include <TopLoc_Location.hxx>
7fd59977 41#include <TopoDS.hxx>
7fd59977 42#include <TopoDS_Shape.hxx>
7fd59977 43#include <TopTools_ListIteratorOfListOfShape.hxx>
42cf5bc1 44#include <TopTools_ListOfShape.hxx>
7fd59977 45
46//=======================================================================
47//function : DistanceOut
48//purpose : Compute the minimum distance between input shapes
49// (using Bounding Boxes of each Shape)
50//=======================================================================
7fd59977 51static Standard_Real DistanceOut (const TopoDS_Shape& S1, const TopoDS_Shape& S2)
52{
53 Bnd_Box BBox1, BBox2;
54 BRepBndLib::Add(S1,BBox1);
55 BRepBndLib::Add(S2,BBox2);
56 return BBox1.Distance(BBox2);
57}
58
59//=======================================================================
60//function : DistanceIn
61//purpose : Compute the maximum distance between input Shapes
62// we compute the maximum dimension of each Bounding Box and then
63// add each other with the minimum distance of shapes.
64//=======================================================================
65
66static Standard_Real DistanceIn (const TopoDS_Shape& S1, const TopoDS_Shape& S2)
67{
68 Bnd_Box LBBox,SBBox;
69 BRepBndLib::Add(S1,SBBox);
70 BRepBndLib::Add(S2,LBBox);
71
72 Standard_Real LXmin, LYmin, LZmin, LXmax, LYmax, LZmax,
73 SXmin, SYmin, SZmin, SXmax, SYmax, SZmax;
74 SBBox.Get(SXmin, SYmin, SZmin,
75 SXmax, SYmax, SZmax);
76 LBBox.Get(LXmin, LYmin, LZmin,
77 LXmax, LYmax, LZmax);
78
79 //Compute the max distance between input shapes------------//
80 gp_XYZ Lmin(LXmin, LYmin, LZmin),
81 Lmax(LXmax, LYmax, LZmax);
82 gp_XYZ Smin(SXmin, SYmin, SZmin),
83 Smax(SXmax, SYmax, SZmax);
84 Lmax.Subtract(Lmin);
85 Smax.Subtract(Smin);
86 return Lmax.Modulus() + Smax.Modulus() + DistanceOut(S1, S2);
87}
88
89//=======================================================================
90//function : BuildSection
91//purpose : Cuts theShape by theTool using BRepAlgoAPI_Section and
92// stores result as set of connected wires and compound
93//=======================================================================
94
95void BRepProj_Projection::BuildSection (const TopoDS_Shape& theShape,
96 const TopoDS_Shape& theTool)
97{
98 myIsDone = Standard_False;
99 mySection.Nullify();
100 myShape.Nullify();
101 myItr = 0;
102
103 // if theShape is compound, extract only faces -- section algorithm
104 // may refuse to work if e.g. vertex is present
105 TopoDS_Shape aShape;
106 if (theShape.ShapeType() == TopAbs_FACE ||
107 theShape.ShapeType() == TopAbs_SHELL ||
108 theShape.ShapeType() == TopAbs_SOLID ||
109 theShape.ShapeType() == TopAbs_COMPSOLID)
110 aShape = theShape;
111 else if (theShape.ShapeType() == TopAbs_COMPOUND)
112 {
113 TopoDS_Compound C;
114 BRep_Builder B;
115 TopExp_Explorer exp (theShape, TopAbs_FACE);
116 for (; exp.More(); exp.Next())
117 {
118 if ( C.IsNull() )
119 B.MakeCompound (C);
120 B.Add (C, exp.Current());
121 }
122 aShape = C;
123 }
124 if ( aShape.IsNull() )
9775fa61 125 throw Standard_ConstructionError(__FILE__": target shape has no faces");
7fd59977 126
03cca6f7 127 // build section computing p-curves on both shapes to get higher precision
128 BRepAlgoAPI_Section aSectionTool(aShape, theTool, Standard_False);
129 aSectionTool.Approximation(Standard_True);
130 aSectionTool.ComputePCurveOn1(Standard_True);
131 aSectionTool.ComputePCurveOn2(Standard_True);
132 // Use Oriented Bounding Boxes inside Booleans to speed up calculation of the section
133 aSectionTool.SetUseOBB(Standard_True);
7fd59977 134 aSectionTool.Build();
135
136 // check for successful work of the section tool
03cca6f7 137 if (!aSectionTool.IsDone())
7fd59977 138 return;
139
140 // get edges of the result
141 Handle(TopTools_HSequenceOfShape) anEdges = new TopTools_HSequenceOfShape;
142 TopExp_Explorer exp(aSectionTool.Shape(), TopAbs_EDGE);
143 for (; exp.More(); exp.Next())
144 anEdges->Append (exp.Current());
145
146 // if no edges are found, this means that this section yields no result
147 if (anEdges->Length() <= 0)
148 return;
149
150 // connect edges to wires using ShapeAnalysis functionality
151 ShapeAnalysis_FreeBounds::ConnectEdgesToWires (anEdges, Precision::Confusion(),
152 Standard_True, mySection);
153 myIsDone = (! mySection.IsNull() && mySection->Length() > 0);
154
155 // collect all resulting wires to compound
156 if ( myIsDone )
157 {
158 BRep_Builder B;
159 B.MakeCompound (myShape);
160 for (Standard_Integer i=1; i <= mySection->Length(); i++)
161 B.Add (myShape, mySection->Value(i));
162
163 // initialize iteration (for compatibility with previous versions)
164 myItr = 1;
165 }
166}
167
168//=======================================================================
169//function : BRepProj_Projection
170//purpose : Cylindrical Projection
171//=======================================================================
172
173BRepProj_Projection::BRepProj_Projection(const TopoDS_Shape& Wire,
174 const TopoDS_Shape& Shape,
175 const gp_Dir& D)
176: myIsDone(Standard_False), myItr(0)
177{
178 // Check the input
179 Standard_NullObject_Raise_if((Wire.IsNull() || Shape.IsNull()),__FILE__": null input shape");
180 if (Wire.ShapeType() != TopAbs_EDGE &&
181 Wire.ShapeType() != TopAbs_WIRE )
9775fa61 182 throw Standard_ConstructionError(__FILE__": projected shape is neither wire nor edge");
7fd59977 183
184 // compute the "length" of the cylindrical surface to build
185 Standard_Real mdis = DistanceIn(Wire, Shape);
186 gp_Vec Vsup (D.XYZ() * 2 * mdis);
187 gp_Vec Vinf (D.XYZ() * -mdis);
188
189 // move the base of the cylindrical surface by translating it by -mdis
190 gp_Trsf T;
191 T.SetTranslation(Vinf);
192 // Note: it is necessary to create copy of wire to avoid adding new pcurves into it
193 Handle(BRepTools_TrsfModification) Trsf = new BRepTools_TrsfModification(T);
194 BRepTools_Modifier Modif (Wire, Trsf);
195 TopoDS_Shape WireBase = Modif.ModifiedShape(Wire);
196
197 // Creation of a cylindrical surface
198 BRepSweep_Prism CylSurf (WireBase, Vsup, Standard_False);
199
200 // Perform section
201 BuildSection (Shape, CylSurf.Shape());
202}
203
204//=======================================================================
205//function : BRepProj_Projection
206//purpose : Conical projection
207//=======================================================================
208
209BRepProj_Projection::BRepProj_Projection (const TopoDS_Shape& Wire,
210 const TopoDS_Shape& Shape,
211 const gp_Pnt& P)
212: myIsDone(Standard_False), myItr(0)
213{
214 // Check the input
215 Standard_NullObject_Raise_if((Wire.IsNull() || Shape.IsNull()),__FILE__": null input shape");
216 if (Wire.ShapeType() != TopAbs_EDGE &&
217 Wire.ShapeType() != TopAbs_WIRE )
9775fa61 218 throw Standard_ConstructionError(__FILE__": projected shape is neither wire nor edge");
7fd59977 219
220 // if Wire is only an edge, transform it into a Wire
221 TopoDS_Wire aWire;
222 if (Wire.ShapeType() == TopAbs_EDGE)
223 {
224 BRep_Builder BB;
225 BB.MakeWire(aWire);
226 BB.Add(aWire, Wire);
227 }
228 else
229 aWire = TopoDS::Wire(Wire);
230
231 // compute the "length" of the conical surface to build
232 Standard_Real mdis = DistanceIn(Wire, Shape);
233
234 // Initialize iterator to get first sub-shape of Wire
235 TopExp_Explorer ExpWire;
236 ExpWire.Init (aWire, TopAbs_VERTEX);
237
238 // get the first Point of the first sub-shape os the Wire
239 gp_Pnt PC = BRep_Tool::Pnt(TopoDS::Vertex(ExpWire.Current()));
240
241 // compute the ratio of the scale transformation
242 Standard_Real Scale = PC.Distance(P);
243 if ( Abs (Scale) < Precision::Confusion() )
9775fa61 244 throw Standard_ConstructionError("Projection");
7fd59977 245 Scale = 1. + mdis / Scale;
246
247 // move the base of the conical surface by scaling it with ratio Scale
7fd59977 248 gp_Trsf T;
249 T.SetScale(P, Scale);
250 Handle(BRepTools_TrsfModification) Tsca = new BRepTools_TrsfModification(T);
251 BRepTools_Modifier ModifScale(aWire,Tsca);
252 TopoDS_Shape ShapeGen1 = ModifScale.ModifiedShape(aWire);
253
1f205411 254 TopoDS_Vertex aVertex = BRepLib_MakeVertex(P);
255 TopoDS_Edge DegEdge;
256 BRep_Builder BB;
257 BB.MakeEdge( DegEdge );
258 BB.Add( DegEdge, aVertex.Oriented(TopAbs_FORWARD) );
259 BB.Add( DegEdge, aVertex.Oriented(TopAbs_REVERSED) );
260 BB.Degenerated( DegEdge, Standard_True );
da72a17c 261
1f205411 262 TopoDS_Wire DegWire;
263 BB.MakeWire( DegWire );
264 BB.Add( DegWire, DegEdge );
265 DegWire.Closed( Standard_True );
7fd59977 266
267 // Build the Ruled surface based shape
268 BRepFill_Generator RuledSurf;
1f205411 269 RuledSurf.AddWire(DegWire);
7fd59977 270 RuledSurf.AddWire(TopoDS::Wire(ShapeGen1));
7fd59977 271 RuledSurf.Perform();
272 TopoDS_Shell SurfShell = RuledSurf.Shell();
273
274 // Perform section
275 BuildSection (Shape, SurfShell);
276}