0026155: TNaming, CurrentShape: order of shapes in Modification compound is unpredictable
[occt.git] / src / TNaming / TNaming_NamingTool.cxx
1 // Created on: 2000-02-14
2 // Created by: Denis PASCAL
3 // Copyright (c) 2000-2014 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16 #include <TNaming_NamingTool.ixx>
17 #include <TNaming_Tool.hxx>
18 #include <TNaming_NewShapeIterator.hxx> 
19 #include <TNaming_Iterator.hxx>
20 #include <TNaming_OldShapeIterator.hxx>
21 #include <TNaming_Tool.hxx>
22 #include <TNaming_Naming.hxx>
23 #include <TDF_ChildIterator.hxx>
24
25 #ifdef OCCT_DEBUG_DESC
26 #include <TCollection_AsciiString.hxx>
27 #include <TDF_Tool.hxx>
28 #include <BRepTools.hxx>
29 static void WriteS(const TopoDS_Shape& shape,
30                       const Standard_CString filename) 
31 {
32   char buf[256];
33   if(strlen(filename) > 255) return;
34 #ifdef WNT
35   strcpy_s (buf, filename);
36 #else
37   strcpy (buf, filename);
38 #endif
39   char* p = buf;
40   while (*p) {
41     if(*p == ':')
42       *p = '-';
43     p++;
44   }
45   ofstream save (buf);
46   if(!save) 
47     cout << "File " << buf << " was not created: rdstate = " << save.rdstate() << endl;
48   save << "DBRep_DrawableShape" << endl << endl;
49   if(!shape.IsNull()) BRepTools::Write(shape, save);
50   save.close();
51 }
52 #endif
53
54 //=======================================================================
55 //function : IsForbiden
56 //purpose  : ANaming voir NamingTool
57 //=======================================================================
58
59 static Standard_Boolean IsForbiden(const TDF_LabelMap& Forbiden,
60                                    const TDF_Label&    Lab)
61 {
62   if (Lab.IsRoot()) {
63     return Standard_False;
64   }
65   if (Forbiden.Contains(Lab)) 
66     return Standard_True;
67   else {
68     return IsForbiden(Forbiden,Lab.Father());
69   }
70 }
71
72 //=======================================================================
73 //function : LastModif 
74 //purpose  : ANaming 
75 //=======================================================================
76 static void LastModif(      TNaming_NewShapeIterator& it,
77                       const TopoDS_Shape&             S,
78                       TopTools_IndexedMapOfShape&     MS,
79                       const TDF_LabelMap&             Updated,
80                       const TDF_LabelMap&             Forbiden)
81
82   Standard_Boolean YaModif = Standard_False;
83   for (; it.More(); it.Next()) {
84     const TDF_Label&    Lab = it.Label();
85 #ifdef OCCT_DEBUG_DESC
86     TCollection_AsciiString entry;
87     TDF_Tool::Entry(Lab, entry);
88     cout << "NamingTool:: LastModif LabelEntry = "<< entry <<  endl;
89 #endif
90     if (!Updated.IsEmpty() && !Updated.Contains(Lab))  continue;
91     if (IsForbiden(Forbiden, Lab))                     continue; 
92     if (it.IsModification()) {
93       YaModif = Standard_True;
94       TNaming_NewShapeIterator it2(it);
95       if (!it2.More()) {
96         const TopoDS_Shape& S   = it.Shape();
97         MS.Add (S);  // Modified
98       }
99       else
100         LastModif(it2,it.Shape(),MS,Updated,Forbiden);
101     } 
102   }
103   if (!YaModif) 
104     MS.Add(S);    
105 }
106 //=======================================================================
107 static void ApplyOrientation (TopTools_IndexedMapOfShape& MS, 
108                               const TopAbs_Orientation OrientationToApply)
109 {
110 #ifdef OCCT_DEBUG_APPLY
111  if (!MS.IsEmpty ()) {
112    cout <<"OrientationToApply = " <<OrientationToApply <<endl;
113    for (Standard_Integer anItMS1 = 1; anItMS1 <= MS.Extent(); ++anItMS1) {
114      cout << "ApplyOrientation: TShape = " << MS (anItMS1).TShape()->This() << " OR = " << MS (anItMS1).Orientation() <<endl;
115    }
116  }
117 #endif
118   for (Standard_Integer anItMS = 1; anItMS <= MS.Extent(); ++anItMS)
119   {
120     MS.Substitute (anItMS, MS (anItMS).Oriented (OrientationToApply));
121   }
122 }
123 //=======================================================================
124 //function : CurrentShape
125 //purpose  : ANaming
126 //=======================================================================
127 void TNaming_NamingTool::CurrentShape(const TDF_LabelMap&               Valid,
128                                       const TDF_LabelMap&               Forbiden,
129                                       const Handle(TNaming_NamedShape)& Att,
130                                       TopTools_IndexedMapOfShape& MS)
131 {
132   TDF_Label Lab = Att->Label();
133 #ifdef OCCT_DEBUG_DESC
134     TCollection_AsciiString entry;
135     TDF_Tool::Entry(Lab, entry);
136     cout << "NamingTool:: LabelEntry = "<< entry <<  endl;
137 #endif
138   if (!Valid.IsEmpty() && !Valid.Contains(Lab)) {
139 #ifdef OCCT_DEBUG_DESC
140     TCollection_AsciiString entry;
141     TDF_Tool::Entry(Lab, entry);
142     cout << "NamingTool:: LabelEntry = "<< entry << " is out of Valid map" <<  endl;
143 #endif
144     return;
145   }
146
147   TNaming_Iterator itL (Att);
148   for (; itL.More(); itL.Next()) {
149     const TopoDS_Shape& S = itL.NewShape();
150     if (S.IsNull()) continue;
151 #ifdef OCCT_DEBUG_DESC
152     WriteS(S, "CS_NewShape.brep");
153     if(itL.OldShape().IsNull())
154       cout <<"OldShape is Null" <<endl;
155     else 
156         WriteS(itL.OldShape(), "CS_OldShape.brep");
157 #endif
158     Standard_Boolean YaOrientationToApply(Standard_False);
159     TopAbs_Orientation OrientationToApply(TopAbs_FORWARD);
160     if(Att->Evolution() == TNaming_SELECTED) {
161       if (itL.More() && itL.NewShape().ShapeType() != TopAbs_VERTEX) {//OR-N
162                 Handle (TNaming_Naming)  aNaming;
163                 Lab.FindAttribute(TNaming_Naming::GetID(), aNaming);
164                 if(!aNaming.IsNull()) {
165                   if(aNaming->GetName().Type() == TNaming_ORIENTATION) {
166                          OrientationToApply = aNaming->GetName().Orientation();
167                   } else {
168                 Handle (TNaming_Naming)  aNaming2;
169                         TDF_ChildIterator it(aNaming->Label());
170                         for(;it.More();it.Next()) {
171                           const TDF_Label& aLabel = it.Value();
172                           aLabel.FindAttribute(TNaming_Naming::GetID(), aNaming2);
173                   if(!aNaming2.IsNull()) {
174                             if(aNaming2->GetName().Type() == TNaming_ORIENTATION) {
175                                   OrientationToApply = aNaming2->GetName().Orientation();
176                                   break;
177                                 }
178                           }
179                         }
180                   }
181                   if(OrientationToApply == TopAbs_FORWARD || OrientationToApply == TopAbs_REVERSED)
182                         YaOrientationToApply = Standard_True;                   
183                 }
184           } //
185     }
186     TNaming_NewShapeIterator it(itL);
187     if (!it.More()) {
188       if (YaOrientationToApply)
189         MS.Add(S.Oriented(OrientationToApply));
190       else
191         MS.Add(S);
192     }
193     else {      
194 //     LastModif(it, S, MS, Valid, Forbiden);
195       TopTools_IndexedMapOfShape MS2; 
196       LastModif(it, S, MS2, Valid, Forbiden);
197       if (YaOrientationToApply) ApplyOrientation (MS2, OrientationToApply);//the solution to be refined
198       for (Standard_Integer anItMS2 = 1; anItMS2 <= MS2.Extent(); ++anItMS2)
199         MS.Add (MS2 (anItMS2));
200     }
201   }
202 }
203
204 //=======================================================================
205 //function : CurrentShapeFromShape
206 //purpose  : ANaming
207 //=======================================================================
208              
209 void TNaming_NamingTool::CurrentShapeFromShape(const TDF_LabelMap&               Valid,
210                                                const TDF_LabelMap&               Forbiden,
211                                                const TDF_Label&                  Acces,
212                                                const TopoDS_Shape&               S,
213                                                TopTools_IndexedMapOfShape&       MS)
214 {
215   TNaming_NewShapeIterator it(S,Acces);
216
217   Handle(TNaming_NamedShape) NS = it.NamedShape(); 
218   if(!NS.IsNull() && NS->Evolution() == TNaming_SELECTED)
219     MS.Add(TNaming_Tool::GetShape(NS));
220   else {
221     if (!it.More()) 
222       MS.Add(S);
223     else 
224       LastModif(it, S, MS, Valid, Forbiden);
225   }
226 }
227
228 //=======================================================================
229 //function : MakeDescendants
230 //purpose  : ANaming
231 //=======================================================================
232
233 static void MakeDescendants (TNaming_NewShapeIterator&         it,
234                              TDF_LabelMap&                     Descendants)
235 {
236   for (; it.More(); it.Next()) {
237     Descendants.Add(it.Label());
238 #ifdef OCCT_DEBUG_DESC
239     TCollection_AsciiString entry;
240     TDF_Tool::Entry(it.Label(), entry);
241     cout<< "MakeDescendants: Label = " <<entry <<endl;
242 #endif
243     if (!it.Shape().IsNull()) {
244       TNaming_NewShapeIterator it2(it);
245       MakeDescendants (it2,Descendants);
246     }
247   }
248 }
249 //=======================================================================
250 void BuildDescendants2 (const Handle(TNaming_NamedShape)& NS, const TDF_Label& ForbLab, TDF_LabelMap& Descendants)
251 {
252   if (NS.IsNull()) return;
253   TNaming_NewShapeIterator it(NS); 
254   for(;it.More();it.Next()) {
255     if(!it.NamedShape().IsNull()) {
256 #ifdef OCCT_DEBUG_DESC
257       TCollection_AsciiString entry;
258       TDF_Tool::Entry(it.Label(), entry);
259       cout<< "MakeDescendants2: Label = " <<entry <<endl;
260 #endif      
261       if(ForbLab == it.Label()) continue;
262       Descendants.Add(it.Label());
263       TNaming_NewShapeIterator it2(it); 
264       MakeDescendants (it2,Descendants); 
265     }
266   }
267 }
268 //=======================================================================
269 //function : BuildDescendants
270 //purpose  : ANaming
271 //=======================================================================
272
273 void TNaming_NamingTool::BuildDescendants (const Handle(TNaming_NamedShape)& NS,
274                                            TDF_LabelMap&                     Descendants)
275 {
276   if (NS.IsNull()) return;
277   Descendants.Add(NS->Label());
278   TNaming_NewShapeIterator it(NS); 
279 #ifdef OCCT_DEBUG_DESC
280     TCollection_AsciiString entry;
281     TDF_Tool::Entry(NS->Label(), entry);
282     cout<< "MakeDescendants: Label = " <<entry <<endl;
283 #endif
284   MakeDescendants (it,Descendants);
285   TNaming_OldShapeIterator it2(NS); 
286   for (; it2.More(); it2.Next()) {
287     if(!it2.Shape().IsNull()) {
288       Handle(TNaming_NamedShape) ONS = TNaming_Tool::NamedShape(it2.Shape(), NS->Label());
289       if(!ONS.IsNull()) {
290 #ifdef OCCT_DEBUG_DESC
291         TCollection_AsciiString entry;
292         TDF_Tool::Entry(ONS->Label(), entry);
293         cout<< "MakeDescendants_Old: Label = " <<entry <<endl;    
294 #endif
295         BuildDescendants2(ONS, NS->Label(), Descendants);
296       }
297     }  
298   }
299 }