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