Salome HOME
c9199eb32a41479079569b24d651b5ef5431b305
[modules/hydro.git] / src / HYDROData / HYDROData_LandCover.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_LandCover.h"
20
21 #include "HYDROData_PolylineXY.h"
22
23 #include <BRep_Builder.hxx>
24 #include <BRepBuilderAPI_MakeFace.hxx>
25 #include <BRepBuilderAPI_MakeWire.hxx>
26 #include <TDataStd_AsciiString.hxx>
27 #include <TNaming_Builder.hxx>
28 #include <TNaming_NamedShape.hxx>
29 #include <TopoDS.hxx>
30 #include <TopoDS_Shape.hxx>
31 #include <TopoDS_Wire.hxx>
32 #include <TopoDS_Face.hxx>
33 #include <TopExp_Explorer.hxx>
34 #include <TopTools_ListOfShape.hxx>
35 #include <TopTools_ListIteratorOfListOfShape.hxx>
36 #include <NCollection_IncAllocator.hxx>
37 #include <BOPAlgo_BOP.hxx>
38 #include <ShapeAnalysis_Wire.hxx>
39 #include <Precision.hxx>
40 #include <TopTools_SequenceOfShape.hxx>
41
42 #include <QColor>
43 #include <QStringList>
44
45 IMPLEMENT_STANDARD_RTTIEXT( HYDROData_LandCover, HYDROData_Entity )
46
47 HYDROData_LandCover::HYDROData_LandCover()
48 : HYDROData_Entity( Geom_2d )
49 {
50 }
51
52 HYDROData_LandCover::~HYDROData_LandCover()
53 {
54 }
55
56 const ObjectKind HYDROData_LandCover::GetKind() const
57 {
58   return KIND_LAND_COVER;
59 }
60
61 QStringList HYDROData_LandCover::DumpToPython( MapOfTreatedObjects& theTreatedObjects ) const
62 {
63   QStringList aResList = dumpObjectCreation( theTreatedObjects );
64   QString aName = GetObjPyName();
65   
66   // Set Strickler type
67   QString aType = GetStricklerType();
68   if ( !aType.isEmpty() ) {
69     aResList << QString( "" );
70     ///< \TODO to be implemented:
71     // aResList << QString( "%1.SetStricklerType( \"%2\" );" ).arg( aName ).arg( aType );
72     aResList << QString( "" );
73   }
74
75   // Set polylines
76   ///< \TODO to be implemented: 
77   
78   aResList << QString( "" );
79   aResList << QString( "%1.Update();" ).arg( aName );
80   aResList << QString( "" );
81
82   return aResList;
83 }
84
85 HYDROData_SequenceOfObjects HYDROData_LandCover::GetAllReferenceObjects() const
86 {
87   HYDROData_SequenceOfObjects aResSeq = HYDROData_Entity::GetAllReferenceObjects();
88
89   HYDROData_SequenceOfObjects aSeqOfPolylines = GetPolylines();
90   aResSeq.Append( aSeqOfPolylines );
91
92   return aResSeq;
93 }
94
95 bool HYDROData_LandCover::IsHas2dPrs() const
96 {
97   return true;
98 }
99
100 void HYDROData_LandCover::SetStricklerType( const QString& theType )
101 {
102   TCollection_AsciiString anAsciiStr( theType.toStdString().c_str() );
103   TDataStd_AsciiString::Set( myLab.FindChild( DataTag_StricklerType ), anAsciiStr );
104 }
105
106 QString HYDROData_LandCover::GetStricklerType() const
107 {
108   QString aType;
109
110   TDF_Label aLabel = myLab.FindChild( DataTag_StricklerType, false );
111   if ( !aLabel.IsNull() ) {
112     Handle(TDataStd_AsciiString) anAsciiStr;
113     if ( aLabel.FindAttribute( TDataStd_AsciiString::GetID(), anAsciiStr ) ) {
114       aType = QString( anAsciiStr->Get().ToCString() );
115     }
116   }
117
118   return aType;
119 }
120
121 void HYDROData_LandCover::Update()
122 {
123   HYDROData_Entity::Update();
124   
125   removeShape();
126
127   TCollection_AsciiString anErrorMsg;
128   TopoDS_Shape aResShape = buildShape( GetPolylines(), anErrorMsg );
129   
130   setShape( aResShape );
131 }
132
133 void HYDROData_LandCover::SetPolylines( const HYDROData_SequenceOfObjects& thePolylines )
134 {
135   SetReferenceObjects( thePolylines, DataTag_Polylines );
136   Changed( Geom_2d );
137 }
138
139 HYDROData_SequenceOfObjects HYDROData_LandCover::GetPolylines() const
140 {
141   return GetReferenceObjects( DataTag_Polylines );
142 }
143
144 TopoDS_Shape HYDROData_LandCover::GetShape() const
145 {
146   TopoDS_Shape aShape;
147
148   TDF_Label aLabel = myLab.FindChild( DataTag_Shape, false );
149   if ( !aLabel.IsNull() )
150   {
151     Handle(TNaming_NamedShape) aNamedShape;
152     if( aLabel.FindAttribute( TNaming_NamedShape::GetID(), aNamedShape ) ) {
153       aShape = aNamedShape->Get();
154     }
155   }
156
157   return aShape;
158 }
159
160 void HYDROData_LandCover::SetFillingColor( const QColor& theColor )
161 {
162   SetColor( theColor, DataTag_FillingColor );
163 }
164
165 QColor HYDROData_LandCover::GetFillingColor() const
166 {
167   return GetColor( DefaultFillingColor(), DataTag_FillingColor );
168 }
169
170 void HYDROData_LandCover::SetBorderColor( const QColor& theColor )
171 {
172   SetColor( theColor, DataTag_BorderColor );
173 }
174
175 QColor HYDROData_LandCover::GetBorderColor() const
176 {
177   return GetColor( DefaultBorderColor(), DataTag_BorderColor );
178 }
179
180 QColor HYDROData_LandCover::DefaultFillingColor()
181 {
182   return QColor( Qt::magenta );
183 }
184
185 QColor HYDROData_LandCover::DefaultBorderColor()
186 {
187   return QColor( Qt::transparent );
188 }
189
190 void HYDROData_LandCover::setShape( const TopoDS_Shape& theShape )
191 {
192   TNaming_Builder aBuilder( myLab.FindChild( DataTag_Shape ) );
193   aBuilder.Generated( theShape );
194 }
195
196 void HYDROData_LandCover::removeShape()
197 {
198   TDF_Label aLabel = myLab.FindChild( DataTag_Shape, false );
199   if ( !aLabel.IsNull() ) {
200     aLabel.ForgetAllAttributes();
201   }
202 }
203
204 TopoDS_Shape HYDROData_LandCover::buildShape( const HYDROData_SequenceOfObjects& thePolylines,
205                                               TCollection_AsciiString& theErrorMsg )
206 {
207   theErrorMsg.Clear();
208   TopoDS_Shape aResShape;
209
210   BRepBuilderAPI_MakeWire aMakeWire;
211   
212   TopTools_ListOfShape aClosedWires;
213
214   int aNbPolylines = thePolylines.Length();
215   for ( int i = 1; i <= aNbPolylines; ++i ) {
216     Handle(HYDROData_PolylineXY) aPolyline = 
217       Handle(HYDROData_PolylineXY)::DownCast( thePolylines.Value( i ) );
218     
219     if ( aPolyline.IsNull() ) {
220       continue;
221     }
222
223     TopoDS_Shape aPolyShape = aPolyline->GetShape();
224     if ( aPolyShape.IsNull() ) {
225       continue;
226     }
227
228     // Extract polyline wire(s)
229     TopTools_ListOfShape aPolylineWires;
230       
231     if ( aPolyShape.ShapeType() == TopAbs_WIRE ) {
232       const TopoDS_Wire& aPolylineWire = TopoDS::Wire( aPolyShape );
233       if ( !aPolylineWire.IsNull() ) {
234         aPolylineWires.Append( aPolylineWire );
235       }
236     } else if ( aPolyShape.ShapeType() == TopAbs_COMPOUND ) {
237       TopExp_Explorer anExp( aPolyShape, TopAbs_WIRE );
238       for (; anExp.More(); anExp.Next() ) {
239         if(!anExp.Current().IsNull()) {
240           const TopoDS_Wire& aWire = TopoDS::Wire( anExp.Current() );
241           aPolylineWires.Append( aWire );
242         }
243       }
244     }
245     
246     TopTools_ListIteratorOfListOfShape anIt( aPolylineWires );
247     for ( ; anIt.More(); anIt.Next() ) {
248       TopoDS_Wire& aWire = TopoDS::Wire( anIt.Value() );
249       
250       if ( aWire.Closed() ) {
251         aClosedWires.Append( aWire );
252       } else {
253         aMakeWire.Add( aWire );
254         aMakeWire.Build();
255         if ( aMakeWire.IsDone() ) {
256           if ( aMakeWire.Wire().Closed() ) {
257             aClosedWires.Append( aMakeWire.Wire() );
258             aMakeWire = BRepBuilderAPI_MakeWire();
259           }
260         }
261       }
262     }
263   }
264
265   if ( aClosedWires.Extent() == 1 ) {
266     // make face
267     TopoDS_Wire aW = TopoDS::Wire( aClosedWires.First());
268     BRepBuilderAPI_MakeFace aMakeFace( aW );
269     aMakeFace.Build();
270     if( aMakeFace.IsDone() ) 
271     {
272       Handle(ShapeAnalysis_Wire) aSAW = new ShapeAnalysis_Wire(aW, aMakeFace.Face(), Precision::Confusion());
273       if (!aSAW->CheckSelfIntersection())
274         aResShape = aMakeFace.Face();
275       else
276         theErrorMsg = "Can't create landcover on the given polyline\nSelf-intersection of wire have been detected";
277     }
278   } else if ( aClosedWires.Extent() > 1 ) {
279     // make compound
280     BRep_Builder aBuilder;
281     TopoDS_Compound aCompound;
282     aBuilder.MakeCompound( aCompound );
283     TopTools_SequenceOfShape aSeq;
284     TopTools_ListIteratorOfListOfShape aWiresIter( aClosedWires );
285     bool anErrStat = false;
286     for ( ; aWiresIter.More() && !anErrStat; aWiresIter.Next() )
287     {
288       TopoDS_Wire aW = TopoDS::Wire( aWiresIter.Value() );
289       BRepBuilderAPI_MakeFace aMakeFace( aW );
290       aMakeFace.Build();
291       if( aMakeFace.IsDone() ) 
292       {
293         Handle(ShapeAnalysis_Wire) aSAW = new ShapeAnalysis_Wire(aW, aMakeFace.Face(), Precision::Confusion());
294         if (!aSAW->CheckSelfIntersection())
295           aSeq.Append( aMakeFace.Face() );
296         else
297         {
298           anErrStat = true;
299           theErrorMsg = "Can't create landcover on the given polyline\nSelf-intersection of wire(s) have been detected";
300         }
301       }
302     }
303     if (!anErrStat)
304     {
305       for (int i = 1; i <= aSeq.Length(); i++)
306         aBuilder.Add( aCompound, aSeq(i) );
307       aResShape = aCompound;
308     }
309     else
310       aResShape = TopoDS_Shape();
311   } else if ( aNbPolylines > 0 ) {
312     TCollection_AsciiString aSourceName = aNbPolylines > 1 ? "polylines" : "polyline";
313     theErrorMsg = "Can't build closed contour on the given ";
314     theErrorMsg += aSourceName;
315   }
316
317   ///< \TODO to be reimplemented
318   /*
319   TopoDS_Shape anArgShape;
320   TopTools_ListOfShape aToolShapes;
321   
322   HYDROData_SequenceOfObjects aRefPolylines = GetPolylines();
323   for ( int i = 1, n = aRefPolylines.Length(); i <= n; ++i ) {
324     Handle(HYDROData_PolylineXY) aPolyline = 
325       Handle(HYDROData_PolylineXY)::DownCast( aRefPolylines.Value( i ) );
326     
327     if ( aPolyline.IsNull() ) {
328       continue;
329     }
330
331     if ( !aPolyline->IsClosed() ) {
332       continue;
333     }
334
335     TopoDS_Shape aPolyShape = aPolyline->GetShape();
336     if ( aPolyShape.IsNull() || aPolyShape.ShapeType() != TopAbs_WIRE ) {
337       continue;
338     }
339
340     const TopoDS_Wire& aPolylineWire = TopoDS::Wire( aPolyShape );
341     if ( aPolylineWire.IsNull() ) {
342       continue;
343     }
344
345     TopoDS_Face aResultFace = TopoDS_Face();
346     BRepBuilderAPI_MakeFace aMakeFace( aPolylineWire, Standard_True );
347     aMakeFace.Build();
348     if( aMakeFace.IsDone() ) {
349       aResultFace = aMakeFace.Face();
350     }
351
352     if( aResultFace.IsNull() ) {
353       continue;
354     }
355
356     if ( anArgShape.IsNull() ) {
357       anArgShape = aResultFace;
358     } else {
359       aToolShapes.Append( aResultFace );
360     }
361   }
362
363   aResShape = anArgShape;
364
365   if ( !anArgShape.IsNull() && aToolShapes.Extent() > 0 ) {
366     Handle(NCollection_BaseAllocator)aAL=new NCollection_IncAllocator;
367     BOPAlgo_BOP aBOP(aAL);
368  
369     aBOP.AddArgument( anArgShape );
370
371     TopTools_ListIteratorOfListOfShape anIt(aToolShapes);
372     for( ; anIt.More(); anIt.Next() ) {
373       aBOP.AddTool( anIt.Value() );
374     }
375
376     aBOP.SetOperation( BOPAlgo_CUT );
377     aBOP.Perform();
378
379     if ( !aBOP.Shape().IsNull() ) {
380       aResShape = aBOP.Shape();
381     }
382   }
383   */
384   
385   return aResShape;
386 }