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