Salome HOME
Minor changes.
[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   HLRAlgo_Projector theProjector(gp::XOY());
237
238   Handle(HLRBRep_Algo) aHLRAlgo = new HLRBRep_Algo();
239   aHLRAlgo->Add(aShape);
240   aHLRAlgo->Projector(theProjector);
241   aHLRAlgo->Update();
242   aHLRAlgo->Hide();
243   HLRBRep_HLRToShape aHLRToShape(aHLRAlgo);
244
245   TopoDS_Shape SharpEdges, OutLines;
246   TopoDS_Compound Total;
247   BRep_Builder BB;
248   BB.MakeCompound(Total);
249
250   SharpEdges = aHLRToShape.VCompound();
251   OutLines = aHLRToShape.OutLineVCompound();
252
253   TopoDS_Iterator itc;
254   if (!SharpEdges.IsNull())
255   {
256     for (itc.Initialize(SharpEdges); itc.More(); itc.Next())
257       BB.Add(Total, itc.Value());
258   }
259   if (!OutLines.IsNull())
260   {
261     for (itc.Initialize(OutLines); itc.More(); itc.Next())
262       BB.Add(Total, itc.Value());
263   }
264
265   BRepBuilderAPI_Sewing aSewing;
266   Standard_Real tol = 1.0e-06;
267   Standard_Boolean NonManifoldMode = Standard_False;
268   aSewing.Init(tol, Standard_True,Standard_True,Standard_True,NonManifoldMode);
269   aSewing.SetFloatingEdgesMode(Standard_True);
270
271   aSewing.Add( Total );
272   aSewing.Perform();
273
274   TopoDS_Shape SewedEdges = aSewing.SewedShape();
275
276   BRepLib::BuildCurves3d( SewedEdges );
277
278   Bnd_Box theBox;
279   BRepBndLib::Add(SewedEdges, theBox);
280   Standard_Real Xmin, Ymin, Zmin, Xmax, Ymax, Zmax;
281   theBox.Get(Xmin, Ymin, Zmin, Xmax, Ymax, Zmax);
282
283   gp_Pnt P1(Xmin, Ymin, 0.), P2(Xmax, Ymin, 0.);
284   TopoDS_Edge LowerBound = BRepLib_MakeEdge(P1, P2);
285   
286   Standard_Real Deviation = 1.e-7; //1.e-5;
287   BRepExtrema_DistShapeShape DSS(SewedEdges, LowerBound, Deviation);
288
289   TopTools_IndexedDataMapOfShapeListOfShape StartShapes;
290   TopTools_DataMapOfShapeReal EdgesWithPars;
291   Standard_Integer i;
292   for (i = 1; i <= DSS.NbSolution(); i++)
293   {
294     if (!StartShapes.Contains( DSS.SupportOnShape1(i) ))
295     {
296       TopTools_ListOfShape aList;
297       aList.Append( DSS.SupportOnShape2(i) );
298       StartShapes.Add( DSS.SupportOnShape1(i), aList );
299     }
300     else
301     {
302       TopTools_ListOfShape& aList = StartShapes.ChangeFromKey( DSS.SupportOnShape1(i) );
303       aList.Append( DSS.SupportOnShape2(i) );
304     }
305     if (DSS.SupportTypeShape1(i) == BRepExtrema_IsOnEdge)
306     {
307       Standard_Real aPar;
308       DSS.ParOnEdgeS1(i, aPar);
309       EdgesWithPars.Bind( DSS.SupportOnShape1(i), aPar );
310     }
311   }
312   
313   TopoDS_Shape aStartShape;
314   for (i = 1; i <= StartShapes.Extent(); i++)
315   {
316     const TopoDS_Shape& aShape = StartShapes.FindKey(i);
317     if (aShape.ShapeType() == TopAbs_EDGE)
318     {
319       aStartShape = aShape;
320       break;
321     }
322   }
323   if (aStartShape.IsNull())
324     aStartShape = StartShapes.FindKey(1); //it is a vertex
325   
326   TopoDS_Vertex StartVertex;
327   TopoDS_Edge   StartEdge;
328   gp_Vec StartDir(1.,0.,0.);
329   TopTools_IndexedDataMapOfShapeListOfShape VEmap;
330   TopExp::MapShapesAndAncestors(SewedEdges, TopAbs_VERTEX, TopAbs_EDGE, VEmap);
331   if (aStartShape.ShapeType() == TopAbs_EDGE)
332   {
333     StartEdge = TopoDS::Edge(aStartShape);
334     Standard_Real StartPar = EdgesWithPars(StartEdge);
335     BRepAdaptor_Curve BAcurve(StartEdge);
336     gp_Pnt aPnt;
337     gp_Vec aDir;
338     BAcurve.D1(StartPar, aPnt, aDir);
339     StartVertex = (StartDir * aDir > 0.)?
340       TopExp::FirstVertex(StartEdge) : TopExp::LastVertex(StartEdge);
341   }
342   else // it is a vertex
343   {
344     StartVertex = TopoDS::Vertex(aStartShape);
345     const TopTools_ListOfShape& Candidates = VEmap.FindFromKey(StartVertex);
346     StartEdge = FindClosestDirection(StartVertex, Candidates, StartDir);
347   }
348
349   TopoDS_Wire OutWire = BuildOutWire(VEmap, StartVertex, StartEdge);
350   TopoDS_Face ProjFace = BRepLib_MakeFace(OutWire, Standard_True); //only plane
351   
352   return ProjFace;
353 }
354