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