]> SALOME platform Git repositories - modules/hydro.git/blob - src/HYDROData/HYDROData_Polyline.cxx
Salome HOME
Access methods for object groups added.
[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 #include <BRep_Builder.hxx>
27 #include <TopTools_ListIteratorOfListOfShape.hxx>
28
29 #include <QStringList>
30
31 #define PYTHON_POLYLINE_ID "KIND_POLYLINE"
32
33 IMPLEMENT_STANDARD_HANDLE(HYDROData_Polyline, HYDROData_Object)
34 IMPLEMENT_STANDARD_RTTIEXT(HYDROData_Polyline, HYDROData_Object)
35
36 HYDROData_Polyline::HYDROData_Polyline()
37 : HYDROData_Object()
38 {
39 }
40
41 HYDROData_Polyline::~HYDROData_Polyline()
42 {
43 }
44
45 TopoDS_Shape HYDROData_Polyline::GetTopShape() const
46 {
47   // TODO
48   return getTopShape();
49 }
50
51 TopoDS_Shape HYDROData_Polyline::GetShape3D() const
52 {
53   // TODO
54   return getTopShape();
55 }
56
57 /**
58  * Dump object to Python script representation.
59  */
60 QStringList HYDROData_Polyline::DumpToPython( MapOfTreatedObjects& theTreatedObjects ) const
61 {
62   QStringList aResList;
63
64   Handle(HYDROData_Document) aDocument = HYDROData_Document::Document( myLab );
65   if ( aDocument.IsNull() )
66     return aResList;
67                              
68   QString aDocName = aDocument->GetDocPyName();
69   QString aPolylineName = GetName();
70
71   aResList << QString( "%1 = %2.CreateObject( %3 );" )
72               .arg( aPolylineName ).arg( aDocName ).arg( PYTHON_POLYLINE_ID );
73   aResList << QString( "%1.SetName( \"%1\" );" ).arg( aPolylineName );
74
75   // Set polilyne dimension
76
77   aResList << QString( "" );
78
79   int aDim = GetDimension();
80   aResList << QString( "%1.SetDimension( %2 );" )
81               .arg( aPolylineName ).arg( aDim );
82
83   // Set polilyne data
84
85   PolylineData aPolylineData = GetPolylineData();
86   if ( !aPolylineData.isEmpty() )
87   {
88     QString aPolylineDataName = "polyline_data";
89
90     aResList << QString( "" );
91     aResList << QString( "%1 = [];" ).arg( aPolylineDataName );
92
93     PolylineData::const_iterator aDataIt = aPolylineData.constBegin();
94     for ( ; aDataIt != aPolylineData.constEnd(); ++aDataIt )
95     {
96       const PolylineSection& aSection = *aDataIt;
97
98       QString aPolylineSectName = "polyline_section";
99
100       aResList << QString( "" );
101       aResList << QString( "%1 = PolylineSection();" ).arg( aPolylineSectName );
102
103       QString aCoordsStr;
104       foreach( const double& aCoordVal, aSection.myCoords )
105         aCoordsStr += QString::number( aCoordVal ) + ", ";
106       aCoordsStr.remove( aCoordsStr.length() - 2, 2 );
107
108       aResList << QString( "" );
109
110       aResList << QString( "%1.mySectionName = \"%2\";" )
111                   .arg( aPolylineSectName )
112                   .arg( TCollection_AsciiString( aSection.mySectionName ).ToCString() );
113       aResList << QString( "%1.myType = %2;" )
114                   .arg( aPolylineSectName ).arg( aSection.myType );
115       aResList << QString( "%1.myIsClosed = %2;" )
116                   .arg( aPolylineSectName ).arg( aSection.myIsClosed );
117       aResList << QString( "%1.myCoords = [ %2 ];" )
118                   .arg( aPolylineSectName ).arg( aCoordsStr );
119
120       aResList << QString( "%1.append( %2 );" )
121                   .arg( aPolylineDataName ).arg( aPolylineSectName );
122     }
123     aResList << QString( "" );
124
125     aResList << QString( "%1.SetPolylineData( %2 );" )
126                   .arg( aPolylineName ).arg( aPolylineDataName );
127   }
128
129   return aResList;
130 }
131
132 QVariant HYDROData_Polyline::GetDataVariant()
133 {
134   QPainterPath aPath = GetPainterPath();
135
136   QVariant aVarData;
137   aVarData.setValue<QPainterPath>( aPath );
138   
139   return aVarData;
140 }
141
142 /**
143  * Replace current polyline data by new sections list
144  * \param theSections the sections list
145  */
146 void HYDROData_Polyline::SetPolylineData( const PolylineData& theSections )
147 {
148 //Keep dimension
149   int aDim = GetDimension();
150   if( aDim == 0 )
151       return;
152   RemoveAll();
153   SetDimension(aDim);
154
155   if( theSections.size() == 0 )
156     return;
157   int aSectionsSize = theSections.size();
158
159   int aPointsCnt = 0;
160
161   TDF_Label aNameLab = myLab.FindChild(DataTag_SectionsName);
162   Handle(TDataStd_ExtStringArray) aSectsNameArray;
163   aSectsNameArray = TDataStd_ExtStringArray::Set(aNameLab, 0, aSectionsSize-1, false );
164
165   TDF_Label aSizeLab = myLab.FindChild(DataTag_SectionsSize);
166   Handle(TDataStd_IntegerArray) aSizeArray;
167   aSizeArray = TDataStd_IntegerArray::Set(aSizeLab, 0, aSectionsSize-1, false );
168
169   TDF_Label aClosedLab = myLab.FindChild(DataTag_SectionsClosed);
170   Handle(TDataStd_BooleanArray) aClosedArray;
171   aClosedArray = TDataStd_BooleanArray::Set(aClosedLab, 0, aSectionsSize-1 );
172
173   TDF_Label aTypeLab = myLab.FindChild(DataTag_SectionsType);
174   Handle(TDataStd_ByteArray) aTypeArray;
175   aTypeArray = TDataStd_ByteArray::Set(aTypeLab, 0, aSectionsSize-1, false );
176
177 //Extract sections parameters and count points
178   for( int i = 0 ; i < theSections.size() ; i++ ){
179     int aSectSize = theSections[i].myCoords.size();
180     aSectsNameArray->SetValue( i, theSections[i].mySectionName );
181     aSizeArray->SetValue( i, aSectSize );
182     aClosedArray->SetValue( i, theSections[i].myIsClosed );
183     char aType = (char)theSections[i].myType;
184     aTypeArray->SetValue( i, aType );
185     aPointsCnt += aSectSize;
186   }
187 //Don't create a points array
188   if( aPointsCnt == 0 )
189     return;
190 //Save coordinates
191   Handle(TDataStd_RealArray) anArray;
192   anArray = TDataStd_RealArray::Set( myLab, 0, aPointsCnt*aDim - 1 );
193   int aPtr = 0;
194   for( int i = 0 ; i < theSections.size() ; i++ ){
195     for( int j = 0 ; j < theSections[i].myCoords.size() ; j++ ){
196       anArray->SetValue(aPtr, theSections[i].myCoords[j]);
197       aPtr++;
198     }
199   }
200
201   UpdateWire( theSections );
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  * Return polyline dimension
289  * \return polyline dimension. 2 or 3 is valid. 0 is invalid.
290  */
291 int HYDROData_Polyline::GetDimension() const
292 {
293     Handle(TDataStd_Integer) aDim;
294     if(!myLab.FindAttribute(TDataStd_Integer::GetID(), aDim))
295       return 0;
296     return aDim->Get();
297 }
298
299 /**
300  * Set polyline dimension. Should be 2 or 3.
301  * \param theDimension the polyline dimension
302  */
303 void HYDROData_Polyline::SetDimension( int theDimension )
304 {
305     RemoveAll();
306     int aDim=0;
307     if( theDimension == 2 || theDimension == 3){
308         aDim = theDimension;
309     }
310     TDataStd_Integer::Set(myLab, aDim);
311 }
312
313 /**
314  * Remove all polyline attributes except dimension.
315  */
316 void HYDROData_Polyline::RemoveAll()
317 {
318 //Remove only section data
319   TDF_Label aLab = myLab.FindChild( DataTag_SectionsSize );
320   aLab.ForgetAllAttributes();
321
322   aLab = myLab.FindChild( DataTag_SectionsType );
323   aLab.ForgetAllAttributes();
324
325   aLab = myLab.FindChild( DataTag_SectionsClosed );
326   aLab.ForgetAllAttributes();
327
328   myLab.ForgetAttribute(TDataStd_RealArray::GetID());
329   return;
330 }
331
332 /**
333  * Returns the painter path.
334  * Note: currently only the first section of the polyline data is taken into account.
335  * \return polyline painter path.
336  */
337 QPainterPath HYDROData_Polyline::GetPainterPath() const
338 {
339   QPainterPath aPath;
340   int aDim = GetDimension();
341   if( aDim != 2 && aDim != 3 )
342     return aPath;
343
344   PolylineData aSects = GetPolylineData();
345   if( aSects.isEmpty() )
346     return aPath;
347
348   PolylineSection aSection = aSects.first();
349   int aPntCount = aSection.myCoords.size() / aDim;
350   PolylineSection::SectionType aSectionType = aSection.myType;
351   bool anIsSectionClosed = aSection.myIsClosed;
352   if( aSectionType == PolylineSection::SECTION_POLYLINE )
353   {
354     if( aPntCount )
355       aPath.moveTo( aSection.myCoords[0], aSection.myCoords[1] );
356     for( int i = 1; i < aPntCount; i++ )
357     {
358       int anIndex = i * aDim;
359       aPath.lineTo( aSection.myCoords[ anIndex ], aSection.myCoords[ anIndex + 1 ] );
360     }
361     if( anIsSectionClosed )
362       aPath.closeSubpath();
363   }
364   else //if( aSectionType == PolylineSection::SECTION_SPLINE )
365   {
366     QList<double> aPoints;
367     for( int i = 0; i < aPntCount; i++ )
368     {
369       int anIndex = i * aDim;
370       aPoints << aSection.myCoords[ anIndex ] << aSection.myCoords[ anIndex + 1 ];
371     }
372     HYDROData_BSplineOperation aBSpline( aPoints, 0, anIsSectionClosed );
373     aPath = aBSpline.ComputePath();
374   }
375   return aPath;
376 }
377
378 void HYDROData_Polyline::SetZValue( const double theZValue )
379 {
380   TDataStd_Real::Set(myLab.FindChild(DataTag_ZValue), theZValue);
381 }
382
383 double HYDROData_Polyline::ZValue() const
384 {
385   Handle(TDataStd_Real) aZValue;
386   if(myLab.FindChild(DataTag_ZValue).FindAttribute(TDataStd_Real::GetID(), aZValue))
387     return aZValue->Get();
388   return 0;
389 }
390
391 void HYDROData_Polyline::UpdateWire( const PolylineData& theSections )
392 {
393   BRepBuilderAPI_MakeWire aMakeWire;
394
395   int aDim = GetDimension();
396
397   double aZValue = ZValue();
398
399   TopTools_ListOfShape aSectionWiresList;
400
401   int aSectionCount = theSections.size();
402   for( int aSectionId = 0; aSectionId < aSectionCount; aSectionId++ )
403   {
404     const PolylineSection& aSection = theSections[ aSectionId ];
405     PolylineSection::SectionType aSectionType = aSection.myType;
406     bool anIsSectionClosed = aSection.myIsClosed;
407     int aPointCount = aSection.myCoords.size() / aDim;
408     if( aPointCount > 1 )
409     {
410       BRepBuilderAPI_MakeWire aMakeSectionWire;
411       if( aSectionType == PolylineSection::SECTION_POLYLINE )
412       {
413         for( int aPointId = 0; aPointId < aPointCount; aPointId++ )
414         {
415           int anId1 = aDim * aPointId;
416           int anId2 = aDim * ( aPointId + 1 );
417           if( aPointId == aPointCount - 1 )
418           {
419             if( anIsSectionClosed )
420               anId2 = 0;
421             else
422               break;
423           }
424
425           gp_Pnt aPnt1( aSection.myCoords[ anId1 ], aSection.myCoords[ anId1 + 1 ], aZValue );
426           gp_Pnt aPnt2( aSection.myCoords[ anId2 ], aSection.myCoords[ anId2 + 1 ], aZValue );
427
428           TopoDS_Edge anEdge = BRepBuilderAPI_MakeEdge( aPnt1, aPnt2 ).Edge();
429           aMakeSectionWire.Add( anEdge );
430         }
431       }
432       else //if( aSectionType == PolylineSection::SECTION_SPLINE )
433       {
434         QList<double> aPoints;
435         for( int aPointId = 0; aPointId < aPointCount; aPointId++ )
436         {
437           int anId = aPointId * aDim;
438           double x = aSection.myCoords[ anId ];
439           double y = aSection.myCoords[ anId+1 ];
440           aPoints << x << y;
441         }
442
443         HYDROData_BSplineOperation aBSpline( aPoints, aZValue, anIsSectionClosed );
444         TopoDS_Edge anEdge = BRepBuilderAPI_MakeEdge( aBSpline.Curve() ).Edge();
445         aMakeSectionWire.Add( anEdge );
446       }
447       TopoDS_Wire aSectionWire = aMakeSectionWire.Wire();
448       aSectionWiresList.Append( aSectionWire );
449       aMakeWire.Add( aSectionWire );
450     }
451   }
452
453   TopoDS_Shape aShape;
454   if ( aMakeWire.IsDone() ) {
455     aShape = aMakeWire.Shape();
456   } else {
457     // build compound
458     TopoDS_Compound aCompound;
459     BRep_Builder aBuilder;
460     aBuilder.MakeCompound( aCompound );
461     TopTools_ListIteratorOfListOfShape anIter( aSectionWiresList );
462     for ( ; anIter.More(); anIter.Next() ) {
463       aBuilder.Add( aCompound, anIter.Value() );
464     }
465     aShape = aCompound;
466   }
467
468   SetTopShape( aShape );
469 }