Salome HOME
ca01c6555c646d0b7083e3a118b7a871688941f8
[modules/hydro.git] / src / HYDROData / HYDROData_Image.cxx
1
2 #include "HYDROData_Image.h"
3
4 #include "HYDROData_Document.h"
5 #include "HYDROData_Tool.h"
6 #include "HYDROData_OperationsFactory.h"
7
8 #include <TDataStd_RealArray.hxx>
9 #include <TDataStd_ByteArray.hxx>
10 #include <TDataStd_Integer.hxx>
11 #include <TDataStd_IntegerArray.hxx>
12 #include <TDataStd_ReferenceList.hxx>
13 #include <TDataStd_Name.hxx>
14 #include <TDataStd_UAttribute.hxx>
15 #include <TDataStd_AsciiString.hxx>
16
17 #include <ImageComposer_Operator.h>
18 #include <ImageComposer_MetaTypes.h>
19
20 #include <QStringList>
21
22 static const Standard_GUID GUID_MUST_BE_UPDATED("80f2bb81-3873-4631-8ddd-940d2119f000");
23 static const Standard_GUID GUID_SELF_SPLITTED("997995aa-5c19-40bf-9a60-ab4b70ad04d8");
24
25 #define PYTHON_IMAGE_ID "KIND_IMAGE"
26
27 IMPLEMENT_STANDARD_HANDLE(HYDROData_Image, HYDROData_Entity)
28 IMPLEMENT_STANDARD_RTTIEXT(HYDROData_Image, HYDROData_Entity)
29
30 HYDROData_Image::HYDROData_Image()
31 : HYDROData_Entity()
32 {
33 }
34
35 HYDROData_Image::~HYDROData_Image()
36 {
37 }
38
39 QStringList HYDROData_Image::DumpToPython( MapOfTreatedObjects& theTreatedObjects ) const
40 {
41   QStringList aResList;
42
43   Handle(HYDROData_Document) aDocument = HYDROData_Document::Document( this );
44   if ( aDocument.IsNull() )
45     return aResList;
46                              
47   QString aDocName = aDocument->GetDocPyName();
48   QString anImageName = GetName();
49
50   aResList << QString( "%1 = %2.CreateObject( %3 );" )
51               .arg( anImageName ).arg( aDocName ).arg( PYTHON_IMAGE_ID );
52   aResList << QString( "%1.SetName( \"%2\" );" )
53               .arg( anImageName ).arg( anImageName );
54
55   QString aFilePath = GetFilePath();
56   if ( !aFilePath.isEmpty() )
57   {
58     aResList << QString( "" );
59     aResList << QString( "%1.LoadImage( \"%2\" );" )
60                 .arg( anImageName ).arg( aFilePath );
61
62     // Dump transformation matrix for image
63     aResList << QString( "" );
64
65     QTransform aTrsf = Trsf();
66
67     aResList << QString( "trsf = QTransform( %1, %2, %3," )
68                 .arg( aTrsf.m11() ).arg( aTrsf.m12() ).arg( aTrsf.m13() );
69     aResList << QString( "                   %1, %2, %3," )
70                 .arg( aTrsf.m21() ).arg( aTrsf.m22() ).arg( aTrsf.m23() );
71     aResList << QString( "                   %1, %2, %3 );" )
72                 .arg( aTrsf.m31() ).arg( aTrsf.m32() ).arg( aTrsf.m33() );
73
74     aResList << QString( "%1.SetTrsf( trsf );" ).arg( anImageName );
75
76     // Dump transformation points for image
77     aResList << QString( "" );
78
79     QPoint aPointA, aPointB, aPointC;
80     QPointF aLambertPointA, aLambertPointB, aLambertPointC;
81     QPointF aCartesianPointA, aCartesianPointB, aCartesianPointC;
82     TrsfPoints( aPointA, aPointB, aPointC,
83                 aLambertPointA, aLambertPointB, aLambertPointC,
84                 aCartesianPointA, aCartesianPointB, aCartesianPointC );
85
86     aResList << QString( "pa = QPoint( %1, %2 );" )
87                 .arg( aPointA.x() ).arg( aPointA.y() );
88
89     aResList << QString( "pb = QPoint( %1, %2 );" )
90                 .arg( aPointB.x() ).arg( aPointB.y() );
91
92     aResList << QString( "pc = QPoint( %1, %2 );" )
93                 .arg( aPointC.x() ).arg( aPointC.y() );
94
95     aResList << QString( "lpa = QPointF( %1, %2 );" )
96                 .arg( aLambertPointA.x() ).arg( aLambertPointA.y() );
97
98     aResList << QString( "lpb = QPointF( %1, %2 );" )
99                 .arg( aLambertPointB.x() ).arg( aLambertPointB.y() );
100
101     aResList << QString( "lpc = QPointF( %1, %2 );" )
102                 .arg( aLambertPointC.x() ).arg( aLambertPointC.y() );
103
104     aResList << QString( "cpa = QPointF( %1, %2 );" )
105                 .arg( aCartesianPointA.x() ).arg( aCartesianPointA.y() );
106
107     aResList << QString( "cpb = QPointF( %1, %2 );" )
108                 .arg( aCartesianPointB.x() ).arg( aCartesianPointB.y() );
109
110     aResList << QString( "cpc = QPointF( %1, %2 );" )
111                 .arg( aCartesianPointC.x() ).arg( aCartesianPointC.y() );
112
113     QString aGap = QString().fill( ' ', anImageName.size() + 16 );
114     aResList << QString( "%1.SetTrsfPoints( pa,  pb,  pc," ).arg( anImageName );
115     aResList << QString( aGap            + "lpa, lpb, lpc," );
116     aResList << QString( aGap            + "cpa, cpb, cpc );" );
117   }
118   else
119   {
120     // Image is composed from other image(s)
121
122     QString anOperatorName = OperatorName();
123     if ( !anOperatorName.isEmpty() )
124     {
125       aResList << QString( "" );
126
127       aResList << QString( "%1.SetOperatorName( \"%2\" );" )
128                   .arg( anImageName ).arg( anOperatorName );
129
130       ImageComposer_Operator* anImageOp = HYDROData_OperationsFactory::Factory()->Operator( this );
131       if ( anImageOp )
132       {
133         // Dump operation arguments
134         QString anOpArgsArrayName;
135         QStringList anOpArgs = anImageOp->dumpArgsToPython( anOpArgsArrayName );
136         if ( !anOpArgs.isEmpty() )
137         {
138           aResList << QString( "" );
139           aResList << anOpArgs;
140
141           aResList << QString( "" );
142           aResList << QString( "%1.SetArgs( %2 );" )
143                       .arg( anImageName ).arg( anOpArgsArrayName );
144         }
145       }
146     }
147     
148     int aNbReferences = NbReferences();
149     if ( aNbReferences > 0 )
150     {
151       aResList << QString( "" );
152
153       for ( int i = 0; i < aNbReferences; ++i )
154       {
155         Handle(HYDROData_Image) aRefImg = Handle(HYDROData_Image)::DownCast( Reference( i ) );
156         setPythonReferenceObject( theTreatedObjects, aResList, aRefImg, "AppendReference" );
157       }
158     }
159
160     // Necessary to update image in case of composed operator
161     aResList << QString( "" );
162     aResList << QString( "%1.Update( False );" ).arg( anImageName );
163   }
164
165   return aResList;
166 }
167
168 void HYDROData_Image::Update( const bool theIsForce )
169 {
170   HYDROData_OperationsFactory* aFactory = HYDROData_OperationsFactory::Factory();
171
172   // Update image only if there is an operation
173   ImageComposer_Operator* anOp = aFactory->Operator( OperatorName() );
174   if ( anOp ) 
175   {
176     // Fill by arguments and process the operation
177     QVariant anObj1, anObj2;
178     int aNbReferences = NbReferences();
179
180     if ( aNbReferences > 0 )
181     {
182       // First referenced object
183       Handle(HYDROData_Entity) aRefObj = Reference( 0 );
184       if ( !aRefObj.IsNull() )
185       {
186         anObj1 = aRefObj->GetDataVariant();
187         if ( !anObj1.isNull() && anObj1.canConvert<ImageComposer_Image>() )
188         {
189           ImageComposer_Image anImage = anObj1.value<ImageComposer_Image>();
190           QTransform aTransform = anImage.transform();
191           SetTrsf( aTransform );
192         }
193       }
194     }
195
196     if ( aNbReferences > 1 )
197     {
198       // Second referenced object
199       Handle(HYDROData_Entity) aRefObj = Reference( 1 );
200       if ( !aRefObj.IsNull() )
201         anObj2 = aRefObj->GetDataVariant();
202     }
203
204     ImageComposer_Image aResImg = anOp->process( anObj1, anObj2 );
205     SetImage( aResImg );
206   }
207
208   if ( theIsForce )
209   {
210     Handle(HYDROData_Document) aDocument = HYDROData_Document::Document( this );
211     if ( !aDocument.IsNull() )
212     {
213       // Change the states of this and all depended images
214       MustBeUpdated( true );
215       HYDROData_Tool::SetMustBeUpdatedImages( aDocument );
216       MustBeUpdated( false );
217     }
218   }
219 }
220
221 QVariant HYDROData_Image::GetDataVariant()
222 {
223   QTransform aTransform = Trsf();
224
225   ImageComposer_Image anImage = Image();
226   anImage.setTransform( aTransform );
227
228   QVariant aVarData;
229   aVarData.setValue<ImageComposer_Image>( anImage );
230   
231   return aVarData;
232 }
233
234 void HYDROData_Image::SetImage(const QImage& theImage)
235 {
236   if (theImage.isNull()) {
237     // for empty image remove all previously stored attributes
238     myLab.ForgetAttribute(TDataStd_IntegerArray::GetID());
239     myLab.ForgetAttribute(TDataStd_ByteArray::GetID());
240     return;
241   }
242   // store width, height, bytes per line and format in integer array 
243   Handle(TDataStd_IntegerArray) aParams;
244   if (!myLab.FindAttribute(TDataStd_IntegerArray::GetID(), aParams)) {
245     aParams = TDataStd_IntegerArray::Set(myLab, 1, 4);
246   }
247   aParams->SetValue(1, theImage.width());
248   aParams->SetValue(2, theImage.height());
249   aParams->SetValue(3, theImage.bytesPerLine());
250   aParams->SetValue(4, (int)(theImage.format()));
251   // store data of image in byte array
252   const char* aData = (const char*)(theImage.bits());
253   SaveByteArray(0, aData, theImage.byteCount());
254 }
255
256 bool HYDROData_Image::LoadImage(const QString& theFilePath)
257 {
258   QImage anImage( theFilePath );
259   SetImage( anImage );
260   return !anImage.isNull();
261 }
262
263 QImage HYDROData_Image::Image()
264 {
265   Handle(TDataStd_IntegerArray) aParams;
266   if (!myLab.FindAttribute(TDataStd_IntegerArray::GetID(), aParams))
267     return QImage(); // return empty image if there is no array
268   int aLen = 0;
269   uchar* anArray = (uchar*)ByteArray(0, aLen);
270   if (!aLen)
271     return QImage(); // return empty image if there is no array
272   QImage aResult(anArray, aParams->Value(1), aParams->Value(2),
273                  aParams->Value(3), QImage::Format(aParams->Value(4)));
274   return aResult;
275 }
276
277 void HYDROData_Image::SetFilePath(const QString& theFilePath)
278 {
279   TCollection_AsciiString anAsciiStr( theFilePath.toStdString().c_str() );
280   TDataStd_AsciiString::Set( myLab.FindChild( DataTag_FilePath ), anAsciiStr );
281 }
282
283 QString HYDROData_Image::GetFilePath() const
284 {
285   QString aRes;
286
287   Handle(TDataStd_AsciiString) anAsciiStr;
288   if ( myLab.FindChild( DataTag_FilePath ).FindAttribute( TDataStd_AsciiString::GetID(), anAsciiStr ) )
289     aRes = QString( anAsciiStr->Get().ToCString() );
290
291   return aRes;
292 }
293
294 void HYDROData_Image::SetTrsf(const QTransform& theTrsf)
295 {
296   // locate 9 coeffs of matrix into the real array
297   Handle(TDataStd_RealArray) anArray;
298   if (!myLab.FindAttribute(TDataStd_RealArray::GetID(), anArray)) {
299     if (theTrsf.isIdentity()) return; // no need to store identity transformation
300     anArray = TDataStd_RealArray::Set(myLab, 1, 9);
301   }
302   anArray->SetValue(1, theTrsf.m11());
303   anArray->SetValue(2, theTrsf.m12());
304   anArray->SetValue(3, theTrsf.m13());
305   anArray->SetValue(4, theTrsf.m21());
306   anArray->SetValue(5, theTrsf.m22());
307   anArray->SetValue(6, theTrsf.m23());
308   anArray->SetValue(7, theTrsf.m31());
309   anArray->SetValue(8, theTrsf.m32());
310   anArray->SetValue(9, theTrsf.m33());
311 }
312
313 QTransform HYDROData_Image::Trsf() const
314 {
315   // get 9 coeffs of matrix from the real array
316   Handle(TDataStd_RealArray) anArray;
317   if (!myLab.FindAttribute(TDataStd_RealArray::GetID(), anArray))
318     return QTransform(); // return identity if there is no array
319   QTransform aTrsf(
320     anArray->Value(1), anArray->Value(2), anArray->Value(3), 
321     anArray->Value(4), anArray->Value(5), anArray->Value(6), 
322     anArray->Value(7), anArray->Value(8), anArray->Value(9));
323   return aTrsf;
324 }
325
326 void HYDROData_Image::SetTrsfPoints(const QPoint& thePointA,
327                                     const QPoint& thePointB,
328                                     const QPoint& thePointC,
329                                     const QPointF& theLambertPointA,
330                                     const QPointF& theLambertPointB,
331                                     const QPointF& theLambertPointC,
332                                     const QPointF& theCartesianPointA,
333                                     const QPointF& theCartesianPointB,
334                                     const QPointF& theCartesianPointC)
335 {
336   Handle(TDataStd_RealArray) anArray;
337   if (!myLab.FindChild(DataTag_TrsfPoints).FindAttribute(TDataStd_RealArray::GetID(), anArray)) {
338     anArray = TDataStd_RealArray::Set(myLab.FindChild(DataTag_TrsfPoints), 1, 18);
339   }
340   anArray->SetValue(1, thePointA.x());
341   anArray->SetValue(2, thePointA.y());
342   anArray->SetValue(3, thePointB.x());
343   anArray->SetValue(4, thePointB.y());
344   anArray->SetValue(5, thePointC.x());
345   anArray->SetValue(6, thePointC.y());
346   anArray->SetValue(7, theLambertPointA.x());
347   anArray->SetValue(8, theLambertPointA.y());
348   anArray->SetValue(9, theLambertPointB.x());
349   anArray->SetValue(10, theLambertPointB.y());
350   anArray->SetValue(11, theLambertPointC.x());
351   anArray->SetValue(12, theLambertPointC.y());
352   anArray->SetValue(13, theCartesianPointA.x());
353   anArray->SetValue(14, theCartesianPointA.y());
354   anArray->SetValue(15, theCartesianPointB.x());
355   anArray->SetValue(16, theCartesianPointB.y());
356   anArray->SetValue(17, theCartesianPointC.x());
357   anArray->SetValue(18, theCartesianPointC.y());
358 }
359
360 void HYDROData_Image::TrsfPoints(QPoint& thePointA,
361                                  QPoint& thePointB,
362                                  QPoint& thePointC,
363                                  QPointF& theLambertPointA,
364                                  QPointF& theLambertPointB,
365                                  QPointF& theLambertPointC,
366                                  QPointF& theCartesianPointA,
367                                  QPointF& theCartesianPointB,
368                                  QPointF& theCartesianPointC) const
369 {
370   Handle(TDataStd_RealArray) anArray;
371   if (myLab.FindChild(DataTag_TrsfPoints).FindAttribute(TDataStd_RealArray::GetID(), anArray)) {
372     thePointA = QPointF( anArray->Value(1), anArray->Value(2) ).toPoint();
373     thePointB = QPointF( anArray->Value(3), anArray->Value(4) ).toPoint();
374     thePointC = QPointF( anArray->Value(5), anArray->Value(6) ).toPoint();
375     theLambertPointA = QPointF( anArray->Value(7), anArray->Value(8) );
376     theLambertPointB = QPointF( anArray->Value(9), anArray->Value(10) );
377     theLambertPointC = QPointF( anArray->Value(11), anArray->Value(12) );
378     theCartesianPointA = QPointF( anArray->Value(13), anArray->Value(14) );
379     theCartesianPointB = QPointF( anArray->Value(15), anArray->Value(16) );
380     theCartesianPointC = QPointF( anArray->Value(17), anArray->Value(18) );
381   }
382 }
383
384 bool HYDROData_Image::HasTrsfPoints() const
385 {
386   Handle(TDataStd_RealArray) anArray;
387   return myLab.FindChild(DataTag_TrsfPoints).FindAttribute(TDataStd_RealArray::GetID(), anArray);
388 }
389
390 void HYDROData_Image::SetTrsfMode(const int theMode)
391 {
392   TDataStd_Integer::Set(myLab.FindChild(DataTag_TrsfMode), theMode);
393 }
394
395 int HYDROData_Image::TrsfMode() const
396 {
397   Handle(TDataStd_Integer) aMode;
398   if(myLab.FindChild(DataTag_TrsfMode).FindAttribute(TDataStd_Integer::GetID(), aMode))
399     return aMode->Get();
400   return 0;
401 }
402
403 void HYDROData_Image::AppendReference( const Handle(HYDROData_Entity)& theReferenced )
404 {
405   AddReferenceObject( theReferenced, 0 );
406 }
407
408 int HYDROData_Image::NbReferences() const
409 {
410   return NbReferenceObjects( 0 );
411 }
412
413 Handle(HYDROData_Entity) HYDROData_Image::Reference( const int theIndex ) const
414 {
415   return GetReferenceObject( 0, theIndex );
416 }
417
418 void HYDROData_Image::ChangeReference(
419     const int theIndex, Handle(HYDROData_Entity) theReferenced)
420 {
421   SetReferenceObject( theReferenced, 0, theIndex );
422 }
423
424 void HYDROData_Image::RemoveReference(const int theIndex)
425 {
426   RemoveReferenceObject( 0, theIndex );
427 }
428
429 void HYDROData_Image::ClearReferences()
430 {
431   ClearReferenceObjects( 0 );
432 }
433
434 void HYDROData_Image::SetOperatorName(const QString theOpName)
435 {
436   TDataStd_Name::Set(myLab.FindChild(DataTag_Operator),
437     TCollection_ExtendedString(theOpName.toLatin1().constData()));
438 }
439
440 QString HYDROData_Image::OperatorName() const
441 {
442   Handle(TDataStd_Name) aName;
443   if (myLab.FindChild(DataTag_Operator).
444         FindAttribute(TDataStd_Name::GetID(), aName)) {
445     TCollection_AsciiString aStr(aName->Get());
446     return QString(aStr.ToCString());
447   }
448   return QString();
449 }
450
451 void HYDROData_Image::SetArgs(const QByteArray& theArgs)
452 {
453   SaveByteArray(DataTag_Operator, theArgs.constData(), theArgs.length());
454 }
455
456 QByteArray HYDROData_Image::Args() const
457 {
458   int aLen = 0;
459   const char* aData = ByteArray(DataTag_Operator, aLen);
460   if (!aLen)
461     return QByteArray();
462   return QByteArray(aData, aLen);
463 }
464
465 void HYDROData_Image::MustBeUpdated(bool theFlag)
466 {
467   if (theFlag) {
468     TDataStd_UAttribute::Set(myLab, GUID_MUST_BE_UPDATED);
469   } else {
470     myLab.ForgetAttribute(GUID_MUST_BE_UPDATED);
471   }
472 }
473
474 bool HYDROData_Image::MustBeUpdated() const
475 {
476   return myLab.IsAttribute(GUID_MUST_BE_UPDATED);
477 }
478
479 void HYDROData_Image::SetIsSelfSplitted(bool theFlag)
480 {
481   if (theFlag) {
482     TDataStd_UAttribute::Set(myLab, GUID_SELF_SPLITTED);
483   } else {
484     myLab.ForgetAttribute(GUID_SELF_SPLITTED);
485   }
486 }
487
488 bool HYDROData_Image::IsSelfSplitted() const
489 {
490   return myLab.IsAttribute(GUID_SELF_SPLITTED);
491 }