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