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