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