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