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