Salome HOME
refs #493: provide Python API
[modules/hydro.git] / src / HYDROData / HYDROData_Document.cxx
1 // Copyright (C) 2007-2015  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 #include <HYDROData_Document.h>
24 #include <HYDROData_Application.h>
25 #include <HYDROData_Iterator.h>
26 #include <HYDROData_Tool.h>
27 #include <HYDROData_InterpolatorsFactory.h>
28
29 #include <TDataStd_Integer.hxx>
30 #include <TDataXtd_Position.hxx>
31
32 #include <TDF_Delta.hxx>
33
34 #include <gp_Pnt.hxx>
35
36 #include <QFile>
37 #include <QStringList>
38 #include <QTextStream>
39
40 IMPLEMENT_STANDARD_HANDLE(HYDROData_Document,MMgt_TShared)
41 IMPLEMENT_STANDARD_RTTIEXT(HYDROData_Document,MMgt_TShared)
42
43 #define PYTHON_DOC_NAME "hydro_doc"
44
45 static const int UNDO_LIMIT = 10; // number of possible undo operations in the module
46
47 static const int TAG_PROPS = 1; // general properties tag
48 static const int TAG_PROPS_NEW_ID = 1; // general properties: tag for storage of the new object ID
49 static const int TAG_OBJECTS = 2; // tag of the objects sub-tree
50 static const int TAG_HISTORY = 3; // tag of the history sub-tree (Root for History)
51 static const int TAG_LOCAL_CS = 4; // tag of local coordinate system information
52 static const gp_Pnt2d DEFAULT_LOCAL_CS( 0, 0 );
53
54 using namespace std;
55
56 typedef QMap<Standard_Integer,Handle_HYDROData_Entity> MapOfOrdered;
57 typedef QMap<QString,Handle_HYDROData_Entity> MapOfUnordered;
58
59 Handle(HYDROData_Document) HYDROData_Document::Document(const int theStudyID)
60 {
61   Handle(HYDROData_Document) aResult = 
62     HYDROData_Application::GetApplication()->GetDocument(theStudyID);
63   if (aResult.IsNull()) {
64     aResult = new HYDROData_Document();
65     HYDROData_Application::GetApplication()->AddDocument(theStudyID, aResult);
66   }
67   return aResult;
68 }
69
70 Handle(HYDROData_Document) HYDROData_Document::Document(
71   const TDF_Label& theObjectLabel )
72 {
73   Handle(HYDROData_Document) aResDoc;
74   if ( theObjectLabel.IsNull() )
75     return aResDoc;
76
77   Handle(TDocStd_Document) anObjDoc;
78   try
79   {
80     anObjDoc = TDocStd_Document::Get( theObjectLabel );
81   }
82   catch( ... )
83   {
84   }
85
86   if ( anObjDoc.IsNull() )
87     return aResDoc;
88
89   HYDROData_Application* anApp = HYDROData_Application::GetApplication();
90
91   DataMapOfStudyIDDocument::Iterator aMapIt( anApp->myDocuments );
92   for ( ; aMapIt.More(); aMapIt.Next() )
93   {
94     Handle(HYDROData_Document) anAppDoc = aMapIt.Value();
95     if ( anAppDoc.IsNull() || anAppDoc->myDoc != anObjDoc )
96       continue;
97
98     aResDoc = anAppDoc;
99     break;
100   }
101
102   return aResDoc;
103 }
104
105 bool HYDROData_Document::HasDocument(const int theStudyID)
106 {
107   Handle(HYDROData_Document) aResult = 
108     HYDROData_Application::GetApplication()->GetDocument(theStudyID);
109   return !aResult.IsNull();
110 }
111
112 bool HYDROData_Document::DocumentId(const Handle(HYDROData_Document)& theDocument,
113                                     int&                              theDocId )
114 {
115   return HYDROData_Application::GetApplication()->GetDocumentId(theDocument, theDocId);
116 }
117
118 Data_DocError HYDROData_Document::Load(const char* theFileName, const int theStudyID)
119 {
120   Handle(TDocStd_Document) aResult;
121   TCollection_ExtendedString aPath ((const Standard_CString)theFileName);
122   PCDM_ReaderStatus aStatus = (PCDM_ReaderStatus) -1;
123   try
124   {
125     aStatus = HYDROData_Application::GetApplication()->Open (aPath, aResult);
126   }
127   catch (Standard_Failure)
128   {}
129   if (!aResult.IsNull()) {
130     aResult->SetUndoLimit(UNDO_LIMIT);
131     HYDROData_Application::GetApplication()->AddDocument(theStudyID, new HYDROData_Document(aResult));
132   }
133   // recognize error
134   Data_DocError anError;
135   switch(aStatus) {
136   case PCDM_RS_OK:
137     anError = DocError_OK;
138     break;
139   case PCDM_RS_NoDriver:
140   case PCDM_RS_UnknownFileDriver:
141   case PCDM_RS_NoSchema:
142   case PCDM_RS_DriverFailure:
143   case PCDM_RS_WrongResource:
144     anError = DocError_ResourcesProblem;
145     break;
146   case PCDM_RS_OpenError:
147   case PCDM_RS_NoDocument:
148   case PCDM_RS_WrongStreamMode:
149   case PCDM_RS_PermissionDenied:
150     anError = DocError_CanNotOpen;
151     break;
152   case PCDM_RS_NoVersion:
153     anError = DocError_InvalidVersion;
154     break;
155   case PCDM_RS_ExtensionFailure:
156   case PCDM_RS_FormatFailure:
157   case PCDM_RS_TypeFailure:
158   case PCDM_RS_TypeNotFoundInSchema:
159   case PCDM_RS_UnrecognizedFileFormat:
160     anError = DocError_InvalidFormat;
161     break;
162   case PCDM_RS_MakeFailure:
163   default:
164     anError = DocError_UnknownProblem;
165     break;
166   }
167   return anError;
168 }
169
170 Data_DocError HYDROData_Document::Save(const char* theFileName)
171 {
172   TCollection_ExtendedString aPath ((const Standard_CString)theFileName);
173   PCDM_StoreStatus aStatus;
174   try {
175     aStatus = HYDROData_Application::GetApplication()->SaveAs (myDoc, aPath);
176   }
177   catch (Standard_Failure) {}
178   myTransactionsAfterSave = 0;
179   Standard::Purge(); // Release free memory
180
181   // recognize error
182   Data_DocError anError;
183   switch(aStatus) {
184   case PCDM_SS_OK:
185     anError = DocError_OK;
186     break;
187   case PCDM_SS_DriverFailure:
188     anError = DocError_ResourcesProblem;
189     break;
190   case PCDM_SS_WriteFailure:
191   //case PCDM_SS_DiskWritingFailure:
192   //case PCDM_SS_UserRightsFailure:
193     anError = DocError_CanNotOpen;
194     break;
195   default:
196     anError = DocError_UnknownProblem;
197     break;
198   }
199   return anError;
200 }
201
202 void HYDROData_Document::Close()
203 {
204   myDoc->Close();
205   HYDROData_Application::GetApplication()->RemoveDocument(this);
206 }
207
208 bool HYDROData_Document::DumpToPython( const QString& theFileName,
209                                        const bool     theIsMultiFile ) const
210 {
211   // Try to open the file
212   QFile aFile( theFileName );
213   if ( !aFile.open( QIODevice::WriteOnly ) )
214     return false;
215
216   MapOfTreatedObjects aTreatedObjects;
217
218   // Dump header for python script
219   QStringList aHeaderDump = DumpToPython( aTreatedObjects, theIsMultiFile );
220   if ( aHeaderDump.isEmpty() )
221     return false;
222
223   HYDROData_Tool::WriteStringsToFile( aFile, aHeaderDump );
224
225   bool aRes = true;
226
227   // Dump the local CS data to Python 
228   UpdateLCSFields();
229   QString aLCS = QString( "%1.SetLocalCS( %2, %3 )" ).arg( GetDocPyName() ).arg( myLX ).arg( myLY );
230   if( theIsMultiFile )
231     aLCS.prepend( "  " );
232   HYDROData_Tool::WriteStringsToFile( aFile, QStringList() << aLCS );
233
234   // Dump all model objects to Python script
235   aRes = aRes && dumpPartitionToPython( aFile, theIsMultiFile, aTreatedObjects, KIND_IMAGE );
236   aRes = aRes && dumpPartitionToPython( aFile, theIsMultiFile, aTreatedObjects, KIND_POLYLINEXY );
237   aRes = aRes && dumpPartitionToPython( aFile, theIsMultiFile, aTreatedObjects, KIND_BATHYMETRY );
238   aRes = aRes && dumpPartitionToPython( aFile, theIsMultiFile, aTreatedObjects, KIND_PROFILE );
239   aRes = aRes && dumpPartitionToPython( aFile, theIsMultiFile, aTreatedObjects, KIND_POLYLINE );
240   aRes = aRes && dumpPartitionToPython( aFile, theIsMultiFile, aTreatedObjects, KIND_IMMERSIBLE_ZONE );
241   aRes = aRes && dumpPartitionToPython( aFile, theIsMultiFile, aTreatedObjects, KIND_STREAM );
242   aRes = aRes && dumpPartitionToPython( aFile, theIsMultiFile, aTreatedObjects, KIND_CHANNEL );
243   aRes = aRes && dumpPartitionToPython( aFile, theIsMultiFile, aTreatedObjects, KIND_DIGUE );
244   aRes = aRes && dumpPartitionToPython( aFile, theIsMultiFile, aTreatedObjects, KIND_OBSTACLE );
245   aRes = aRes && dumpPartitionToPython( aFile, theIsMultiFile, aTreatedObjects, KIND_CALCULATION );
246
247   // Dump code to close python fuction
248   if ( aRes && theIsMultiFile )
249   {
250     QStringList aFooterScript;
251     aFooterScript << QString( "" );
252     aFooterScript << QString( "  pass" );
253     HYDROData_Tool::WriteStringsToFile( aFile, aFooterScript );
254   }
255
256   return aRes;
257 }
258
259 QString HYDROData_Document::GetDocPyName() const
260 {
261   QString aDocName = PYTHON_DOC_NAME;
262   
263   /*
264   int aDocId = 1;
265   if ( DocumentId( this, aDocId ) )
266     aDocName += "_" + QString::number( aDocId );
267   */
268   
269   return aDocName;
270 }
271
272 QStringList HYDROData_Document::DumpToPython( MapOfTreatedObjects& theTreatedObjects,
273                                               const bool           theIsMultiFile ) const
274 {
275   QString aDocName = GetDocPyName();
276
277   // Append document in to the map of treated objects to prevent names overlaping
278   theTreatedObjects.insert( aDocName, this );
279
280   int aDocId = 1;
281   if ( !DocumentId( this, aDocId ) )
282     aDocId = 1;
283
284   QStringList aResScript;
285
286   aResScript << QString( "from HYDROPy import *" );
287   aResScript << QString( "from PyQt4.QtCore import *" );
288   aResScript << QString( "from PyQt4.QtGui import *" );
289
290   if ( theIsMultiFile )
291   {
292     aResScript << QString( "import salome" );
293     aResScript << QString( "" );
294     aResScript << QString( "def RebuildData( theStudy ):" );
295     aResScript << QString( "  %1 = HYDROData_Document.Document( theStudy._get_StudyId() );" ).arg( aDocName );
296   }
297   else
298   {
299     aResScript << QString( "" );
300     aResScript << QString( "%1 = HYDROData_Document.Document( theStudy._get_StudyId() );" ).arg( aDocName );
301   }
302
303   return aResScript;
304 }
305
306 bool HYDROData_Document::dumpPartitionToPython( QFile&               theFile,
307                                                 const bool           theIsMultiFile,
308                                                 MapOfTreatedObjects& theTreatedObjects,
309                                                 const ObjectKind&    theObjectKind ) const
310 {
311   if ( !theFile.isOpen() )
312     return false;
313
314   QTextStream anOutStream( &theFile );
315
316   bool aRes = true;
317
318   HYDROData_Iterator anIterator( this, theObjectKind );
319   for( ; anIterator.More(); anIterator.Next() )
320   {
321     Handle(HYDROData_Entity) anObject = anIterator.Current();
322     if ( anObject.IsNull() )
323       continue;
324
325     QString anObjName = anObject->GetName();
326     if ( theTreatedObjects.contains( anObjName ) )
327       continue;
328
329     theTreatedObjects.insert( anObjName, anObject );
330
331     QStringList anObjDump = anObject->DumpToPython( theTreatedObjects );
332
333     if ( theIsMultiFile )
334     {
335       // For multifile dump we use the function, see the document dump header
336       QStringList::iterator anIt = anObjDump.begin();
337       for ( ; anIt != anObjDump.end(); ++anIt )
338         anIt->prepend( "  " );
339     }
340     
341     HYDROData_Tool::WriteStringsToFile( theFile, anObjDump );
342   }
343   
344   return aRes;
345 }
346
347 bool takeLastDigits( QString& theStr, int& aRes )
348 {
349   aRes = -1;
350
351   QString anStrNum;
352   for ( int i = theStr.length() - 1; i >= 0; --i )
353   {
354     const QChar& aChar = theStr.at( i );
355     if ( !aChar.isDigit() )
356       break;
357
358     anStrNum.prepend( aChar );
359   }
360
361   if ( anStrNum.isEmpty() )
362     return false;
363
364   theStr.remove( theStr.length() - anStrNum.length(), anStrNum.length() );
365   aRes = anStrNum.toInt();
366
367   return true;
368 }
369
370 bool isObjectNameLessThan( const QString& theStr1, const QString& theStr2 )
371 {
372   QString aStr1 = theStr1, aStr2 = theStr2;
373
374   int aNum1 = -1, aNum2 = -1;
375   if ( takeLastDigits( aStr1, aNum1 ) && takeLastDigits( aStr2, aNum2 ) )
376   {
377     if ( aStr1 == aStr2 )
378       return aNum1 < aNum2;
379   }
380
381   return theStr1 < theStr2;
382 }
383
384 HYDROData_SequenceOfObjects HYDROData_Document::GetObjectsLayerOrder(
385   const Standard_Boolean theIsAll ) const
386 {
387   HYDROData_SequenceOfObjects anOrder;
388
389   MapOfOrdered   aMapOfOrdered;
390   MapOfUnordered aMapOfUnordered;
391
392   HYDROData_Iterator anIter( this );
393   for ( ; anIter.More(); anIter.Next() )
394   {
395     Handle(HYDROData_Entity) anObject = anIter.Current();
396     if ( anObject.IsNull() || !anObject->IsHas2dPrs() )
397       continue;
398
399     Standard_Integer anObjZLevel = -1;
400     if ( anObject->GetZLevel( anObjZLevel ) )
401     {
402       aMapOfOrdered.insert( anObjZLevel, anObject );
403     }
404     else
405     {
406       QString anObjName = anObject->GetName();
407       if ( anObjName.isEmpty() )
408         continue;
409
410       aMapOfUnordered.insert( anObjName, anObject );
411     }
412   }
413
414   MapOfOrdered::const_iterator anOrderedMapIt = aMapOfOrdered.constBegin();
415   for ( ; anOrderedMapIt != aMapOfOrdered.constEnd(); anOrderedMapIt++ )
416   {
417     const Handle(HYDROData_Entity)& anObject = anOrderedMapIt.value();
418     anOrder.Prepend( anObject );
419   }
420
421   if ( theIsAll )
422   {
423     QStringList aSortedNames = aMapOfUnordered.keys();
424     qSort( aSortedNames.begin(), aSortedNames.end(), isObjectNameLessThan );
425
426     for ( int i = 0; i < aSortedNames.length(); ++i )
427     {
428       QString anObjName = aSortedNames.value( i );
429
430       const Handle(HYDROData_Entity)& anObject = aMapOfUnordered.value( anObjName );
431       anOrder.Append( anObject );
432     }
433   }
434
435   return anOrder;
436 }
437
438 void HYDROData_Document::SetObjectsLayerOrder( const HYDROData_SequenceOfObjects& theOrder )
439 {
440   // At first we remove previous model order
441   RemoveObjectsLayerOrder();
442
443   // Make new objects order
444   Standard_Integer aLevel = 0;
445   for ( int i = theOrder.Length(), n = 1; i >= n; --i )
446   {
447     const Handle(HYDROData_Entity)& anObject = theOrder.Value( i );
448     if ( anObject.IsNull() || !anObject->IsHas2dPrs() )
449       continue;
450
451     anObject->SetZLevel( aLevel++ );
452   }
453 }
454
455 void HYDROData_Document::Show( const Handle_HYDROData_Entity& theObject )
456 {
457   HYDROData_SequenceOfObjects anOrder;
458   anOrder.Append( theObject );
459   Show( anOrder );
460 }
461
462 void HYDROData_Document::Show( const HYDROData_SequenceOfObjects& theObjects )
463 {
464   MapOfUnordered aMapOfUnordered;
465
466   for ( int i = 1, n = theObjects.Length(); i <= n; ++i )
467   {
468     const Handle(HYDROData_Entity)& anObject = theObjects.Value( i );
469     if ( anObject.IsNull() || !anObject->IsHas2dPrs() )
470       continue;
471
472     Standard_Integer anObjZLevel = -1;
473     if ( anObject->GetZLevel( anObjZLevel ) )
474     {
475       continue; // Skip objects that already have the z-level
476     }
477     else
478     {
479       QString anObjName = anObject->GetName();
480       if ( anObjName.isEmpty() )
481         continue;
482
483       aMapOfUnordered.insert( anObjName, anObject );
484     }
485   }
486
487   if ( aMapOfUnordered.isEmpty() )
488     return; // Nothing to show
489
490   Standard_Integer aTopId = 0;
491
492   HYDROData_SequenceOfObjects aModelOrder = GetObjectsLayerOrder( Standard_False );
493   if ( !aModelOrder.IsEmpty() )
494   {
495     const Handle(HYDROData_Entity)& anObject = aModelOrder.First();
496     anObject->GetZLevel( aTopId );
497     aTopId++;
498   }
499
500   aTopId += aMapOfUnordered.size() - 1;
501
502   QStringList aSortedNames = aMapOfUnordered.keys();
503   qSort( aSortedNames.begin(), aSortedNames.end(), isObjectNameLessThan );
504
505   for ( int i = 0; i < aSortedNames.length(); ++i )
506   {
507     QString anObjName = aSortedNames.value( i );
508
509     const Handle(HYDROData_Entity)& anObject = aMapOfUnordered.value( anObjName );
510     anObject->SetZLevel( aTopId-- );
511   }
512 }
513
514 void HYDROData_Document::RemoveObjectsLayerOrder()
515 {
516   HYDROData_Iterator anIter( this );
517   for ( ; anIter.More(); anIter.Next() )
518   {
519     Handle(HYDROData_Entity) anObject = anIter.Current();
520     if ( anObject.IsNull() || !anObject->IsHas2dPrs() )
521       continue;
522
523     anObject->RemoveZLevel();
524   }
525 }
526
527 void HYDROData_Document::StartOperation()
528 {
529   myDoc->NewCommand();
530 }
531
532 void HYDROData_Document::CommitOperation(const TCollection_ExtendedString& theName)
533 {
534   if( !myDoc->CommitCommand() ) // it means that there were no modifications done
535   {
536     myDoc->NewCommand();
537     NewID(); // workaround: do something just to modify the document
538     myDoc->CommitCommand();
539   }
540   myTransactionsAfterSave++;
541
542   if( theName.Length() != 0 )
543   {
544     const TDF_DeltaList& aList = GetUndos();
545     if( !aList.IsEmpty() )
546     {
547       Handle(TDF_Delta) aDelta = aList.Last();
548       if( !aDelta.IsNull() )
549         aDelta->SetName( theName );
550     }
551   }
552 }
553
554 void HYDROData_Document::AbortOperation()
555 {
556   myDoc->AbortCommand();
557 }
558
559 bool HYDROData_Document::IsOperation()
560 {
561   return myDoc->HasOpenCommand() != 0;
562 }
563
564 bool HYDROData_Document::IsModified()
565 {
566   return myTransactionsAfterSave != 0;
567 }
568
569 bool HYDROData_Document::CanUndo()
570 {
571   return myDoc->GetAvailableUndos() > 0;
572 }
573
574 const TDF_DeltaList& HYDROData_Document::GetUndos()
575 {
576   return myDoc->GetUndos();
577 }
578
579 void HYDROData_Document::ClearUndos()
580 {
581   return myDoc->ClearUndos();
582 }
583
584 void HYDROData_Document::Undo()
585 {
586   myDoc->Undo();
587   myTransactionsAfterSave--;
588 }
589
590 bool HYDROData_Document::CanRedo()
591 {
592   return myDoc->GetAvailableRedos() > 0;
593 }
594
595 const TDF_DeltaList& HYDROData_Document::GetRedos()
596 {
597   return myDoc->GetRedos();
598 }
599
600 void HYDROData_Document::ClearRedos()
601 {
602   return myDoc->ClearRedos();
603 }
604
605 void HYDROData_Document::Redo()
606 {
607   myDoc->Redo();
608   myTransactionsAfterSave++;
609 }
610
611 Handle(HYDROData_Entity) HYDROData_Document::CreateObject( const ObjectKind theKind )
612 {
613   return HYDROData_Iterator::CreateObject( this, theKind );
614 }
615
616 Handle(HYDROData_Entity) HYDROData_Document::FindObjectByName( 
617   const QString&   theName,
618   const ObjectKind theObjectKind ) const
619 {
620   Handle(HYDROData_Entity) anObject;
621   if ( theName.isEmpty() )
622     return anObject;
623
624   QStringList aNamesList;
625   aNamesList << theName;
626
627   HYDROData_SequenceOfObjects aSeqOfObjs = FindObjectsByNames( aNamesList, theObjectKind );
628   if( aSeqOfObjs.IsEmpty() )
629     return anObject;
630   
631   anObject = aSeqOfObjs.First();
632   return anObject;
633 }
634
635 HYDROData_SequenceOfObjects HYDROData_Document::FindObjectsByNames(
636   const QStringList& theNames, 
637   const ObjectKind   theObjectKind ) const
638 {
639   HYDROData_SequenceOfObjects aResSeq;
640
641   QStringList aNamesList = theNames;
642
643   HYDROData_Iterator anIter( this, theObjectKind );
644   for( ; anIter.More(); anIter.Next() )
645   {
646     Handle(HYDROData_Entity) anObject = anIter.Current();
647     if( anObject.IsNull() )
648       continue;
649
650     QString anObjName = anObject->GetName();
651     if ( anObjName.isEmpty() || !aNamesList.contains( anObjName ) )
652       continue;
653
654     aResSeq.Append( anObject );
655
656     aNamesList.removeAll( anObjName );
657     if ( aNamesList.isEmpty() )
658       break;
659   }
660
661   return aResSeq;
662 }
663
664 HYDROData_Document::HYDROData_Document()
665 {
666   HYDROData_Application::GetApplication()->NewDocument("BinOcaf", myDoc);
667   myDoc->SetUndoLimit(UNDO_LIMIT);
668   NewID(); // needed to have at least one attribute in initial document to avoid errors
669   myTransactionsAfterSave = 0;
670   myLX = -1;
671   myLY = -1;
672
673   myInterpolatorsFactory = 0;
674 }
675
676 HYDROData_Document::HYDROData_Document(const Handle(TDocStd_Document)& theDoc)
677 {
678   myDoc = theDoc;
679   myTransactionsAfterSave = 0;
680   myLX = -1;
681   myLY = -1;
682
683   myInterpolatorsFactory = 0;
684 }
685
686 HYDROData_Document::~HYDROData_Document()
687 {
688 }
689
690 int HYDROData_Document::NewID()
691 {
692   TDF_Label anIDLab = myDoc->Main().FindChild(TAG_PROPS).
693     FindChild(TAG_PROPS_NEW_ID);
694   Handle(TDataStd_Integer) anInt;
695   if (!anIDLab.FindAttribute(TDataStd_Integer::GetID(), anInt)) {
696     anInt = TDataStd_Integer::Set(anIDLab, 0);
697   }
698   // just increment value and return
699   anInt->Set(anInt->Get() + 1);
700   return anInt->Get();
701 }
702
703 TDF_Label HYDROData_Document::LabelOfObjects()
704 {
705   return myDoc->Main().FindChild(TAG_OBJECTS);
706 }
707
708 TDF_Label HYDROData_Document::LabelOfLocalCS() const
709 {
710   return myDoc->Main().FindChild(TAG_LOCAL_CS);
711 }
712
713 void HYDROData_Document::GetLocalCS( double& theLX, double& theLY ) const
714 {
715   TDF_Label aLocalCSLab = LabelOfLocalCS();
716
717   Handle( TDataXtd_Position ) aLocalCS;
718   if( aLocalCSLab.FindAttribute( TDataXtd_Position::GetID(), aLocalCS ) )
719   {
720     gp_Pnt aLocalCS3d = aLocalCS->GetPosition();
721     theLX = aLocalCS3d.X();
722     theLY = aLocalCS3d.Y();
723   }
724   else
725   {
726     theLX = DEFAULT_LOCAL_CS.X();
727     theLY = DEFAULT_LOCAL_CS.Y();
728   }
729 }
730
731 void HYDROData_Document::SetLocalCS( double theLX, double theLY )
732 {
733   UpdateLCSFields();
734
735   // update the local CS data in attribute
736   TDF_Label aLocalCSLab = LabelOfLocalCS();
737   Handle( TDataXtd_Position ) aLocalCS;
738   if( !aLocalCSLab.FindAttribute( TDataXtd_Position::GetID(), aLocalCS ) )
739     aLocalCS = TDataXtd_Position::Set( aLocalCSLab );
740
741   gp_Pnt aLocalCS3d( theLX, theLY, 0 );
742   aLocalCS->SetPosition( aLocalCS3d );
743
744   // calculate delta for coordinates
745   double aDX = myLX - theLX;
746   double aDY = myLY - theLY;
747
748   // update the local CS data in internal fields
749   myLX = theLX;
750   myLY = theLY;
751
752   //update all objects in the document
753   HYDROData_Iterator anIterator( this, KIND_UNKNOWN );
754   for( ; anIterator.More(); anIterator.Next() )
755     anIterator.Current()->UpdateLocalCS( aDX, aDY );
756 }
757
758 void HYDROData_Document::UpdateLCSFields() const
759 {
760   if( myLX >= 0 && myLY >= 0 )
761     return;
762
763   double aLX, aLY;
764   GetLocalCS( aLX, aLY );
765   HYDROData_Document* aThat = const_cast<HYDROData_Document*>( this );
766   aThat->myLX = aLX;
767   aThat->myLY = aLY;
768 }
769
770 void HYDROData_Document::Transform( double& X, double& Y, bool IsToLocalCS ) const
771 {
772   UpdateLCSFields();
773   if( IsToLocalCS )
774   {
775     X -= myLX;
776     Y -= myLY;
777   }
778   else
779   {
780     X += myLX;
781     Y += myLY;
782   }
783 }
784
785 void HYDROData_Document::Transform( gp_Pnt& thePnt, bool IsToLocalCS ) const
786 {
787   double X = thePnt.X();
788   double Y = thePnt.Y();
789   double Z = thePnt.Z();
790   Transform( X, Y, IsToLocalCS );
791   thePnt = gp_Pnt( X, Y, Z ); 
792 }
793
794 void HYDROData_Document::Transform( gp_XYZ& thePnt, bool IsToLocalCS ) const
795 {
796   double X = thePnt.X();
797   double Y = thePnt.Y();
798   double Z = thePnt.Z();
799   Transform( X, Y, IsToLocalCS );
800   thePnt = gp_XYZ( X, Y, Z ); 
801 }
802
803 void HYDROData_Document::Transform( gp_XY& thePnt, bool IsToLocalCS ) const
804 {
805   double X = thePnt.X();
806   double Y = thePnt.Y();
807   Transform( X, Y, IsToLocalCS );
808   thePnt = gp_XY( X, Y ); 
809 }
810
811 HYDROData_InterpolatorsFactory* HYDROData_Document::GetInterpolatorsFactory()
812 {
813   if ( !myInterpolatorsFactory ) {
814     myInterpolatorsFactory = new HYDROData_InterpolatorsFactory();
815   }
816
817   return myInterpolatorsFactory;
818 }
819
820 HYDROData_IProfilesInterpolator* HYDROData_Document::GetInterpolator( const TCollection_AsciiString& theName ) const
821 {
822   HYDROData_IProfilesInterpolator* anInterpolator = NULL;
823
824   HYDROData_Document* aThat = const_cast<HYDROData_Document*>( this );
825   HYDROData_InterpolatorsFactory* aFactory = aThat->GetInterpolatorsFactory();
826   if ( aFactory ) {
827     anInterpolator = aFactory->GetInterpolator( theName );
828   }
829
830   return anInterpolator;
831 }
832  
833 NCollection_Sequence<TCollection_AsciiString> HYDROData_Document::GetInterpolatorNames() const
834 {
835   NCollection_Sequence<TCollection_AsciiString> aNames;
836
837   HYDROData_Document* aThat = const_cast<HYDROData_Document*>( this );
838   HYDROData_InterpolatorsFactory* aFactory = aThat->GetInterpolatorsFactory();
839   if ( aFactory ) {
840     aNames = aFactory->GetInterpolatorNames();
841   }
842
843   return aNames;
844 }