Salome HOME
Base implementation of Zone data object (Feature #31).
[modules/hydro.git] / src / HYDROData / HYDROData_Polyline.cxx
1 #include <HYDROData_Polyline.h>
2 #include <HYDROData_Iterator.h>
3
4 #include <ImageComposer_MetaTypes.h>
5
6 #include <TDataStd_Name.hxx>
7 #include <TDataStd_Integer.hxx>
8 #include <TDataStd_ByteArray.hxx>
9 #include <TDataStd_BooleanArray.hxx>
10 #include <TDataStd_IntegerArray.hxx>
11 #include <TDataStd_RealArray.hxx>
12 #include <TDataStd_ExtStringArray.hxx>
13 #include <TDataStd_UAttribute.hxx>
14 #include <TDF_ListIteratorOfLabelList.hxx>
15
16 #include <QStringList>
17
18 // tage of the child of my label that contains information about the operator
19 static const Standard_GUID GUID_MUST_BE_UPDATED("6647e1f7-1971-4c5a-86c7-11ff0291452d");
20
21 #define PYTHON_POLYLINE_ID "KIND_POLYLINE"
22
23 IMPLEMENT_STANDARD_HANDLE(HYDROData_Polyline, HYDROData_Object)
24 IMPLEMENT_STANDARD_RTTIEXT(HYDROData_Polyline, HYDROData_Object)
25
26 HYDROData_Polyline::HYDROData_Polyline()
27 {
28 }
29
30 HYDROData_Polyline::~HYDROData_Polyline()
31 {
32 }
33
34 /**
35  * Dump object to Python script representation.
36  */
37 QStringList HYDROData_Polyline::DumpToPython( MapOfTreatedObjects& theTreatedObjects ) const
38 {
39   QStringList aResList;
40
41   Handle(HYDROData_Document) aDocument = HYDROData_Document::Document( this );
42   if ( aDocument.IsNull() )
43     return aResList;
44                              
45   QString aDocName = aDocument->GetDocPyName();
46   QString aPolylineName = GetName();
47
48   aResList << QString( "%1 = %2.CreateObject( %3 );" )
49               .arg( aPolylineName ).arg( aDocName ).arg( PYTHON_POLYLINE_ID );
50   aResList << QString( "%1.SetName( \"%1\" );" ).arg( aPolylineName );
51
52   // Set polilyne dimension
53
54   aResList << QString( "" );
55
56   int aDim = getDimension();
57   aResList << QString( "%1.setDimension( %2 );" )
58               .arg( aPolylineName ).arg( aDim );
59
60   // Set polilyne data
61
62   PolylineData aPolylineData = getPolylineData();
63   if ( !aPolylineData.isEmpty() )
64   {
65     QString aPolylineDataName = "polyline_data";
66
67     aResList << QString( "" );
68     aResList << QString( "%1 = [];" ).arg( aPolylineDataName );
69
70     PolylineData::const_iterator aDataIt = aPolylineData.constBegin();
71     for ( ; aDataIt != aPolylineData.constEnd(); ++aDataIt )
72     {
73       const PolylineSection& aSection = *aDataIt;
74
75       QString aPolylineSectName = "polyline_section";
76
77       aResList << QString( "" );
78       aResList << QString( "%1 = PolylineSection();" ).arg( aPolylineSectName );
79
80       QString aCoordsStr;
81       foreach( const double& aCoordVal, aSection.myCoords )
82         aCoordsStr += QString::number( aCoordVal ) + ", ";
83       aCoordsStr.remove( aCoordsStr.length() - 2, 2 );
84
85       aResList << QString( "" );
86
87       aResList << QString( "%1.mySectionName = \"%2\";" )
88                   .arg( aPolylineSectName )
89                   .arg( TCollection_AsciiString( aSection.mySectionName ).ToCString() );
90       aResList << QString( "%1.myType = %2;" )
91                   .arg( aPolylineSectName ).arg( aSection.myType );
92       aResList << QString( "%1.myIsClosed = %2;" )
93                   .arg( aPolylineSectName ).arg( aSection.myIsClosed );
94       aResList << QString( "%1.myCoords = [ %2 ];" )
95                   .arg( aPolylineSectName ).arg( aCoordsStr );
96
97       aResList << QString( "%1.append( %2 );" )
98                   .arg( aPolylineDataName ).arg( aPolylineSectName );
99     }
100
101     aResList << QString( "%1.setPolylineData( %2 );" )
102                   .arg( aPolylineName ).arg( aPolylineDataName );
103   }
104
105   return aResList;
106 }
107
108 QVariant HYDROData_Polyline::GetDataVariant()
109 {
110   QPainterPath aPath = painterPath();
111
112   QVariant aVarData;
113   aVarData.setValue<QPainterPath>( aPath );
114   
115   return aVarData;
116 }
117
118 /**
119  * Return polyline dimension
120  * \return polyline dimension. 2 or 3 is valid. 0 is invalid.
121  */
122 int HYDROData_Polyline::getDimension() const
123 {
124     Handle(TDataStd_Integer) aDim;
125     if(!myLab.FindAttribute(TDataStd_Integer::GetID(), aDim))
126       return 0;
127     return aDim->Get();
128 }
129
130 /**
131  * Set polyline dimension. Should be 2 or 3.
132  * \param theDimension the polyline dimension
133  */
134 void HYDROData_Polyline::setDimension( int theDimension )
135 {
136     removeAll();
137     int aDim=0;
138     if( theDimension == 2 || theDimension == 3){
139         aDim = theDimension;
140     }
141     TDataStd_Integer::Set(myLab, aDim);
142 }
143
144 /**
145  * Replace current polyline data by new sections list
146  * \param theSections the sections list
147  */
148 void HYDROData_Polyline::setPolylineData( const PolylineData& theSections )
149 {
150 //Keep dimension
151   int aDim = getDimension();
152   if( aDim == 0 )
153       return;
154   removeAll();
155   setDimension(aDim);
156
157   if( theSections.size() == 0 )
158     return;
159   int aSectionsSize = theSections.size();
160
161   int aPointsCnt = 0;
162
163   TDF_Label aNameLab = myLab.FindChild(DataTag_SectionsName);
164   Handle(TDataStd_ExtStringArray) aSectsNameArray;
165   aSectsNameArray = TDataStd_ExtStringArray::Set(aNameLab, 0, aSectionsSize-1, false );
166
167   TDF_Label aSizeLab = myLab.FindChild(DataTag_SectionsSize);
168   Handle(TDataStd_IntegerArray) aSizeArray;
169   aSizeArray = TDataStd_IntegerArray::Set(aSizeLab, 0, aSectionsSize-1, false );
170
171   TDF_Label aClosedLab = myLab.FindChild(DataTag_SectionsClosed);
172   Handle(TDataStd_BooleanArray) aClosedArray;
173   aClosedArray = TDataStd_BooleanArray::Set(aClosedLab, 0, aSectionsSize-1 );
174
175   TDF_Label aTypeLab = myLab.FindChild(DataTag_SectionsType);
176   Handle(TDataStd_ByteArray) aTypeArray;
177   aTypeArray = TDataStd_ByteArray::Set(aTypeLab, 0, aSectionsSize-1, false );
178
179 //Extract sections parameters and count points
180   for( int i = 0 ; i < theSections.size() ; i++ ){
181     int aSectSize = theSections[i].myCoords.size();
182     aSectsNameArray->SetValue( i, theSections[i].mySectionName );
183     aSizeArray->SetValue( i, aSectSize );
184     aClosedArray->SetValue( i, theSections[i].myIsClosed );
185     char aType = (char)theSections[i].myType;
186     aTypeArray->SetValue( i, aType );
187     aPointsCnt += aSectSize;
188   }
189 //Don't create a points array
190   if( aPointsCnt == 0 )
191     return;
192 //Save coordinates
193   Handle(TDataStd_RealArray) anArray;
194   anArray = TDataStd_RealArray::Set( myLab, 0, aPointsCnt*aDim - 1 );
195   int aPtr = 0;
196   for( int i = 0 ; i < theSections.size() ; i++ ){
197     for( int j = 0 ; j < theSections[i].myCoords.size() ; j++ ){
198       anArray->SetValue(aPtr, theSections[i].myCoords[j]);
199       aPtr++;
200     }
201   }
202 }
203
204 /**
205  * Return polyline data
206  * \return polyline section list
207  */
208 HYDROData_Polyline::PolylineData HYDROData_Polyline::getPolylineData() const
209 {
210   int aSectCnt;
211   PolylineData aRes;
212 //Get sections size array handle
213   TDF_Label aLab = myLab.FindChild( DataTag_SectionsSize );
214   Handle(TDataStd_IntegerArray) aSizeArray;
215   if (!aLab.FindAttribute(TDataStd_IntegerArray::GetID(), aSizeArray))
216     return aRes; // return empty if no array
217   aSectCnt = aSizeArray->Length();
218   if( aSectCnt == 0 )
219     return aRes;
220 //Get section type array handle
221   aLab = myLab.FindChild( DataTag_SectionsType );
222   Handle(TDataStd_ByteArray) aTypeArray;
223   if (!aLab.FindAttribute(TDataStd_ByteArray::GetID(), aTypeArray))
224     return aRes;
225   int aLen = aTypeArray->Length();
226   if( aLen != aSectCnt )
227     return aRes;
228 //Get section closed array handle
229   aLab = myLab.FindChild( DataTag_SectionsClosed );
230   Handle(TDataStd_BooleanArray) aClosedArray;
231   if (!aLab.FindAttribute(TDataStd_BooleanArray::GetID(), aClosedArray))
232     return aRes;
233   aLen = aClosedArray->Length();
234   if( aLen != aSectCnt )
235     return aRes;
236 //Get sections names
237   TDF_Label aNameLab = myLab.FindChild(DataTag_SectionsName);
238   Handle(TDataStd_ExtStringArray) aSectNamesArray;
239   if(!aNameLab.FindAttribute(TDataStd_ExtStringArray::GetID(), aSectNamesArray))
240     return aRes;
241   aLen = aSectNamesArray->Length();
242   if( aLen != aSectCnt )
243     return aRes;
244 //Get coordinates array
245   Handle(TDataStd_RealArray) aCoordsArray;
246   myLab.FindAttribute(TDataStd_RealArray::GetID(), aCoordsArray);
247
248   int aCoordPtr = 0;
249   for( int i = 0 ; i < aSectCnt ; i++ ){
250     PolylineSection aSect;
251     aSect.myIsClosed = aClosedArray->Value(i);
252     aSect.myType = (PolylineSection::SectionType)aTypeArray->Value(i);
253     aSect.mySectionName = aSectNamesArray->Value(i);
254     int aSectSize = aSizeArray->Value(i);
255     for( int j = 0 ; j < aSectSize ; j++ ){
256       double aCoord = aCoordsArray->Value(aCoordPtr);
257       aSect.myCoords << aCoord;
258       aCoordPtr++;
259     }
260     aRes << aSect;
261   }
262   return aRes;
263 }
264
265 /**
266  * Returns true if polyline is closed
267  */
268 bool HYDROData_Polyline::isClosed() const
269 {
270   int aDim = getDimension();
271   PolylineData aPolylineData = getPolylineData();
272
273   if ( aDim == 0 || aPolylineData.isEmpty() )
274     return false;
275
276   PolylineData::const_iterator anIt = aPolylineData.constBegin();
277   for ( ; anIt != aPolylineData.constEnd(); ++anIt )
278   {
279     const PolylineSection& aSection = *anIt;
280     if ( !aSection.myIsClosed )
281       return false;
282   }
283
284   return true;
285 }
286
287 /**
288  * Remove all polyline attributes except dimension.
289  */
290 void HYDROData_Polyline::removeAll()
291 {
292 //Remove only section data
293   TDF_Label aLab = myLab.FindChild( DataTag_SectionsSize );
294   aLab.ForgetAllAttributes();
295
296   aLab = myLab.FindChild( DataTag_SectionsType );
297   aLab.ForgetAllAttributes();
298
299   aLab = myLab.FindChild( DataTag_SectionsClosed );
300   aLab.ForgetAllAttributes();
301
302   myLab.ForgetAttribute(TDataStd_RealArray::GetID());
303   return;
304 }
305
306 /**
307  * Return polyline painter path. Current implementation
308  * is ignored section type.
309  * \return polyline painter path.
310  */
311 QPainterPath HYDROData_Polyline::painterPath() const
312 {
313   QPainterPath aPath;
314   int aDim = getDimension();
315   if( ( aDim != 2 ) && ( aDim != 3) )
316       return aPath;
317   PolylineData aSects = getPolylineData();
318   for( int i = 0 ; i < aSects.size() ; i++ ){
319     int aPntCnt = aSects[i].myCoords.size()/aDim;
320     if( aPntCnt ){
321       aPath.moveTo(aSects[i].myCoords[0], aSects[i].myCoords[1] );
322     }
323     for( int j = 1 ; j < aPntCnt ; j++ ){
324       int anIndx = j*aDim;
325       aPath.lineTo(aSects[i].myCoords[anIndx], aSects[i].myCoords[anIndx+1]);
326     }
327     if( aSects[i].myIsClosed ){
328       aPath.closeSubpath();
329     }
330   }
331   return aPath;
332 }