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