Salome HOME
refs #560: Strickler table: import/export
[modules/hydro.git] / src / HYDROData / HYDROData_PriorityQueue.cxx
1 // Copyright (C) 2014-2015  EDF-R&D
2 // This library is free software; you can redistribute it and/or
3 // modify it under the terms of the GNU Lesser General Public
4 // License as published by the Free Software Foundation; either
5 // version 2.1 of the License, or (at your option) any later version.
6 //
7 // This library is distributed in the hope that it will be useful,
8 // but WITHOUT ANY WARRANTY; without even the implied warranty of
9 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
10 // Lesser General Public License for more details.
11 //
12 // You should have received a copy of the GNU Lesser General Public
13 // License along with this library; if not, write to the Free Software
14 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
15 //
16 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
17 //
18
19 #include <HYDROData_PriorityQueue.h>
20 #include <HYDROData_CalculationCase.h>
21 #include <HYDROData_Iterator.h>
22 #include <TDataStd_ReferenceList.hxx>
23 #include <TDataStd_Integer.hxx>
24 #include <TDF_ChildIterator.hxx>
25
26 HYDROData_PriorityQueue::HYDROData_PriorityQueue( HYDROData_CalculationCase* theCalcCase )
27 {
28   myGeomObjects = theCalcCase->GetGeometryObjects();
29   for( int i=myGeomObjects.Lower(), n=myGeomObjects.Upper(); i<=n; i++ )
30   {
31     Handle(HYDROData_Object) anObj = Handle(HYDROData_Object)::DownCast( myGeomObjects.Value( i ) );
32     if( !anObj.IsNull() )
33     {
34       QString anObjName = anObj->GetName();
35       myNames[anObjName] = anObj;
36     }
37   }
38
39   myRules = GetRules( theCalcCase->Label().FindChild( HYDROData_CalculationCase::DataTag_CustomRules ) );
40 }
41
42 HYDROData_PriorityQueue::~HYDROData_PriorityQueue()
43 {
44 }
45
46 Handle(HYDROData_Object) HYDROData_PriorityQueue::GetMostPriorityObject( const QStringList& theZoneObjects,
47                                                                          HYDROData_Zone::MergeAltitudesType& theMergeType ) const
48 {
49   QStringList aSortedZoneObjects;
50   for( int i=myGeomObjects.Lower(), n=myGeomObjects.Upper(); i<=n; i++ )
51   {
52     QString aName = myGeomObjects.Value( i )->GetName();
53     if( theZoneObjects.contains( aName ) )
54       aSortedZoneObjects.append( aName );
55   }
56
57   Handle(HYDROData_Object) aMostPriorityObj;
58   theMergeType = HYDROData_Zone::Merge_UNKNOWN;
59   QStringList::const_iterator anIt = aSortedZoneObjects.begin(), aLast = aSortedZoneObjects.end();
60   for( ; anIt!=aLast; anIt++ )
61   {
62     HYDROData_Zone::MergeAltitudesType aLocalMerge = HYDROData_Zone::Merge_UNKNOWN;
63     Handle(HYDROData_Object) anObj = myNames[*anIt];
64     if( !anObj.IsNull() )
65     {
66       if( aMostPriorityObj.IsNull() )
67       {
68         aMostPriorityObj = anObj;
69         continue;
70       }
71
72       bool isMorePriority = IsMorePriority( anObj, aMostPriorityObj, aLocalMerge );
73
74       if( isMorePriority )
75         aMostPriorityObj = anObj;
76
77       if( aLocalMerge != HYDROData_Zone::Merge_UNKNOWN && 
78           ( theMergeType==HYDROData_Zone::Merge_UNKNOWN || isMorePriority ) )
79         theMergeType = aLocalMerge;
80     }
81   }
82   return aMostPriorityObj;
83 }
84
85 bool HYDROData_PriorityQueue::IsMorePriority( const Handle(HYDROData_Object)& theObj1,
86                                               const Handle(HYDROData_Object)& theObj2,
87                                               HYDROData_Zone::MergeAltitudesType& theMergeType ) const
88 {
89   // 1. First we check custom rules
90   HYDROData_ListOfRules::const_iterator anIt = myRules.begin(), aLast = myRules.end();
91   for( ; anIt!=aLast; anIt++ )
92   {
93     if( anIt->Object1->Label()==theObj1->Label() && anIt->Object2->Label()==theObj2->Label() )
94     {
95       theMergeType = anIt->MergeType;
96       return anIt->Priority==GREATER;
97     }
98     if( anIt->Object1->Label()==theObj2->Label() && anIt->Object2->Label()==theObj1->Label() )
99     {
100       theMergeType = anIt->MergeType;
101       return anIt->Priority==LESS;
102     }
103   }
104
105   // 2. If no custom rule found, the standard ordering list is applied
106   for( int i=myGeomObjects.Lower(), n=myGeomObjects.Upper(); i<=n; i++ )
107   {
108     if( myGeomObjects.Value( i )->Label() == theObj1->Label() )
109     {
110       theMergeType = HYDROData_Zone::Merge_Object;
111       return true;
112     }
113     if( myGeomObjects.Value( i )->Label() == theObj2->Label() )
114     {
115       theMergeType = HYDROData_Zone::Merge_Object;
116       return false;
117     }
118   }
119   return false;
120 }
121
122 void HYDROData_PriorityQueue::ClearRules( TDF_Label& theRulesLabel )
123 {
124   theRulesLabel.ForgetAllAttributes( true );
125 }
126
127 enum HYDROData_PriorityQueueTag
128 {
129   Object1_Tag,
130   Priority_Tag,
131   Object2_Tag,
132   Merge_Tag,
133 };
134
135 void HYDROData_PriorityQueue::AddRule( TDF_Label&                         theRulesLabel,
136                                        const Handle(HYDROData_Object)&    theObject1,
137                                        HYDROData_PriorityType             thePriority,
138                                        const Handle(HYDROData_Object)&    theObject2,
139                                        HYDROData_Zone::MergeAltitudesType theMergeType )
140 {
141   // Get the last rule index
142   Standard_Integer aRuleIndex = 0;
143   Handle(TDataStd_Integer) anIntVal;
144   if ( theRulesLabel.FindAttribute( TDataStd_Integer::GetID(), anIntVal ) ) {
145     aRuleIndex = anIntVal->Get();
146   }
147
148   TDF_Label aNewRuleLab = theRulesLabel.FindChild( aRuleIndex );
149
150   TDF_Label anObj1Lab = aNewRuleLab.FindChild( Object1_Tag );
151   Handle(TDataStd_ReferenceList) aRefs = TDataStd_ReferenceList::Set( anObj1Lab );
152   aRefs->Append( theObject1->Label() );
153   
154   TDF_Label aPriorityLab = aNewRuleLab.FindChild( Priority_Tag );
155   TDataStd_Integer::Set( aPriorityLab, thePriority );
156
157   TDF_Label anObj2Lab = aNewRuleLab.FindChild( Object2_Tag );
158   aRefs = TDataStd_ReferenceList::Set( anObj2Lab );
159   aRefs->Append( theObject2->Label() );
160
161   TDF_Label aMergeLab = aNewRuleLab.FindChild( Merge_Tag );
162   TDataStd_Integer::Set( aMergeLab, theMergeType );
163
164   // Increment the last rule index
165   TDataStd_Integer::Set( theRulesLabel, aRuleIndex + 1 );
166 }
167
168 HYDROData_ListOfRules HYDROData_PriorityQueue::GetRules( const TDF_Label& theRulesLabel )
169 {
170   HYDROData_ListOfRules aRules;
171
172   Handle(TDataStd_ReferenceList) aRefs1, aRefs2;
173   Handle(TDataStd_Integer) aPriorityAttr, aMergeAttr;
174
175   TDF_ChildIterator anIt( theRulesLabel );
176   for( ; anIt.More(); anIt.Next() )
177   {
178     TDF_Label aRuleLabel = anIt.Value();
179
180     bool isObj1OK = aRuleLabel.FindChild    ( Object1_Tag ). FindAttribute( TDataStd_ReferenceList::GetID(), aRefs1 );
181     bool isPriorityOK = aRuleLabel.FindChild( Priority_Tag ).FindAttribute( TDataStd_Integer::GetID(),       aPriorityAttr );
182     bool isObj2OK = aRuleLabel.FindChild    ( Object2_Tag ). FindAttribute( TDataStd_ReferenceList::GetID(), aRefs2 );
183     bool isMergeOK = aRuleLabel.FindChild   ( Merge_Tag ).   FindAttribute( TDataStd_Integer::GetID(),       aMergeAttr );
184
185     if( isObj1OK && isPriorityOK && isObj2OK && isMergeOK )
186     {
187       HYDROData_CustomRule aRule;
188       aRule.Object1 = Handle_HYDROData_Object::DownCast( HYDROData_Iterator::Object( aRefs1->First() ) );
189       aRule.Priority = ( HYDROData_PriorityType ) aPriorityAttr->Get();
190       aRule.Object2 = Handle_HYDROData_Object::DownCast( HYDROData_Iterator::Object( aRefs2->First() ) );
191       aRule.MergeType = ( HYDROData_Zone::MergeAltitudesType ) aMergeAttr->Get();
192       aRules.append( aRule );
193     }
194   }
195
196   return aRules;
197 }
198
199 QString HYDROData_PriorityQueue::DumpRules( const TDF_Label& theRulesLab )
200 {
201   QString aDump = "Rules:\n";
202   HYDROData_ListOfRules aRules = GetRules( theRulesLab );
203   HYDROData_ListOfRules::const_iterator anIt = aRules.begin(), aLast = aRules.end();
204   for( ; anIt!=aLast; anIt++ )
205   {
206     QString aRule = anIt->Object1->GetName() + " ";
207     aRule += ( anIt->Priority == LESS ? "<" : ">" ) + QString( " " );
208     aRule += anIt->Object2->GetName() + " ";
209
210     switch( anIt->MergeType )
211     {
212     case HYDROData_Zone::Merge_UNKNOWN:
213       aRule += "unknown";
214       break;
215     case HYDROData_Zone::Merge_ZMIN:
216       aRule += "zmin";
217       break;
218     case HYDROData_Zone::Merge_ZMAX:
219       aRule += "zmax";
220       break;
221     case HYDROData_Zone::Merge_Object:
222       aRule += "object";
223       break;
224     }
225     aDump += aRule + "\n";
226   }
227   return aDump;
228 }
229
230 void HYDROData_PriorityQueue::DumpRulesToPython( const TDF_Label& theRulesLab,
231                                                  const QString& theCalcCaseName,
232                                                  QStringList& theScript )
233 {
234   HYDROData_ListOfRules aRules = GetRules( theRulesLab );
235   HYDROData_ListOfRules::const_iterator anIt = aRules.begin(), aLast = aRules.end();
236   for( ; anIt!=aLast; anIt++ )
237   {
238     QString anObj1 = anIt->Object1->GetObjPyName();
239     QString anObj2 = anIt->Object2->GetObjPyName();
240     QString aPriority = anIt->Priority == LESS ? "LESS" : "GREATER";
241     QString aMergeType;
242
243     switch( anIt->MergeType )
244     {
245     case HYDROData_Zone::Merge_UNKNOWN:
246       aMergeType = "HYDROData_Zone.Merge_UNKNOWN";
247       break;
248     case HYDROData_Zone::Merge_ZMIN:
249       aMergeType = "HYDROData_Zone.Merge_ZMIN";
250       break;
251     case HYDROData_Zone::Merge_ZMAX:
252       aMergeType = "HYDROData_Zone.Merge_ZMAX";
253       break;
254     case HYDROData_Zone::Merge_Object:
255       aMergeType = "HYDROData_Zone.Merge_Object";
256       break;
257     }
258
259     QString aRule = QString( "%0.AddRule( %1, %2, %3, %4 )" ).
260       arg( theCalcCaseName ).arg( anObj1 ).arg( aPriority ).arg( anObj2 ).arg( aMergeType );
261
262     theScript << aRule;
263   }
264 }
265
266 bool HYDROData_PriorityQueue::GetRule( const TDF_Label& theRulesLab,
267                                        int theIndex, 
268                                        Handle(HYDROData_Object)&           theObject1,
269                                        HYDROData_PriorityType&             thePriority,
270                                        Handle(HYDROData_Object)&           theObject2,
271                                        HYDROData_Zone::MergeAltitudesType& theMergeType )
272 {
273   TDF_Label aRuleLabel = theRulesLab.FindChild( theIndex );
274
275   Handle(TDataStd_ReferenceList) aRefs1, aRefs2;
276   Handle(TDataStd_Integer) aPriorityAttr, aMergeAttr;
277
278   bool isObj1OK = aRuleLabel.FindChild    ( Object1_Tag ). FindAttribute( TDataStd_ReferenceList::GetID(), aRefs1 );
279   bool isPriorityOK = aRuleLabel.FindChild( Priority_Tag ).FindAttribute( TDataStd_Integer::GetID(),       aPriorityAttr );
280   bool isObj2OK = aRuleLabel.FindChild    ( Object2_Tag ). FindAttribute( TDataStd_ReferenceList::GetID(), aRefs2 );
281   bool isMergeOK = aRuleLabel.FindChild   ( Merge_Tag ).   FindAttribute( TDataStd_Integer::GetID(),       aMergeAttr );
282
283   bool isOK = isObj1OK && isPriorityOK && isObj2OK && isMergeOK;
284   if( isOK )
285   {
286     theObject1   = Handle_HYDROData_Object::DownCast( HYDROData_Iterator::Object( aRefs1->First() ) );
287     thePriority  = ( HYDROData_PriorityType ) aPriorityAttr->Get();
288     theObject2   = Handle_HYDROData_Object::DownCast( HYDROData_Iterator::Object( aRefs2->First() ) );
289     theMergeType = ( HYDROData_Zone::MergeAltitudesType ) aMergeAttr->Get();
290   }
291   return isOK;
292 }