Salome HOME
Initial merge of branch 'BR_HYDRO_IMPS_2016' into BR_PORTING_OCCT_7
[modules/hydro.git] / src / HYDROData / HYDROData_ImmersibleZone.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_ImmersibleZone.h"
20
21 #include "HYDROData_IAltitudeObject.h"
22 #include "HYDROData_Document.h"
23 #include "HYDROData_ShapesGroup.h"
24 #include "HYDROData_PolylineXY.h"
25 #include "HYDROData_ShapesTool.h"
26
27 #include <BRepBuilderAPI_MakeFace.hxx>
28
29 #include <TopoDS.hxx>
30 #include <TopoDS_Face.hxx>
31 #include <TopoDS_Wire.hxx>
32 #include <TopoDS_Compound.hxx>
33 #include <TopExp_Explorer.hxx>
34 #include <TopTools_ListIteratorOfListOfShape.hxx>
35 #include <TopTools_HSequenceOfShape.hxx>
36
37 #include <BRep_Builder.hxx>
38 #include <BRepAlgo_FaceRestrictor.hxx>
39 #include <BRepCheck_Analyzer.hxx>
40
41 #include <ShapeAnalysis.hxx>
42 #include <ShapeAnalysis_FreeBounds.hxx>
43
44 #include <QColor>
45 #include <QStringList>
46
47 #define DEB_IMZ
48 #include <BRepTools.hxx>
49 #define _DEVDEBUG_
50 #include "HYDRO_trace.hxx"
51
52 //#define HYDRODATA_IMZONE_DEB 1
53
54 IMPLEMENT_STANDARD_RTTIEXT(HYDROData_ImmersibleZone,HYDROData_NaturalObject)
55
56
57 HYDROData_ImmersibleZone::HYDROData_ImmersibleZone()
58 : HYDROData_NaturalObject( Geom_2d )
59 {
60 }
61
62 HYDROData_ImmersibleZone::~HYDROData_ImmersibleZone()
63 {
64 }
65
66 QStringList HYDROData_ImmersibleZone::DumpToPython( const QString& thePyScriptPath,
67                                                     MapOfTreatedObjects& theTreatedObjects ) const
68 {
69   QStringList aResList = dumpObjectCreation( theTreatedObjects );
70   
71   QString aZoneName = GetObjPyName();
72
73   Handle(HYDROData_IAltitudeObject) aRefAltitude = GetAltitudeObject();
74   setPythonReferenceObject( thePyScriptPath, theTreatedObjects, aResList, aRefAltitude, "SetAltitudeObject" );
75
76   Handle(HYDROData_PolylineXY) aRefPolyline = GetPolyline();
77   setPythonReferenceObject( thePyScriptPath, theTreatedObjects, aResList, aRefPolyline, "SetPolyline" );
78
79   if (!this->IsSubmersible())
80     {
81       aResList << QString( "%1.SetIsSubmersible(False)" ).arg( aZoneName );
82     }
83
84   aResList << QString( "" );
85
86   aResList << QString( "%1.Update()" ).arg( aZoneName );
87   aResList << QString( "" );
88
89   return aResList;
90 }
91
92 HYDROData_SequenceOfObjects HYDROData_ImmersibleZone::GetAllReferenceObjects() const
93 {
94   HYDROData_SequenceOfObjects aResSeq = HYDROData_NaturalObject::GetAllReferenceObjects();
95
96   Handle(HYDROData_PolylineXY) aRefPolyline = GetPolyline();
97   if ( !aRefPolyline.IsNull() )
98     aResSeq.Append( aRefPolyline );
99
100   return aResSeq;
101 }
102
103 void HYDROData_ImmersibleZone::Update()
104 {
105   HYDROData_NaturalObject::Update();
106   
107   TopoDS_Shape aResShape = generateTopShape();
108   SetTopShape( aResShape );
109
110   createGroupObjects();
111 }
112
113 bool HYDROData_ImmersibleZone::IsHas2dPrs() const
114 {
115   return true;
116 }
117
118 TopoDS_Shape HYDROData_ImmersibleZone::generateTopShape() const
119 {
120   return generateTopShape( GetPolyline() );
121 }
122
123 TopoDS_Shape HYDROData_ImmersibleZone::generateTopShape( const Handle(HYDROData_PolylineXY)& aPolyline )
124 {
125   //DEBTRACE("generateTopShape");
126   TopoDS_Face aResultFace = TopoDS_Face(); // --- result: default = null face
127
128   if (!aPolyline.IsNull())
129     {
130       TopoDS_Shape aPolylineShape = aPolyline->GetShape();
131 #ifdef DEB_IMZ
132       std::string brepName = "imz.brep";
133       BRepTools::Write(aPolylineShape, brepName.c_str());
134 #endif
135       TopTools_ListOfShape aWiresList;
136
137       if (!aPolylineShape.IsNull() && aPolylineShape.ShapeType() == TopAbs_WIRE)
138         {
139           // --- only one wire: try to make a face
140           //DEBTRACE("one wire: try to build a face");
141           const TopoDS_Wire& aPolylineWire = TopoDS::Wire(aPolylineShape);
142           if (!aPolylineWire.IsNull())
143             {
144               BRepBuilderAPI_MakeFace aMakeFace(aPolylineWire, Standard_True);
145               aMakeFace.Build();
146               if (aMakeFace.IsDone())
147                 {
148                   //DEBTRACE(" a face with the only wire given");
149                   aResultFace = aMakeFace.Face();
150                 }
151             }
152         }
153       else
154         {
155           // --- a list of wires ? inventory of wires and edges
156           Handle(TopTools_HSequenceOfShape) aSeqWires = new TopTools_HSequenceOfShape;
157           Handle(TopTools_HSequenceOfShape) aSeqEdges = new TopTools_HSequenceOfShape;
158           TopExp_Explorer anExp(aPolylineShape, TopAbs_WIRE);
159           //DEBTRACE("list of wires ?");
160           for (; anExp.More(); anExp.Next())
161             {
162               if (!anExp.Current().IsNull())
163                 {
164                   const TopoDS_Wire& aWire = TopoDS::Wire(anExp.Current());
165                   aWiresList.Append(aWire);
166                   //DEBTRACE("  append wire");
167                   TopExp_Explorer it2(aWire, TopAbs_EDGE);
168                   for (; it2.More(); it2.Next())
169                     aSeqEdges->Append(it2.Current());
170                 }
171             }
172           if (aWiresList.IsEmpty())
173             return aResultFace; // --- no wires: null result
174
175           if (aSeqEdges->Length() > 1)
176             {
177               //DEBTRACE("try to connect all the edges together, build a unique wire and a face");
178               // --- try to create one wire by connecting edges with a distance tolerance (no necessity of sharing points)
179               ShapeAnalysis_FreeBounds::ConnectEdgesToWires(aSeqEdges, 1E-5, Standard_False, aSeqWires);
180
181               if (aSeqWires->Length() == 1)
182                 {
183                   // --- one wire: try to make a face
184                   const TopoDS_Wire& aPolylineWire = TopoDS::Wire(aSeqWires->Value(1));
185                   if (!aPolylineWire.IsNull())
186                     {
187                       BRepBuilderAPI_MakeFace aMakeFace(aPolylineWire, Standard_True);
188                       aMakeFace.Build();
189                       if (aMakeFace.IsDone())
190                         {
191                           //DEBTRACE("  a face from all the wires connected");
192                           aResultFace = aMakeFace.Face();
193                         }
194                     }
195                 }
196             }
197
198           if (aResultFace.IsNull())
199             {
200               //DEBTRACE("try to make a face with the first wire of the list and other wires as restrictions");
201               // --- try to make a face with the first wire of the list and other wires as restrictions
202               BRepAlgo_FaceRestrictor aFR;
203               TopoDS_Face aRefFace;
204               TopoDS_Shape aS = aWiresList.First();
205               BRepBuilderAPI_MakeFace aMakeFace(TopoDS::Wire(aWiresList.First()), Standard_True);
206               aMakeFace.Build();
207               if (aMakeFace.IsDone())
208                 {
209                   //DEBTRACE("  a face with first wire");
210                   aRefFace = aMakeFace.Face();
211                 }
212               if (!aRefFace.IsNull())
213                 {
214                   aFR.Init(aRefFace, Standard_False, Standard_True);
215                   TopTools_ListIteratorOfListOfShape anIt(aWiresList);
216                   for (; anIt.More(); anIt.Next())
217                     {
218                       TopoDS_Wire& aWire = TopoDS::Wire(anIt.Value());
219                       if (aWire.IsNull())
220                         continue;
221                       aFR.Add(aWire);
222                     }
223                   aFR.Perform();
224                   if (aFR.IsDone())
225                     {
226                       for (; aFR.More(); aFR.Next())
227                         {
228                           //DEBTRACE("  a restricted face");
229                           aResultFace = aFR.Current();
230                           break;
231                         }
232                     }
233                 }
234             }
235         }
236     }
237
238   if (aResultFace.IsNull())
239     return aResultFace;
240
241   //DEBTRACE("check the face");
242   BRepCheck_Analyzer anAnalyzer(aResultFace);
243   if (anAnalyzer.IsValid() && aResultFace.ShapeType() == TopAbs_FACE)
244   {
245     //DEBTRACE("face OK");
246     return aResultFace;
247   }
248   else
249   {
250     //DEBTRACE("bad face");
251   }
252   return TopoDS_Face();
253 }
254
255 void HYDROData_ImmersibleZone::createGroupObjects()
256 {
257   TopoDS_Shape aZoneShape = GetTopShape();
258   
259   // Temporary solution while the restriction for polylines is not implemented
260   // and shape for zone can be compound and not face only
261   if ( !aZoneShape.IsNull() && aZoneShape.ShapeType() != TopAbs_FACE )
262   {
263     TopExp_Explorer aZoneFaceExp( aZoneShape, TopAbs_FACE );
264     if ( aZoneFaceExp.More() )
265       aZoneShape = aZoneFaceExp.Current(); // Take only first face into account
266   }
267
268   if ( aZoneShape.IsNull() || aZoneShape.ShapeType() != TopAbs_FACE )
269     return;
270
271   TopoDS_Face aZoneFace = TopoDS::Face( aZoneShape );
272   
273   TopoDS_Wire aZoneOuterWire = ShapeAnalysis::OuterWire( aZoneFace );
274
275   // Create outer edges group
276   QString anOutWiresGroupName = GetName() + "_Outer";
277
278   Handle(HYDROData_ShapesGroup) anOutWiresGroup = createGroupObject();
279   anOutWiresGroup->SetName( anOutWiresGroupName );
280
281   TopTools_SequenceOfShape anOuterEdges;
282   HYDROData_ShapesTool::ExploreShapeToShapes( aZoneOuterWire, TopAbs_EDGE, anOuterEdges );
283   anOutWiresGroup->SetShapes( anOuterEdges );
284
285   int anInnerCounter = 1;
286   TopExp_Explorer aZoneFaceExp( aZoneFace, TopAbs_WIRE );
287   for ( ; aZoneFaceExp.More(); aZoneFaceExp.Next() )
288   {
289     TopoDS_Wire aZoneWire = TopoDS::Wire( aZoneFaceExp.Current() );
290     if ( aZoneWire.IsEqual( aZoneOuterWire ) )
291       continue; // Skip the outer wire
292
293     TopTools_SequenceOfShape anInnerEdges;
294     HYDROData_ShapesTool::ExploreShapeToShapes( aZoneWire, TopAbs_EDGE, anInnerEdges );
295     if ( anInnerEdges.IsEmpty() )
296       continue;
297
298     QString anInWiresGroupName = GetName() + "_Inner_" + QString::number( anInnerCounter++ );
299
300     Handle(HYDROData_ShapesGroup) anInWiresGroup = createGroupObject();
301     anInWiresGroup->SetName( anInWiresGroupName );
302
303     anInWiresGroup->SetShapes( anInnerEdges );
304   }  
305 }
306
307 TopoDS_Shape HYDROData_ImmersibleZone::GetShape3D() const
308 {
309   return GetTopShape();
310 }
311
312 QColor HYDROData_ImmersibleZone::DefaultFillingColor() const
313 {
314   return QColor( Qt::darkBlue );
315 }
316
317 QColor HYDROData_ImmersibleZone::DefaultBorderColor() const
318 {
319   return QColor( Qt::transparent );
320 }
321
322 void HYDROData_ImmersibleZone::SetPolyline( const Handle(HYDROData_PolylineXY)& thePolyline )
323 {
324   if( IsEqual( GetPolyline(), thePolyline ) )
325     return;
326
327   SetReferenceObject( thePolyline, DataTag_Polyline );
328   Changed( Geom_2d );
329 }
330
331 Handle(HYDROData_PolylineXY) HYDROData_ImmersibleZone::GetPolyline() const
332 {
333   return Handle(HYDROData_PolylineXY)::DownCast( 
334            GetReferenceObject( DataTag_Polyline ) );
335 }
336
337 void HYDROData_ImmersibleZone::RemovePolyline()
338 {
339   ClearReferenceObjects( DataTag_Polyline );
340   Changed( Geom_2d );
341 }