Salome HOME
refs #651: wrapping land cover map by Python
[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                                                   Standard_Integer aTag )
28 {
29   myObjects = theCalcCase->GetGeometryObjects();
30   for( int i=myObjects.Lower(), n=myObjects.Upper(); i<=n; i++ )
31   {
32     Handle(HYDROData_Entity) anObj = myObjects.Value( i );
33     if( !anObj.IsNull() )
34     {
35       QString anObjName = anObj->GetName();
36       myNames[anObjName] = anObj;
37     }
38   }
39
40   myRules = GetRules( theCalcCase->Label().FindChild( aTag ) );
41 }
42
43 HYDROData_PriorityQueue::~HYDROData_PriorityQueue()
44 {
45 }
46
47 Handle(HYDROData_Entity) HYDROData_PriorityQueue::GetMostPriorityObject( const QStringList& theZoneObjects,
48                                                                          HYDROData_Zone::MergeType& theMergeType ) const
49 {
50   QStringList aSortedZoneObjects;
51   for( int i=myObjects.Lower(), n=myObjects.Upper(); i<=n; i++ )
52   {
53     QString aName = myObjects.Value( i )->GetName();
54     if( theZoneObjects.contains( aName ) )
55       aSortedZoneObjects.append( aName );
56   }
57
58   Handle(HYDROData_Entity) aMostPriorityObj;
59   theMergeType = HYDROData_Zone::Merge_UNKNOWN;
60   QStringList::const_iterator anIt = aSortedZoneObjects.begin(), aLast = aSortedZoneObjects.end();
61   for( ; anIt!=aLast; anIt++ )
62   {
63     HYDROData_Zone::MergeType aLocalMerge = HYDROData_Zone::Merge_UNKNOWN;
64     Handle(HYDROData_Entity) anObj = myNames[*anIt];
65     if( !anObj.IsNull() )
66     {
67       if( aMostPriorityObj.IsNull() )
68       {
69         aMostPriorityObj = anObj;
70         continue;
71       }
72
73       bool isMorePriority = IsMorePriority( anObj, aMostPriorityObj, aLocalMerge );
74
75       if( isMorePriority )
76         aMostPriorityObj = anObj;
77
78       if( aLocalMerge != HYDROData_Zone::Merge_UNKNOWN && 
79           ( theMergeType==HYDROData_Zone::Merge_UNKNOWN || isMorePriority ) )
80         theMergeType = aLocalMerge;
81     }
82   }
83   return aMostPriorityObj;
84 }
85
86 bool HYDROData_PriorityQueue::IsMorePriority( const Handle(HYDROData_Entity)& theObj1,
87                                               const Handle(HYDROData_Entity)& theObj2,
88                                               HYDROData_Zone::MergeType& theMergeType ) const
89 {
90   // 1. First we check custom rules
91   HYDROData_ListOfRules::const_iterator anIt = myRules.begin(), aLast = myRules.end();
92   for( ; anIt!=aLast; anIt++ )
93   {
94     if( anIt->Object1->Label()==theObj1->Label() && anIt->Object2->Label()==theObj2->Label() )
95     {
96       theMergeType = anIt->MergeType;
97       return anIt->Priority==GREATER;
98     }
99     if( anIt->Object1->Label()==theObj2->Label() && anIt->Object2->Label()==theObj1->Label() )
100     {
101       theMergeType = anIt->MergeType;
102       return anIt->Priority==LESS;
103     }
104   }
105
106   // 2. If no custom rule found, the standard ordering list is applied
107   for( int i=myObjects.Lower(), n=myObjects.Upper(); i<=n; i++ )
108   {
109     if( myObjects.Value( i )->Label() == theObj1->Label() )
110     {
111       theMergeType = HYDROData_Zone::Merge_Object;
112       return true;
113     }
114     if( myObjects.Value( i )->Label() == theObj2->Label() )
115     {
116       theMergeType = HYDROData_Zone::Merge_Object;
117       return false;
118     }
119   }
120   return false;
121 }
122
123 void HYDROData_PriorityQueue::ClearRules( TDF_Label& theRulesLabel )
124 {
125   theRulesLabel.ForgetAllAttributes( true );
126 }
127
128 enum HYDROData_PriorityQueueTag
129 {
130   Object1_Tag,
131   Priority_Tag,
132   Object2_Tag,
133   Merge_Tag,
134 };
135
136 void HYDROData_PriorityQueue::AddRule( TDF_Label&                      theRulesLabel,
137                                        const Handle(HYDROData_Entity)& theObject1,
138                                        HYDROData_PriorityType          thePriority,
139                                        const Handle(HYDROData_Entity)& theObject2,
140                                        HYDROData_Zone::MergeType       theMergeType )
141 {
142   // Get the last rule index
143   Standard_Integer aRuleIndex = 0;
144   Handle(TDataStd_Integer) anIntVal;
145   if ( theRulesLabel.FindAttribute( TDataStd_Integer::GetID(), anIntVal ) ) {
146     aRuleIndex = anIntVal->Get();
147   }
148
149   TDF_Label aNewRuleLab = theRulesLabel.FindChild( aRuleIndex );
150
151   TDF_Label anObj1Lab = aNewRuleLab.FindChild( Object1_Tag );
152   Handle(TDataStd_ReferenceList) aRefs = TDataStd_ReferenceList::Set( anObj1Lab );
153   aRefs->Append( theObject1->Label() );
154   
155   TDF_Label aPriorityLab = aNewRuleLab.FindChild( Priority_Tag );
156   TDataStd_Integer::Set( aPriorityLab, thePriority );
157
158   TDF_Label anObj2Lab = aNewRuleLab.FindChild( Object2_Tag );
159   aRefs = TDataStd_ReferenceList::Set( anObj2Lab );
160   aRefs->Append( theObject2->Label() );
161
162   TDF_Label aMergeLab = aNewRuleLab.FindChild( Merge_Tag );
163   TDataStd_Integer::Set( aMergeLab, theMergeType );
164
165   // Increment the last rule index
166   TDataStd_Integer::Set( theRulesLabel, aRuleIndex + 1 );
167 }
168
169 HYDROData_ListOfRules HYDROData_PriorityQueue::GetRules( const TDF_Label& theRulesLabel )
170 {
171   HYDROData_ListOfRules aRules;
172
173   Handle(TDataStd_ReferenceList) aRefs1, aRefs2;
174   Handle(TDataStd_Integer) aPriorityAttr, aMergeAttr;
175
176   TDF_ChildIterator anIt( theRulesLabel );
177   for( ; anIt.More(); anIt.Next() )
178   {
179     TDF_Label aRuleLabel = anIt.Value();
180
181     bool isObj1OK = aRuleLabel.FindChild    ( Object1_Tag ). FindAttribute( TDataStd_ReferenceList::GetID(), aRefs1 );
182     bool isPriorityOK = aRuleLabel.FindChild( Priority_Tag ).FindAttribute( TDataStd_Integer::GetID(),       aPriorityAttr );
183     bool isObj2OK = aRuleLabel.FindChild    ( Object2_Tag ). FindAttribute( TDataStd_ReferenceList::GetID(), aRefs2 );
184     bool isMergeOK = aRuleLabel.FindChild   ( Merge_Tag ).   FindAttribute( TDataStd_Integer::GetID(),       aMergeAttr );
185
186     if( isObj1OK && isPriorityOK && isObj2OK && isMergeOK )
187     {
188       HYDROData_CustomRule aRule;
189       aRule.Object1 = HYDROData_Iterator::Object( aRefs1->First() );
190       aRule.Priority = ( HYDROData_PriorityType ) aPriorityAttr->Get();
191       aRule.Object2 = HYDROData_Iterator::Object( aRefs2->First() );
192       aRule.MergeType = ( HYDROData_Zone::MergeType ) aMergeAttr->Get();
193       aRules.append( aRule );
194     }
195   }
196
197   return aRules;
198 }
199
200 QString HYDROData_PriorityQueue::DumpRules( const TDF_Label& theRulesLab )
201 {
202   QString aDump = "Rules:\n";
203
204   HYDROData_ListOfRules aRules = GetRules( theRulesLab );
205   HYDROData_ListOfRules::const_iterator anIt = aRules.begin(), aLast = aRules.end();
206   for( ; anIt!=aLast; anIt++ )
207   {
208     QString aRule = anIt->Object1->GetName() + " ";
209     aRule += ( anIt->Priority == LESS ? "<" : ">" ) + QString( " " );
210     aRule += anIt->Object2->GetName() + " ";
211
212     switch( anIt->MergeType )
213     {
214     case HYDROData_Zone::Merge_UNKNOWN:
215       aRule += "unknown";
216       break;
217     case HYDROData_Zone::Merge_ZMIN:
218       aRule += "zmin";
219       break;
220     case HYDROData_Zone::Merge_ZMAX:
221       aRule += "zmax";
222       break;
223     case HYDROData_Zone::Merge_Object:
224       aRule += "object";
225       break;
226     }
227     aDump += aRule + "\n";
228   }
229   return aDump;
230 }
231
232 void HYDROData_PriorityQueue::DumpRulesToPython( const TDF_Label& theRulesLab,
233                                                  const QString& theCalcCaseName,
234                                                  QStringList& theScript )
235 {
236   HYDROData_ListOfRules aRules = GetRules( theRulesLab );
237   HYDROData_ListOfRules::const_iterator anIt = aRules.begin(), aLast = aRules.end();
238   for( ; anIt!=aLast; anIt++ )
239   {
240     QString anObj1 = anIt->Object1->GetObjPyName();
241     QString anObj2 = anIt->Object2->GetObjPyName();
242     QString aPriority = anIt->Priority == LESS ? "LESS" : "GREATER";
243     QString aMergeType;
244
245     HYDROData_CalculationCase::DataTag aDataTag = HYDROData_CalculationCase::DataTag_CustomRules;
246
247     switch( anIt->MergeType )
248     {
249     case HYDROData_Zone::Merge_UNKNOWN:
250       aMergeType = "HYDROData_Zone.Merge_UNKNOWN";
251       break;
252     case HYDROData_Zone::Merge_ZMIN:
253       aMergeType = "HYDROData_Zone.Merge_ZMIN";
254       break;
255     case HYDROData_Zone::Merge_ZMAX:
256       aMergeType = "HYDROData_Zone.Merge_ZMAX";
257       break;
258     case HYDROData_Zone::Merge_Object:
259       aMergeType = "HYDROData_Zone.Merge_Object";
260       break;
261     }
262
263     QString aRule = QString( "%0.AddRule( %1, %2, %3, %4, %5 )" ).
264       arg( theCalcCaseName ).arg( anObj1 ).arg( aPriority ).arg( anObj2 ).arg( aMergeType ).arg( aDataTag );
265
266     theScript << aRule;
267   }
268 }
269
270 bool HYDROData_PriorityQueue::GetRule( const TDF_Label& theRulesLab,
271                                        int theIndex, 
272                                        Handle(HYDROData_Entity)&  theObject1,
273                                        HYDROData_PriorityType&    thePriority,
274                                        Handle(HYDROData_Entity)&  theObject2,
275                                        HYDROData_Zone::MergeType& theMergeType )
276 {
277   TDF_Label aRuleLabel = theRulesLab.FindChild( theIndex );
278
279   Handle(TDataStd_ReferenceList) aRefs1, aRefs2;
280   Handle(TDataStd_Integer) aPriorityAttr, aMergeAttr;
281
282   bool isObj1OK = aRuleLabel.FindChild    ( Object1_Tag ). FindAttribute( TDataStd_ReferenceList::GetID(), aRefs1 );
283   bool isPriorityOK = aRuleLabel.FindChild( Priority_Tag ).FindAttribute( TDataStd_Integer::GetID(),       aPriorityAttr );
284   bool isObj2OK = aRuleLabel.FindChild    ( Object2_Tag ). FindAttribute( TDataStd_ReferenceList::GetID(), aRefs2 );
285   bool isMergeOK = aRuleLabel.FindChild   ( Merge_Tag ).   FindAttribute( TDataStd_Integer::GetID(),       aMergeAttr );
286
287   bool isOK = isObj1OK && isPriorityOK && isObj2OK && isMergeOK;
288   if( isOK )
289   {
290     theObject1   = HYDROData_Iterator::Object( aRefs1->First() );
291     thePriority  = ( HYDROData_PriorityType ) aPriorityAttr->Get();
292     theObject2   = HYDROData_Iterator::Object( aRefs2->First() );
293     theMergeType = ( HYDROData_Zone::MergeType ) aMergeAttr->Get();
294   }
295   return isOK;
296 }