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