1 // Copyright (c) 1998-1999 Matra Datavision
2 // Copyright (c) 1999-2014 OPEN CASCADE SAS
4 // This file is part of Open CASCADE Technology software library.
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
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.
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
16 #include <Bnd_Box.hxx>
17 #include <BRep_Builder.hxx>
18 #include <BRep_Tool.hxx>
19 #include <BRepAlgoAPI_Section.hxx>
20 #include <BRepBndLib.hxx>
21 #include <BRepFill_Generator.hxx>
22 #include <BRepLib_MakeEdge.hxx>
23 #include <BRepLib_MakeVertex.hxx>
24 #include <BRepLib_MakeWire.hxx>
25 #include <BRepProj_Projection.hxx>
26 #include <BRepSweep_Prism.hxx>
27 #include <BRepTools_Modifier.hxx>
28 #include <BRepTools_TrsfModification.hxx>
31 #include <gp_Trsf.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>
39 #include <TopExp_Explorer.hxx>
40 #include <TopLoc_Location.hxx>
42 #include <TopoDS_Iterator.hxx>
43 #include <TopoDS_Shape.hxx>
44 #include <TopTools_ListIteratorOfListOfShape.hxx>
45 #include <TopTools_ListOfShape.hxx>
47 //=======================================================================
48 //function : DistanceOut
49 //purpose : Compute the minimum distance between input shapes
50 // (using Bounding Boxes of each Shape)
51 //=======================================================================
52 static Standard_Real DistanceOut (const TopoDS_Shape& S1, const TopoDS_Shape& S2)
55 BRepBndLib::Add(S1,BBox1);
56 BRepBndLib::Add(S2,BBox2);
57 return BBox1.Distance(BBox2);
60 //=======================================================================
61 //function : DistanceIn
62 //purpose : Compute the maximum distance between input Shapes
63 // we compute the maximum dimension of each Bounding Box and then
64 // add each other with the minimum distance of shapes.
65 //=======================================================================
67 static Standard_Real DistanceIn (const TopoDS_Shape& S1, const TopoDS_Shape& S2)
70 BRepBndLib::Add(S1,SBBox);
71 BRepBndLib::Add(S2,LBBox);
73 Standard_Real LXmin, LYmin, LZmin, LXmax, LYmax, LZmax,
74 SXmin, SYmin, SZmin, SXmax, SYmax, SZmax;
75 SBBox.Get(SXmin, SYmin, SZmin,
77 LBBox.Get(LXmin, LYmin, LZmin,
80 //Compute the max distance between input shapes------------//
81 gp_XYZ Lmin(LXmin, LYmin, LZmin),
82 Lmax(LXmax, LYmax, LZmax);
83 gp_XYZ Smin(SXmin, SYmin, SZmin),
84 Smax(SXmax, SYmax, SZmax);
87 return Lmax.Modulus() + Smax.Modulus() + DistanceOut(S1, S2);
90 //=======================================================================
91 //function : BuildSection
92 //purpose : Cuts theShape by theTool using BRepAlgoAPI_Section and
93 // stores result as set of connected wires and compound
94 //=======================================================================
96 void BRepProj_Projection::BuildSection (const TopoDS_Shape& theShape,
97 const TopoDS_Shape& theTool)
99 myIsDone = Standard_False;
104 // if theShape is compound, extract only faces -- section algorithm
105 // may refuse to work if e.g. vertex is present
107 if (theShape.ShapeType() == TopAbs_FACE ||
108 theShape.ShapeType() == TopAbs_SHELL ||
109 theShape.ShapeType() == TopAbs_SOLID ||
110 theShape.ShapeType() == TopAbs_COMPSOLID)
112 else if (theShape.ShapeType() == TopAbs_COMPOUND)
116 TopExp_Explorer exp (theShape, TopAbs_FACE);
117 for (; exp.More(); exp.Next())
121 B.Add (C, exp.Current());
125 if ( aShape.IsNull() )
126 throw Standard_ConstructionError(__FILE__": target shape has no faces");
128 // build section computing p-curves on both shapes to get higher precision
129 BRepAlgoAPI_Section aSectionTool(aShape, theTool, Standard_False);
130 aSectionTool.Approximation(Standard_True);
131 aSectionTool.ComputePCurveOn1(Standard_True);
132 aSectionTool.ComputePCurveOn2(Standard_True);
133 // Use Oriented Bounding Boxes inside Booleans to speed up calculation of the section
134 aSectionTool.SetUseOBB(Standard_True);
135 aSectionTool.Build();
137 // check for successful work of the section tool
138 if (!aSectionTool.IsDone())
141 // get edges of the result
142 Handle(TopTools_HSequenceOfShape) anEdges = new TopTools_HSequenceOfShape;
143 TopExp_Explorer exp(aSectionTool.Shape(), TopAbs_EDGE);
144 for (; exp.More(); exp.Next())
145 anEdges->Append (exp.Current());
147 // if no edges are found, this means that this section yields no result
148 if (anEdges->Length() <= 0)
151 // connect edges to wires using ShapeAnalysis functionality
152 ShapeAnalysis_FreeBounds::ConnectEdgesToWires (anEdges, Precision::Confusion(),
153 Standard_True, mySection);
154 myIsDone = (! mySection.IsNull() && mySection->Length() > 0);
156 // collect all resulting wires to compound
160 B.MakeCompound (myShape);
161 for (Standard_Integer i=1; i <= mySection->Length(); i++)
162 B.Add (myShape, mySection->Value(i));
164 // initialize iteration (for compatibility with previous versions)
169 //=======================================================================
170 //function : BRepProj_Projection
171 //purpose : Cylindrical Projection
172 //=======================================================================
174 BRepProj_Projection::BRepProj_Projection(const TopoDS_Shape& Wire,
175 const TopoDS_Shape& Shape,
177 : myIsDone(Standard_False), myItr(0)
180 Standard_NullObject_Raise_if((Wire.IsNull() || Shape.IsNull()),__FILE__": null input shape");
181 if (Wire.ShapeType() != TopAbs_EDGE &&
182 Wire.ShapeType() != TopAbs_WIRE )
183 throw Standard_ConstructionError(__FILE__": projected shape is neither wire nor edge");
185 // compute the "length" of the cylindrical surface to build
186 Standard_Real mdis = DistanceIn(Wire, Shape);
187 gp_Vec Vsup (D.XYZ() * 2 * mdis);
188 gp_Vec Vinf (D.XYZ() * -mdis);
190 // move the base of the cylindrical surface by translating it by -mdis
192 T.SetTranslation(Vinf);
193 // Note: it is necessary to create copy of wire to avoid adding new pcurves into it
194 Handle(BRepTools_TrsfModification) Trsf = new BRepTools_TrsfModification(T);
195 BRepTools_Modifier Modif (Wire, Trsf);
196 TopoDS_Shape WireBase = Modif.ModifiedShape(Wire);
198 // Creation of a cylindrical surface
199 BRepSweep_Prism CylSurf (WireBase, Vsup, Standard_False);
202 BuildSection (Shape, CylSurf.Shape());
205 //=======================================================================
206 //function : BRepProj_Projection
207 //purpose : Conical projection
208 //=======================================================================
210 BRepProj_Projection::BRepProj_Projection (const TopoDS_Shape& Wire,
211 const TopoDS_Shape& Shape,
213 : myIsDone(Standard_False), myItr(0)
216 Standard_NullObject_Raise_if((Wire.IsNull() || Shape.IsNull()),__FILE__": null input shape");
217 if (Wire.ShapeType() != TopAbs_EDGE &&
218 Wire.ShapeType() != TopAbs_WIRE )
219 throw Standard_ConstructionError(__FILE__": projected shape is neither wire nor edge");
221 // if Wire is only an edge, transform it into a Wire
223 if (Wire.ShapeType() == TopAbs_EDGE)
230 aWire = TopoDS::Wire(Wire);
232 // compute the "length" of the conical surface to build
233 Standard_Real mdis = DistanceIn(Wire, Shape);
235 // Initialize iterator to get first sub-shape of Wire
236 TopExp_Explorer ExpWire;
237 ExpWire.Init (aWire, TopAbs_VERTEX);
239 // get the first Point of the first sub-shape os the Wire
240 gp_Pnt PC = BRep_Tool::Pnt(TopoDS::Vertex(ExpWire.Current()));
242 // compute the ratio of the scale transformation
243 Standard_Real Scale = PC.Distance(P);
244 if ( Abs (Scale) < Precision::Confusion() )
245 throw Standard_ConstructionError("Projection");
246 Scale = 1. + mdis / Scale;
248 // move the base of the conical surface by scaling it with ratio Scale
250 T.SetScale(P, Scale);
251 Handle(BRepTools_TrsfModification) Tsca = new BRepTools_TrsfModification(T);
252 BRepTools_Modifier ModifScale(aWire,Tsca);
253 TopoDS_Shape ShapeGen1 = ModifScale.ModifiedShape(aWire);
255 TopoDS_Vertex aVertex = BRepLib_MakeVertex(P);
258 BB.MakeEdge( DegEdge );
259 BB.Add( DegEdge, aVertex.Oriented(TopAbs_FORWARD) );
260 BB.Add( DegEdge, aVertex.Oriented(TopAbs_REVERSED) );
261 BB.Degenerated( DegEdge, Standard_True );
264 BB.MakeWire( DegWire );
265 BB.Add( DegWire, DegEdge );
266 DegWire.Closed( Standard_True );
268 // Build the Ruled surface based shape
269 BRepFill_Generator RuledSurf;
270 RuledSurf.AddWire(DegWire);
271 RuledSurf.AddWire(TopoDS::Wire(ShapeGen1));
273 TopoDS_Shell SurfShell = RuledSurf.Shell();
276 BuildSection (Shape, SurfShell);