Salome HOME
Useless method has been removed.
[modules/hydro.git] / src / HYDROData / HYDROData_Polyline.cxx
1 #include <HYDROData_Polyline.h>
2 #include <HYDROData_Iterator.h>
3
4 #include <HYDROData_BSplineOperation.h>
5
6 #include <ImageComposer_MetaTypes.h>
7
8 #include <BRepBuilderAPI_MakeEdge.hxx>
9 #include <BRepBuilderAPI_MakeWire.hxx>
10 #include <gp_Pnt.hxx>
11 #include <TDataStd_Name.hxx>
12 #include <TDataStd_Integer.hxx>
13 #include <TDataStd_ByteArray.hxx>
14 #include <TDataStd_BooleanArray.hxx>
15 #include <TDataStd_IntegerArray.hxx>
16 #include <TDataStd_Real.hxx>
17 #include <TDataStd_RealArray.hxx>
18 #include <TDataStd_ExtStringArray.hxx>
19 #include <TDataStd_UAttribute.hxx>
20 #include <TDF_ListIteratorOfLabelList.hxx>
21 #include <TNaming_Builder.hxx>
22 #include <TNaming_NamedShape.hxx>
23 #include <TopoDS.hxx>
24 #include <TopoDS_Edge.hxx>
25 #include <TopoDS_Wire.hxx>
26
27 #include <QStringList>
28
29 // tage of the child of my label that contains information about the operator
30 static const Standard_GUID GUID_MUST_BE_UPDATED("6647e1f7-1971-4c5a-86c7-11ff0291452d");
31
32 #define PYTHON_POLYLINE_ID "KIND_POLYLINE"
33
34 IMPLEMENT_STANDARD_HANDLE(HYDROData_Polyline, HYDROData_Object)
35 IMPLEMENT_STANDARD_RTTIEXT(HYDROData_Polyline, HYDROData_Object)
36
37 HYDROData_Polyline::HYDROData_Polyline()
38 : HYDROData_Object()
39 {
40 }
41
42 HYDROData_Polyline::~HYDROData_Polyline()
43 {
44 }
45
46 TopoDS_Shape HYDROData_Polyline::GetTopShape() const
47 {
48   // TODO
49   return getTopShape();
50 }
51
52 TopoDS_Shape HYDROData_Polyline::GetShape3D() const
53 {
54   // TODO
55   return getTopShape();
56 }
57
58 /**
59  * Dump object to Python script representation.
60  */
61 QStringList HYDROData_Polyline::DumpToPython( MapOfTreatedObjects& theTreatedObjects ) const
62 {
63   QStringList aResList;
64
65   Handle(HYDROData_Document) aDocument = HYDROData_Document::Document( this );
66   if ( aDocument.IsNull() )
67     return aResList;
68                              
69   QString aDocName = aDocument->GetDocPyName();
70   QString aPolylineName = GetName();
71
72   aResList << QString( "%1 = %2.CreateObject( %3 );" )
73               .arg( aPolylineName ).arg( aDocName ).arg( PYTHON_POLYLINE_ID );
74   aResList << QString( "%1.SetName( \"%1\" );" ).arg( aPolylineName );
75
76   // Set polilyne dimension
77
78   aResList << QString( "" );
79
80   int aDim = GetDimension();
81   aResList << QString( "%1.SetDimension( %2 );" )
82               .arg( aPolylineName ).arg( aDim );
83
84   // Set polilyne data
85
86   PolylineData aPolylineData = GetPolylineData();
87   if ( !aPolylineData.isEmpty() )
88   {
89     QString aPolylineDataName = "polyline_data";
90
91     aResList << QString( "" );
92     aResList << QString( "%1 = [];" ).arg( aPolylineDataName );
93
94     PolylineData::const_iterator aDataIt = aPolylineData.constBegin();
95     for ( ; aDataIt != aPolylineData.constEnd(); ++aDataIt )
96     {
97       const PolylineSection& aSection = *aDataIt;
98
99       QString aPolylineSectName = "polyline_section";
100
101       aResList << QString( "" );
102       aResList << QString( "%1 = PolylineSection();" ).arg( aPolylineSectName );
103
104       QString aCoordsStr;
105       foreach( const double& aCoordVal, aSection.myCoords )
106         aCoordsStr += QString::number( aCoordVal ) + ", ";
107       aCoordsStr.remove( aCoordsStr.length() - 2, 2 );
108
109       aResList << QString( "" );
110
111       aResList << QString( "%1.mySectionName = \"%2\";" )
112                   .arg( aPolylineSectName )
113                   .arg( TCollection_AsciiString( aSection.mySectionName ).ToCString() );
114       aResList << QString( "%1.myType = %2;" )
115                   .arg( aPolylineSectName ).arg( aSection.myType );
116       aResList << QString( "%1.myIsClosed = %2;" )
117                   .arg( aPolylineSectName ).arg( aSection.myIsClosed );
118       aResList << QString( "%1.myCoords = [ %2 ];" )
119                   .arg( aPolylineSectName ).arg( aCoordsStr );
120
121       aResList << QString( "%1.append( %2 );" )
122                   .arg( aPolylineDataName ).arg( aPolylineSectName );
123     }
124     aResList << QString( "" );
125
126     aResList << QString( "%1.SetPolylineData( %2 );" )
127                   .arg( aPolylineName ).arg( aPolylineDataName );
128   }
129
130   return aResList;
131 }
132
133 QVariant HYDROData_Polyline::GetDataVariant()
134 {
135   QPainterPath aPath = GetPainterPath();
136
137   QVariant aVarData;
138   aVarData.setValue<QPainterPath>( aPath );
139   
140   return aVarData;
141 }
142
143 /**
144  * Replace current polyline data by new sections list
145  * \param theSections the sections list
146  */
147 void HYDROData_Polyline::SetPolylineData( const PolylineData& theSections )
148 {
149 //Keep dimension
150   int aDim = GetDimension();
151   if( aDim == 0 )
152       return;
153   RemoveAll();
154   SetDimension(aDim);
155
156   if( theSections.size() == 0 )
157     return;
158   int aSectionsSize = theSections.size();
159
160   int aPointsCnt = 0;
161
162   TDF_Label aNameLab = myLab.FindChild(DataTag_SectionsName);
163   Handle(TDataStd_ExtStringArray) aSectsNameArray;
164   aSectsNameArray = TDataStd_ExtStringArray::Set(aNameLab, 0, aSectionsSize-1, false );
165
166   TDF_Label aSizeLab = myLab.FindChild(DataTag_SectionsSize);
167   Handle(TDataStd_IntegerArray) aSizeArray;
168   aSizeArray = TDataStd_IntegerArray::Set(aSizeLab, 0, aSectionsSize-1, false );
169
170   TDF_Label aClosedLab = myLab.FindChild(DataTag_SectionsClosed);
171   Handle(TDataStd_BooleanArray) aClosedArray;
172   aClosedArray = TDataStd_BooleanArray::Set(aClosedLab, 0, aSectionsSize-1 );
173
174   TDF_Label aTypeLab = myLab.FindChild(DataTag_SectionsType);
175   Handle(TDataStd_ByteArray) aTypeArray;
176   aTypeArray = TDataStd_ByteArray::Set(aTypeLab, 0, aSectionsSize-1, false );
177
178 //Extract sections parameters and count points
179   for( int i = 0 ; i < theSections.size() ; i++ ){
180     int aSectSize = theSections[i].myCoords.size();
181     aSectsNameArray->SetValue( i, theSections[i].mySectionName );
182     aSizeArray->SetValue( i, aSectSize );
183     aClosedArray->SetValue( i, theSections[i].myIsClosed );
184     char aType = (char)theSections[i].myType;
185     aTypeArray->SetValue( i, aType );
186     aPointsCnt += aSectSize;
187   }
188 //Don't create a points array
189   if( aPointsCnt == 0 )
190     return;
191 //Save coordinates
192   Handle(TDataStd_RealArray) anArray;
193   anArray = TDataStd_RealArray::Set( myLab, 0, aPointsCnt*aDim - 1 );
194   int aPtr = 0;
195   for( int i = 0 ; i < theSections.size() ; i++ ){
196     for( int j = 0 ; j < theSections[i].myCoords.size() ; j++ ){
197       anArray->SetValue(aPtr, theSections[i].myCoords[j]);
198       aPtr++;
199     }
200   }
201
202   UpdateWire( theSections );
203 }
204
205 /**
206  * Return polyline data
207  * \return polyline section list
208  */
209 HYDROData_Polyline::PolylineData HYDROData_Polyline::GetPolylineData() const
210 {
211   int aSectCnt;
212   PolylineData aRes;
213 //Get sections size array handle
214   TDF_Label aLab = myLab.FindChild( DataTag_SectionsSize );
215   Handle(TDataStd_IntegerArray) aSizeArray;
216   if (!aLab.FindAttribute(TDataStd_IntegerArray::GetID(), aSizeArray))
217     return aRes; // return empty if no array
218   aSectCnt = aSizeArray->Length();
219   if( aSectCnt == 0 )
220     return aRes;
221 //Get section type array handle
222   aLab = myLab.FindChild( DataTag_SectionsType );
223   Handle(TDataStd_ByteArray) aTypeArray;
224   if (!aLab.FindAttribute(TDataStd_ByteArray::GetID(), aTypeArray))
225     return aRes;
226   int aLen = aTypeArray->Length();
227   if( aLen != aSectCnt )
228     return aRes;
229 //Get section closed array handle
230   aLab = myLab.FindChild( DataTag_SectionsClosed );
231   Handle(TDataStd_BooleanArray) aClosedArray;
232   if (!aLab.FindAttribute(TDataStd_BooleanArray::GetID(), aClosedArray))
233     return aRes;
234   aLen = aClosedArray->Length();
235   if( aLen != aSectCnt )
236     return aRes;
237 //Get sections names
238   TDF_Label aNameLab = myLab.FindChild(DataTag_SectionsName);
239   Handle(TDataStd_ExtStringArray) aSectNamesArray;
240   if(!aNameLab.FindAttribute(TDataStd_ExtStringArray::GetID(), aSectNamesArray))
241     return aRes;
242   aLen = aSectNamesArray->Length();
243   if( aLen != aSectCnt )
244     return aRes;
245 //Get coordinates array
246   Handle(TDataStd_RealArray) aCoordsArray;
247   myLab.FindAttribute(TDataStd_RealArray::GetID(), aCoordsArray);
248
249   int aCoordPtr = 0;
250   for( int i = 0 ; i < aSectCnt ; i++ ){
251     PolylineSection aSect;
252     aSect.myIsClosed = aClosedArray->Value(i);
253     aSect.myType = (PolylineSection::SectionType)aTypeArray->Value(i);
254     aSect.mySectionName = aSectNamesArray->Value(i);
255     int aSectSize = aSizeArray->Value(i);
256     for( int j = 0 ; j < aSectSize ; j++ ){
257       double aCoord = aCoordsArray->Value(aCoordPtr);
258       aSect.myCoords << aCoord;
259       aCoordPtr++;
260     }
261     aRes << aSect;
262   }
263   return aRes;
264 }
265
266 /**
267  * Returns true if polyline is closed
268  */
269 bool HYDROData_Polyline::IsClosed() const
270 {
271   int aDim = GetDimension();
272   PolylineData aPolylineData = GetPolylineData();
273
274   if ( aDim == 0 || aPolylineData.isEmpty() )
275     return false;
276
277   PolylineData::const_iterator anIt = aPolylineData.constBegin();
278   for ( ; anIt != aPolylineData.constEnd(); ++anIt )
279   {
280     const PolylineSection& aSection = *anIt;
281     if ( !aSection.myIsClosed )
282       return false;
283   }
284
285   return true;
286 }
287
288 /**
289  * Return polyline dimension
290  * \return polyline dimension. 2 or 3 is valid. 0 is invalid.
291  */
292 int HYDROData_Polyline::GetDimension() const
293 {
294     Handle(TDataStd_Integer) aDim;
295     if(!myLab.FindAttribute(TDataStd_Integer::GetID(), aDim))
296       return 0;
297     return aDim->Get();
298 }
299
300 /**
301  * Set polyline dimension. Should be 2 or 3.
302  * \param theDimension the polyline dimension
303  */
304 void HYDROData_Polyline::SetDimension( int theDimension )
305 {
306     RemoveAll();
307     int aDim=0;
308     if( theDimension == 2 || theDimension == 3){
309         aDim = theDimension;
310     }
311     TDataStd_Integer::Set(myLab, aDim);
312 }
313
314 /**
315  * Remove all polyline attributes except dimension.
316  */
317 void HYDROData_Polyline::RemoveAll()
318 {
319 //Remove only section data
320   TDF_Label aLab = myLab.FindChild( DataTag_SectionsSize );
321   aLab.ForgetAllAttributes();
322
323   aLab = myLab.FindChild( DataTag_SectionsType );
324   aLab.ForgetAllAttributes();
325
326   aLab = myLab.FindChild( DataTag_SectionsClosed );
327   aLab.ForgetAllAttributes();
328
329   myLab.ForgetAttribute(TDataStd_RealArray::GetID());
330   return;
331 }
332
333 /**
334  * Returns the painter path.
335  * Note: currently only the first section of the polyline data is taken into account.
336  * \return polyline painter path.
337  */
338 QPainterPath HYDROData_Polyline::GetPainterPath() const
339 {
340   QPainterPath aPath;
341   int aDim = GetDimension();
342   if( aDim != 2 && aDim != 3 )
343     return aPath;
344
345   PolylineData aSects = GetPolylineData();
346   if( aSects.isEmpty() )
347     return aPath;
348
349   PolylineSection aSection = aSects.first();
350   int aPntCount = aSection.myCoords.size() / aDim;
351   PolylineSection::SectionType aSectionType = aSection.myType;
352   bool anIsSectionClosed = aSection.myIsClosed;
353   if( aSectionType == PolylineSection::SECTION_POLYLINE )
354   {
355     if( aPntCount )
356       aPath.moveTo( aSection.myCoords[0], aSection.myCoords[1] );
357     for( int i = 1; i < aPntCount; i++ )
358     {
359       int anIndex = i * aDim;
360       aPath.lineTo( aSection.myCoords[ anIndex ], aSection.myCoords[ anIndex + 1 ] );
361     }
362     if( anIsSectionClosed )
363       aPath.closeSubpath();
364   }
365   else //if( aSectionType == PolylineSection::SECTION_SPLINE )
366   {
367     QList<double> aPoints;
368     for( int i = 0; i < aPntCount; i++ )
369     {
370       int anIndex = i * aDim;
371       aPoints << aSection.myCoords[ anIndex ] << aSection.myCoords[ anIndex + 1 ];
372     }
373     HYDROData_BSplineOperation aBSpline( aPoints, 0, anIsSectionClosed );
374     aPath = aBSpline.ComputePath();
375   }
376   return aPath;
377 }
378
379 void HYDROData_Polyline::SetZValue( const double theZValue )
380 {
381   TDataStd_Real::Set(myLab.FindChild(DataTag_ZValue), theZValue);
382 }
383
384 double HYDROData_Polyline::ZValue() const
385 {
386   Handle(TDataStd_Real) aZValue;
387   if(myLab.FindChild(DataTag_ZValue).FindAttribute(TDataStd_Real::GetID(), aZValue))
388     return aZValue->Get();
389   return 0;
390 }
391
392 void HYDROData_Polyline::UpdateWire( const PolylineData& theSections )
393 {
394   BRepBuilderAPI_MakeWire aMakeWire;
395
396   int aDim = GetDimension();
397
398   double aZValue = ZValue();
399
400   int aSectionCount = theSections.size();
401   for( int aSectionId = 0; aSectionId < aSectionCount; aSectionId++ )
402   {
403     const PolylineSection& aSection = theSections[ aSectionId ];
404     PolylineSection::SectionType aSectionType = aSection.myType;
405     bool anIsSectionClosed = aSection.myIsClosed;
406     int aPointCount = aSection.myCoords.size() / aDim;
407     if( aPointCount > 1 )
408     {
409       BRepBuilderAPI_MakeWire aMakeSectionWire;
410       if( aSectionType == PolylineSection::SECTION_POLYLINE )
411       {
412         for( int aPointId = 0; aPointId < aPointCount; aPointId++ )
413         {
414           int anId1 = aDim * aPointId;
415           int anId2 = aDim * ( aPointId + 1 );
416           if( aPointId == aPointCount - 1 )
417           {
418             if( anIsSectionClosed )
419               anId2 = 0;
420             else
421               break;
422           }
423
424           gp_Pnt aPnt1( aSection.myCoords[ anId1 ], aSection.myCoords[ anId1 + 1 ], aZValue );
425           gp_Pnt aPnt2( aSection.myCoords[ anId2 ], aSection.myCoords[ anId2 + 1 ], aZValue );
426
427           TopoDS_Edge anEdge = BRepBuilderAPI_MakeEdge( aPnt1, aPnt2 ).Edge();
428           aMakeSectionWire.Add( anEdge );
429         }
430       }
431       else //if( aSectionType == PolylineSection::SECTION_SPLINE )
432       {
433         QList<double> aPoints;
434         for( int aPointId = 0; aPointId < aPointCount; aPointId++ )
435         {
436           int anId = aPointId * aDim;
437           double x = aSection.myCoords[ anId ];
438           double y = aSection.myCoords[ anId+1 ];
439           aPoints << x << y;
440         }
441
442         HYDROData_BSplineOperation aBSpline( aPoints, aZValue, anIsSectionClosed );
443         TopoDS_Edge anEdge = BRepBuilderAPI_MakeEdge( aBSpline.Curve() ).Edge();
444         aMakeSectionWire.Add( anEdge );
445       }
446       TopoDS_Wire aSectionWire = aMakeSectionWire.Wire();
447       aMakeWire.Add( aSectionWire );
448     }
449   }
450
451   TopoDS_Wire aWire = aMakeWire.Wire();
452   SetTopShape( aWire );
453 }