Salome HOME
refs #1456: correct Python name on dump ECW images
[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   RemoveGroupObjects();
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   {
251     //DEBTRACE("bad face");
252   }
253   return TopoDS_Face();
254 }
255
256 void HYDROData_ImmersibleZone::createGroupObjects()
257 {
258   TopoDS_Shape aZoneShape = GetTopShape();
259   
260   // Temporary solution while the restriction for polylines is not implemented
261   // and shape for zone can be compound and not face only
262   if ( !aZoneShape.IsNull() && aZoneShape.ShapeType() != TopAbs_FACE )
263   {
264     TopExp_Explorer aZoneFaceExp( aZoneShape, TopAbs_FACE );
265     if ( aZoneFaceExp.More() )
266       aZoneShape = aZoneFaceExp.Current(); // Take only first face into account
267   }
268
269   if ( aZoneShape.IsNull() || aZoneShape.ShapeType() != TopAbs_FACE )
270     return;
271
272   TopoDS_Face aZoneFace = TopoDS::Face( aZoneShape );
273   
274   TopoDS_Wire aZoneOuterWire = ShapeAnalysis::OuterWire( aZoneFace );
275
276   // Create outer edges group
277   QString anOutWiresGroupName = GetName() + "_Outer";
278
279   Handle(HYDROData_ShapesGroup) anOutWiresGroup = createGroupObject();
280   anOutWiresGroup->SetName( anOutWiresGroupName );
281
282   TopTools_SequenceOfShape anOuterEdges;
283   HYDROData_ShapesTool::ExploreShapeToShapes( aZoneOuterWire, TopAbs_EDGE, anOuterEdges );
284   anOutWiresGroup->SetShapes( anOuterEdges );
285
286   int anInnerCounter = 1;
287   TopExp_Explorer aZoneFaceExp( aZoneFace, TopAbs_WIRE );
288   for ( ; aZoneFaceExp.More(); aZoneFaceExp.Next() )
289   {
290     TopoDS_Wire aZoneWire = TopoDS::Wire( aZoneFaceExp.Current() );
291     if ( aZoneWire.IsEqual( aZoneOuterWire ) )
292       continue; // Skip the outer wire
293
294     TopTools_SequenceOfShape anInnerEdges;
295     HYDROData_ShapesTool::ExploreShapeToShapes( aZoneWire, TopAbs_EDGE, anInnerEdges );
296     if ( anInnerEdges.IsEmpty() )
297       continue;
298
299     QString anInWiresGroupName = GetName() + "_Inner_" + QString::number( anInnerCounter++ );
300
301     Handle(HYDROData_ShapesGroup) anInWiresGroup = createGroupObject();
302     anInWiresGroup->SetName( anInWiresGroupName );
303
304     anInWiresGroup->SetShapes( anInnerEdges );
305   }  
306 }
307
308 TopoDS_Shape HYDROData_ImmersibleZone::GetShape3D() const
309 {
310   return GetTopShape();
311 }
312
313 QColor HYDROData_ImmersibleZone::DefaultFillingColor() const
314 {
315   return QColor( Qt::darkBlue );
316 }
317
318 QColor HYDROData_ImmersibleZone::DefaultBorderColor() const
319 {
320   return QColor( Qt::transparent );
321 }
322
323 void HYDROData_ImmersibleZone::SetPolyline( const Handle(HYDROData_PolylineXY)& thePolyline )
324 {
325   if( IsEqual( GetPolyline(), thePolyline ) )
326     return;
327
328   SetReferenceObject( thePolyline, DataTag_Polyline );
329   Changed( Geom_2d );
330 }
331
332 Handle(HYDROData_PolylineXY) HYDROData_ImmersibleZone::GetPolyline() const
333 {
334   return Handle(HYDROData_PolylineXY)::DownCast( 
335            GetReferenceObject( DataTag_Polyline ) );
336 }
337
338 void HYDROData_ImmersibleZone::RemovePolyline()
339 {
340   ClearReferenceObjects( DataTag_Polyline );
341   Changed( Geom_2d );
342 }