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