Salome HOME
compilation on Linux
[modules/hydro.git] / src / HYDROData / HYDROData_Projection.cxx
1 // Copyright (C) 2007-2015  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 #include <HYDROData_Projection.h>
24 #include <BRepAdaptor_Curve.hxx>
25 #include <BRep_Builder.hxx>
26 #include <BRepBuilderAPI_Sewing.hxx>
27 #include <BRepLib.hxx>
28 #include <BRepLib_MakeEdge.hxx>
29 #include <BRepLib_MakeFace.hxx>
30 #include <BRepExtrema_DistShapeShape.hxx>
31 #include <Bnd_Box.hxx>
32 #include <BRepBndLib.hxx>
33 #include <gp_Pnt.hxx>
34 #include <gp_Lin.hxx>
35 #include <HLRAlgo_Projector.hxx>
36 #include <HLRBRep_Algo.hxx>
37 #include <HLRBRep_HLRToShape.hxx>
38 #include <IntCurvesFace_ShapeIntersector.hxx>
39 #include <Precision.hxx>
40 #include <TopoDS_Edge.hxx>
41 #include <TopoDS_Shape.hxx>
42 #include <TopoDS_Vertex.hxx>
43 #include <TopoDS_Wire.hxx>
44 #include <TopoDS.hxx>
45 #include <TopoDS_Iterator.hxx>
46 #include <TopExp.hxx>
47 #include <TopTools_ListIteratorOfListOfShape.hxx>
48 #include <TopTools_MapOfShape.hxx>
49 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
50 #include <TopTools_DataMapOfShapeReal.hxx>
51
52 HYDROData_Make3dMesh::HYDROData_Make3dMesh( const TopoDS_Shape& aShape,
53                                             const Standard_Real Tolerance )
54 {
55   myIntersector.Load(aShape, Tolerance);
56 }
57
58 Standard_Boolean HYDROData_Make3dMesh::GetHighestOriginal(const Standard_Real aX,
59                                                           const Standard_Real aY,
60                                                           gp_Pnt& HighestPoint)
61 {
62   gp_Pnt ProjPnt(aX, aY, 0.);
63   gp_Lin Ray(ProjPnt, -gp::DZ());
64   myIntersector.PerformNearest(Ray, -Precision::Infinite(), 0.);
65   if (!myIntersector.IsDone() || myIntersector.NbPnt() == 0)
66     return Standard_False;
67
68   HighestPoint = myIntersector.Pnt(1);
69   return Standard_True;
70 }
71
72 //=======================================================================
73 //function : FindClosestDirection
74 //purpose  : auxiliary function
75 //=======================================================================
76 TopoDS_Edge HYDROData_Projection::FindClosestDirection( const TopoDS_Vertex& StartVertex,
77                                                         const TopTools_ListOfShape& Candidates,
78                                                         const gp_Vec& StartDir )
79 {
80   Standard_Real MinAngle = M_PI;
81   TopoDS_Edge theEdge;
82
83   TopTools_ListIteratorOfListOfShape itl(Candidates);
84   for (; itl.More(); itl.Next())
85   {
86     TopoDS_Edge anEdge = TopoDS::Edge(itl.Value());
87     BRepAdaptor_Curve BAcurve(anEdge);
88     gp_Pnt aPnt, aPnt2;
89     gp_Vec aDir, aDir2;
90     
91     Standard_Real Par, Par2 = 0.; //to avoid warning
92     Standard_Boolean ToReverse = Standard_False;
93     
94     TopoDS_Vertex V1, V2;
95     TopExp::Vertices(anEdge, V1, V2);
96     if (StartVertex.IsSame(V1))
97       Par = 0.99*BAcurve.FirstParameter() + 0.01*BAcurve.LastParameter();
98     else
99     {
100       Par = 0.01*BAcurve.FirstParameter() + 0.99*BAcurve.LastParameter();
101       ToReverse = Standard_True;
102     }
103     if (V1.IsSame(V2))
104     {
105       Par2 = 0.01*BAcurve.FirstParameter() + 0.99*BAcurve.LastParameter();
106     }
107     
108     BAcurve.D1(Par, aPnt, aDir);
109     if (ToReverse)
110       aDir.Reverse();
111     
112     if (V1.IsSame(V2))
113     {
114       BAcurve.D1(Par2, aPnt2, aDir2);
115       aDir2.Reverse();
116     }
117     
118     Standard_Real anAngle = StartDir.Angle(aDir);
119     if (anAngle < MinAngle)
120     {
121       MinAngle = anAngle;
122       theEdge = anEdge;
123     }
124     
125     if (V1.IsSame(V2))
126     {
127       anAngle = StartDir.Angle(aDir2);
128       if (anAngle < MinAngle)
129       {
130         MinAngle = anAngle;
131         theEdge = anEdge;
132       }
133     }     
134   }
135
136   return theEdge;
137 }
138
139 //=======================================================================
140 //function : BuildOutWire
141 //purpose  : auxiliary function
142 //=======================================================================
143 TopoDS_Wire HYDROData_Projection::BuildOutWire( const TopTools_IndexedDataMapOfShapeListOfShape& VEmap,
144                                                 const TopoDS_Vertex& StartVertex,
145                                                 TopoDS_Edge&   StartEdge)
146 {
147   Standard_Real AngularTol = 0.1; //0.01; //1.e-4; //Precision::Angular();
148   TopTools_MapOfShape BoundEdges;
149
150   TopoDS_Wire theWire;
151   BRep_Builder BB;
152   BB.MakeWire(theWire);
153
154   TopoDS_Vertex V1, V2;
155   TopExp::Vertices(StartEdge, V1, V2);
156   if (StartVertex.IsSame(V1))
157     StartEdge.Orientation(TopAbs_FORWARD);
158   else
159     StartEdge.Orientation(TopAbs_REVERSED);
160   BB.Add(theWire, StartEdge);
161   BoundEdges.Add(StartEdge);
162
163   TopoDS_Vertex CurVertex = (StartVertex.IsSame(V1))? V2 : V1;
164   TopoDS_Edge CurEdge = StartEdge;
165   gp_Vec Normal(0., 0., 1.);
166   for (;;)
167   {
168     if (CurVertex.IsSame(StartVertex))
169     {
170       theWire.Closed(Standard_True);
171       break;
172     }
173     
174     const TopTools_ListOfShape& Candidates = VEmap.FindFromKey(CurVertex);
175     Standard_Real MinAngle = M_PI;
176     
177     BRepAdaptor_Curve CurCurve(CurEdge);
178     TopExp::Vertices(CurEdge, V1, V2);
179     Standard_Real CurPar;
180     if (CurVertex.IsSame(V2))
181       CurPar = CurCurve.LastParameter();
182     else
183       CurPar = CurCurve.FirstParameter();
184     gp_Pnt aPnt;
185     gp_Vec CurDir;
186     CurCurve.D1(CurPar, aPnt, CurDir);
187     if (CurDir.SquareMagnitude() < Precision::PConfusion())
188     {
189       CurPar = (CurVertex.IsSame(V2))?
190         0.01*CurCurve.FirstParameter() + 0.99*CurCurve.LastParameter() :
191         0.99*CurCurve.FirstParameter() + 0.01*CurCurve.LastParameter();
192       CurCurve.D1(CurPar, aPnt, CurDir);
193     }
194     if (CurVertex.IsSame(V1))
195       CurDir.Reverse();
196     
197     TopoDS_Edge theEdge;
198     TopTools_ListIteratorOfListOfShape itl(Candidates);
199     for (; itl.More(); itl.Next())
200     {
201       TopoDS_Edge anEdge = TopoDS::Edge(itl.Value());
202       if (BoundEdges.Contains(anEdge)) //if (anEdge.IsSame(CurEdge))
203         continue;
204       
205       TopExp::Vertices(anEdge, V1, V2);
206       if (V1.IsSame(V2))
207         continue;
208       
209       BRepAdaptor_Curve BAcurve(anEdge);
210       gp_Vec aDir;
211       Standard_Real aPar = (CurVertex.IsSame(V1))?
212         0.99*BAcurve.FirstParameter() + 0.01*BAcurve.LastParameter() :
213         0.01*BAcurve.FirstParameter() + 0.99*BAcurve.LastParameter();
214         //BAcurve.FirstParameter() : BAcurve.LastParameter();
215       
216       BAcurve.D1(aPar, aPnt, aDir);
217       if (CurVertex.IsSame(V2))
218         aDir.Reverse();
219       
220       Standard_Real anAngle = CurDir.AngleWithRef(aDir, Normal);
221       if (Abs(anAngle + M_PI) < AngularTol) //anAngle = -PI
222         continue;
223       if (anAngle < MinAngle)
224       {
225         MinAngle = anAngle;
226         theEdge = anEdge;
227       }
228     }
229     if (theEdge.IsNull())
230       break;
231     
232     TopExp::Vertices(theEdge, V1, V2);
233     if (CurVertex.IsSame(V1))
234       theEdge.Orientation(TopAbs_FORWARD);
235     else
236       theEdge.Orientation(TopAbs_REVERSED);
237     BB.Add(theWire, theEdge);
238     BoundEdges.Add(theEdge);
239     
240     CurVertex = (CurVertex.IsSame(V1))? V2 : V1;
241     CurEdge = theEdge;
242   }
243   
244   return theWire;
245 }
246
247 //=======================================================================
248 //Function : MakeProjection
249 //purpose  : this function makes the "shadow" of a shape on the plane XOY
250 //=======================================================================
251 TopoDS_Face HYDROData_Projection::MakeProjection( const TopoDS_Shape& aShape )
252 {
253   if ( aShape.IsNull() )
254     return TopoDS_Face();
255
256   HLRAlgo_Projector theProjector(gp::XOY());
257
258   Handle(HLRBRep_Algo) aHLRAlgo = new HLRBRep_Algo();
259   aHLRAlgo->Add(aShape);
260   aHLRAlgo->Projector(theProjector);
261   aHLRAlgo->Update();
262   aHLRAlgo->Hide();
263   HLRBRep_HLRToShape aHLRToShape(aHLRAlgo);
264
265   TopoDS_Shape SharpEdges, OutLines;
266   TopoDS_Compound Total;
267   BRep_Builder BB;
268   BB.MakeCompound(Total);
269
270   SharpEdges = aHLRToShape.VCompound();
271   OutLines = aHLRToShape.OutLineVCompound();
272
273   TopoDS_Iterator itc;
274   if (!SharpEdges.IsNull())
275   {
276     for (itc.Initialize(SharpEdges); itc.More(); itc.Next())
277       BB.Add(Total, itc.Value());
278   }
279   if (!OutLines.IsNull())
280   {
281     for (itc.Initialize(OutLines); itc.More(); itc.Next())
282       BB.Add(Total, itc.Value());
283   }
284
285   BRepBuilderAPI_Sewing aSewing;
286   Standard_Real tol = 1.0e-06;
287   Standard_Boolean NonManifoldMode = Standard_False;
288   aSewing.Init(tol, Standard_True,Standard_True,Standard_True,NonManifoldMode);
289   aSewing.SetFloatingEdgesMode(Standard_True);
290
291   aSewing.Add( Total );
292   aSewing.Perform();
293
294   TopoDS_Shape SewedEdges = aSewing.SewedShape();
295
296   BRepLib::BuildCurves3d( SewedEdges );
297
298   Bnd_Box theBox;
299   BRepBndLib::Add(SewedEdges, theBox);
300   Standard_Real Xmin, Ymin, Zmin, Xmax, Ymax, Zmax;
301   theBox.Get(Xmin, Ymin, Zmin, Xmax, Ymax, Zmax);
302
303   gp_Pnt P1(Xmin, Ymin, 0.), P2(Xmax, Ymin, 0.);
304   TopoDS_Edge LowerBound = BRepLib_MakeEdge(P1, P2);
305   
306   Standard_Real Deviation = 1.e-7; //1.e-5;
307   BRepExtrema_DistShapeShape DSS(SewedEdges, LowerBound, Deviation);
308
309   TopTools_IndexedDataMapOfShapeListOfShape StartShapes;
310   TopTools_DataMapOfShapeReal EdgesWithPars;
311   Standard_Integer i;
312   for (i = 1; i <= DSS.NbSolution(); i++)
313   {
314     if (!StartShapes.Contains( DSS.SupportOnShape1(i) ))
315     {
316       TopTools_ListOfShape aList;
317       aList.Append( DSS.SupportOnShape2(i) );
318       StartShapes.Add( DSS.SupportOnShape1(i), aList );
319     }
320     else
321     {
322       TopTools_ListOfShape& aList = StartShapes.ChangeFromKey( DSS.SupportOnShape1(i) );
323       aList.Append( DSS.SupportOnShape2(i) );
324     }
325     if (DSS.SupportTypeShape1(i) == BRepExtrema_IsOnEdge)
326     {
327       Standard_Real aPar;
328       DSS.ParOnEdgeS1(i, aPar);
329       EdgesWithPars.Bind( DSS.SupportOnShape1(i), aPar );
330     }
331   }
332   
333   TopoDS_Shape aStartShape;
334   for (i = 1; i <= StartShapes.Extent(); i++)
335   {
336     const TopoDS_Shape& aShape = StartShapes.FindKey(i);
337     if (aShape.ShapeType() == TopAbs_EDGE)
338     {
339       aStartShape = aShape;
340       break;
341     }
342   }
343   if (aStartShape.IsNull())
344     aStartShape = StartShapes.FindKey(1); //it is a vertex
345   
346   TopoDS_Vertex StartVertex;
347   TopoDS_Edge   StartEdge;
348   gp_Vec StartDir(1.,0.,0.);
349   TopTools_IndexedDataMapOfShapeListOfShape VEmap;
350   TopExp::MapShapesAndAncestors(SewedEdges, TopAbs_VERTEX, TopAbs_EDGE, VEmap);
351   if (aStartShape.ShapeType() == TopAbs_EDGE)
352   {
353     StartEdge = TopoDS::Edge(aStartShape);
354     Standard_Real StartPar = EdgesWithPars(StartEdge);
355     BRepAdaptor_Curve BAcurve(StartEdge);
356     gp_Pnt aPnt;
357     gp_Vec aDir;
358     BAcurve.D1(StartPar, aPnt, aDir);
359     StartVertex = (StartDir * aDir > 0.)?
360       TopExp::FirstVertex(StartEdge) : TopExp::LastVertex(StartEdge);
361   }
362   else // it is a vertex
363   {
364     StartVertex = TopoDS::Vertex(aStartShape);
365     const TopTools_ListOfShape& Candidates = VEmap.FindFromKey(StartVertex);
366     StartEdge = FindClosestDirection(StartVertex, Candidates, StartDir);
367   }
368
369   TopoDS_Wire OutWire = BuildOutWire(VEmap, StartVertex, StartEdge);
370   TopoDS_Face ProjFace = BRepLib_MakeFace(OutWire, Standard_True); //only plane
371   
372   return ProjFace;
373 }
374