0023205: Patch for Naming improvement
[occt.git] / src / TNaming / TNaming_Selector.cxx
CommitLineData
b311480e 1// Created on: 1999-09-30
2// Created by: Denis PASCAL
3// Copyright (c) 1999-1999 Matra Datavision
4// Copyright (c) 1999-2012 OPEN CASCADE SAS
5//
6// The content of this file is subject to the Open CASCADE Technology Public
7// License Version 6.5 (the "License"). You may not use the content of this file
8// except in compliance with the License. Please obtain a copy of the License
9// at http://www.opencascade.org and read it completely before using this file.
10//
11// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
12// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
13//
14// The Original Code and all software distributed under the License is
15// distributed on an "AS IS" basis, without warranty of any kind, and the
16// Initial Developer hereby disclaims all such warranties, including without
17// limitation, any warranties of merchantability, fitness for a particular
18// purpose or non-infringement. Please see the License for the specific terms
19// and conditions governing the rights and limitations under the License.
20
7fd59977 21
22
23#include <TNaming_Selector.ixx>
24#include <TNaming.hxx>
25#include <TNaming_Naming.hxx>
26#include <TNaming_Builder.hxx>
27#include <TNaming_Identifier.hxx>
28#include <TNaming_NameType.hxx>
29#include <TDF_ChildIterator.hxx>
30#include <TDF_Tool.hxx>
31#include <TDF_IDFilter.hxx>
32#include <TNaming_NamingTool.hxx>
33#include <TNaming_NewShapeIterator.hxx>
34
35#include <TopTools_MapOfShape.hxx>
36#include <TopTools_MapIteratorOfMapOfShape.hxx>
37#include <TopTools_ListIteratorOfListOfShape.hxx>
38#include <TopoDS_Iterator.hxx>
39#define BUC60862
40#define OCC273
41#define OCC351
42
43//#define MDTV_DEB_SEL
44#ifdef MDTV_DEB_SEL
45//#define MDTV_DEB_BNP
46#include <TopExp_Explorer.hxx>
47#include <TCollection_AsciiString.hxx>
48#include <TNaming_Tool.hxx>
49#include <BRep_Tool.hxx>
50#include <TopoDS.hxx>
51#include <TNaming_UsedShapes.hxx>
52void PrintEntry(const TDF_Label& label, const Standard_Boolean allLevels)
53{
54 TCollection_AsciiString entry;
55 TDF_Tool::Entry(label, entry);
56 cout << "LabelEntry = "<< entry << endl;
57 if(allLevels) {
58 TDF_ChildIterator it (label, allLevels);
59 for (; it.More(); it.Next()) {
60 TDF_Tool::Entry(it.Value(), entry);
61 cout << "ChildLabelEntry = "<< entry << endl;
62 }
63 }
64}
65#include <BRepTools.hxx>
66static void Write(const TopoDS_Shape& shape,
67 const Standard_CString filename)
68{
69 char buf[256];
70 if(strlen(filename) > 255) return;
71#if defined WNT
72 strcpy_s (buf, filename);
73#else
74 strcpy (buf, filename);
75#endif
76 char* p = buf;
77 while (*p) {
78 if(*p == ':')
79 *p = '-';
80 p++;
81 }
82 ofstream save (buf);
83 if(!save)
84 cout << "File " << buf << " was not created: rdstate = " << save.rdstate() << endl;
85 save << "DBRep_DrawableShape" << endl << endl;
86 if(!shape.IsNull()) BRepTools::Write(shape, save);
87 save.close();
88}
89#endif
90
91#define ORIENTATION_DSOPT
92#ifdef ORIENTATION_DSOPT
93#include <TopTools_MapOfOrientedShape.hxx>
94#include <TopTools_MapIteratorOfMapOfOrientedShape.hxx>
95#include <TDF_ChildIDIterator.hxx>
96#include <TNaming_Tool.hxx>
97#include <TNaming_Iterator.hxx>
98#include <TNaming_OldShapeIterator.hxx>
99//==========================================================================================
100inline static void MapOfOrientedShapes(const TopoDS_Shape& S, TopTools_MapOfOrientedShape& M)
101{
102 M.Add(S);
103 TopoDS_Iterator It(S,Standard_True,Standard_True);
104 while (It.More()) {
105 MapOfOrientedShapes(It.Value(),M);
106 It.Next();
107 }
108}
109//=======================================================================
110static void BuildAtomicMap(const TopoDS_Shape& S, TopTools_MapOfOrientedShape& M)
111{
112 if(S.ShapeType() > TopAbs_COMPSOLID) return;
113 TopoDS_Iterator it(S);
114 for(;it.More();it.Next()) {
115 if(it.Value().ShapeType() > TopAbs_COMPSOLID)
116 M.Add(it.Value());
117 else
118 BuildAtomicMap(it.Value(), M);
119 }
120}
121
122//==========================================================================================
123static const Handle(TNaming_NamedShape) FindPrevNDS(const Handle(TNaming_NamedShape)& CNS)
124{
125 Handle(TNaming_NamedShape) aNS;
126 TNaming_Iterator it(CNS);
127 if(it.More()) {
128 if(!it.OldShape().IsNull()) {
129 aNS = TNaming_Tool::NamedShape(it.OldShape(), CNS->Label());
130 return aNS;
131 }
132 }
133 return aNS;
134}
135
136//==========================================================================================
137// Purpose: checks correspondens between orientation of sub-shapes of Context and orientation
138// of sub-shapes registered in DF and put under result label
139//==========================================================================================
140static Standard_Boolean IsSpecificCase(const TDF_Label& F, const TopoDS_Shape& Context)
141{
142 Standard_Boolean isFound(Standard_False);
143 TopTools_MapOfOrientedShape shapesOfContext;
144 MapOfOrientedShapes(Context,shapesOfContext);
145 Handle(TNaming_NamedShape) CNS = TNaming_Tool::NamedShape(Context, F);
146#ifdef MDTV_DEB_BNP
147 PrintEntry (CNS->Label(),0);
148#endif
149 if(!CNS.IsNull()) {
150 TNaming_ListOfNamedShape aLNS;
151 TDF_ChildIDIterator cit(CNS->Label(), TNaming_NamedShape::GetID(), Standard_False);
152 if(!cit.More()) {
153 // Naming data structure is empty - no sub-shapes under resulting shape
154 const Handle(TNaming_NamedShape) aNS = FindPrevNDS(CNS); //look to old shape data structure if exist
155 if(!aNS.IsNull()) {
156#ifdef MDTV_DEB_BNP
157 PrintEntry (aNS->Label(),0);
158#endif
159 cit.Initialize(aNS->Label(), TNaming_NamedShape::GetID(), Standard_False);
160 } else
161 return Standard_True;
162 }
163
164 for(;cit.More();cit.Next()) {
165 const Handle(TNaming_NamedShape)& NS = Handle(TNaming_NamedShape)::DownCast(cit.Value());
166 if(!NS.IsNull()) {
167 TopoDS_Shape aS = TNaming_Tool::CurrentShape(NS);
168 if(aS.IsNull()) continue;
169#ifdef MDTV_DEB_BNP
170 PrintEntry(NS->Label(), 0);
171 cout <<"ShapeType =" << aS.ShapeType() <<endl;
172 Write (aS, "BNProblem.brep");
173#endif
174 if(aS.ShapeType() != TopAbs_COMPOUND) {//single shape at the child label
175 if(!shapesOfContext.Contains(aS)) {
176 isFound = Standard_True;
177 break;
178 }
179 }
180 else {
181 TopTools_MapOfOrientedShape M;
182 BuildAtomicMap(aS, M);
183 TopTools_MapIteratorOfMapOfOrientedShape it(M);
184 for(;it.More();it.Next()) {
185 if(!shapesOfContext.Contains(it.Key())) {
186#ifdef MDTV_DEB_BNP
187 cout <<"BNProblem: ShapeType in AtomicMap = " << it.Key().ShapeType() << " TShape = " <<it.Key().TShape() <<" OR = " <<it.Key().Orientation() <<endl;
188 Write (it.Key(), "BNProblem_AtomicMap_Item.brep");
189 TopTools_MapIteratorOfMapOfOrientedShape itC(shapesOfContext);
190 for(;itC.More(); itC.Next())
191 cout <<" ShapeType = " << itC.Key().ShapeType() << " TShape = " << itC.Key().TShape() << " OR = " << itC.Key().Orientation() << endl;
192
193#endif
194 isFound = Standard_True;
195 break;
196 }
197 if(isFound) break;
198 }
199 }
200 }
201 }
202 }
203 return isFound;
204}
205
206//==========================================================================================
207static Standard_Boolean IsSpecificCase2(const TDF_Label& F, const TopoDS_Shape& Selection)
208{
209 Standard_Boolean isTheCase(Standard_False);
210 if(Selection.ShapeType() == TopAbs_EDGE) {
211 Handle(TNaming_NamedShape) aNS = TNaming_Tool::NamedShape(Selection, F);
212 if(!aNS.IsNull()) { //presented in DF
213#ifdef MDTV_DEB_BNP
214 PrintEntry (aNS->Label(),0);
215#endif
216 const TopoDS_Shape& aS = TNaming_Tool::CurrentShape(aNS);
217 if(!aS.IsNull() && aS.ShapeType() == Selection.ShapeType()) {
218 if(Selection.Orientation() != aS.Orientation()) {
219 isTheCase = Standard_True;
220 }
221 }
222 }
223 }
224 return isTheCase;
225}
226#endif
227//=======================================================================
228//function : FindGenerated
229//purpose : Finds all generated from the <S>
230//=======================================================================
231
232static void FindGenerated(const Handle(TNaming_NamedShape)& NS, const TopoDS_Shape& S,
233 TopTools_ListOfShape& theList)
234
235{
236 const TDF_Label& LabNS = NS->Label();
237 for (TNaming_NewShapeIterator it (S, LabNS); it.More(); it.Next()) {
238 if (it.Label() == LabNS) {
239 theList.Append(it.Shape());
240 }
241 }
242}
243//=======================================================================
244//function : IsIdentified
245//purpose :
246//=======================================================================
247Standard_Boolean TNaming_Selector::IsIdentified (const TDF_Label& L,
248 const TopoDS_Shape& Selection,
249 Handle(TNaming_NamedShape)& NS,
250 const Standard_Boolean Geometry)
251{
252 TopoDS_Shape Context;
253 Standard_Boolean OnlyOne =!Geometry;
254 TNaming_Identifier Ident(L,Selection,Context,OnlyOne);
255 if (Ident.IsFeature()) {
256 if (!OnlyOne) return Standard_False;
257 else {
258 NS = Ident.FeatureArg();
259
260#ifdef OCC273
261 // mpv : external condition
262 TDF_LabelMap Forbiden,Valid;
263 TopTools_MapOfShape MS;
264 TNaming_NamingTool::CurrentShape(Valid,Forbiden,NS,MS);
265 return (MS.Contains(Selection) && MS.Extent() == 1);
266#else
267 return Standard_True;
268#endif
269 }
270 }
271 else if(Ident.Type() == TNaming_GENERATION) {
272 NS = Ident.NamedShapeOfGeneration();
273 if(!NS.IsNull()) {
274 TDF_LabelMap Forbiden,Valid;
275 TopTools_MapOfShape MS;
276 TNaming_NamingTool::CurrentShape(Valid,Forbiden,NS,MS);
277 if(MS.Contains(Selection) && MS.Extent() == 1) {
278 const TopoDS_Shape& aS = Ident.ShapeArg();
279 TopTools_ListOfShape aList;
280 FindGenerated(NS, aS, aList);
281 Ident.NextArg();
282 while(Ident.MoreArgs()) {
283 const TopoDS_Shape& aS = Ident.ShapeArg();
284 FindGenerated(NS, aS, aList);
285 Ident.NextArg();
286 }
287 TopTools_MapIteratorOfMapOfShape itm(MS);
288 const TopoDS_Shape& aC = itm.Key();
289 Standard_Boolean isEq(Standard_False);
290 TopTools_ListIteratorOfListOfShape itl(aList);
291 for(;itl.More();itl.Next()) {
292 if(itl.Value() == aC)
293 isEq = Standard_True;
294 else {
295 isEq = Standard_False;
296 break;
297 }
298 }
299 return isEq;
300 }
301 } else
302 return Standard_False;
303 }
304 return Standard_False;
305}
306
307//=======================================================================
308//function : TNaming_Selector
309//purpose :
310//=======================================================================
311
312TNaming_Selector::TNaming_Selector (const TDF_Label& L)
313{
314 myLabel = L;
315}
316
317//=======================================================================
318//function : Select
319//purpose :
320//=======================================================================
321Standard_Boolean TNaming_Selector::Select (const TopoDS_Shape& Selection,
322 const TopoDS_Shape& Context,
323 const Standard_Boolean Geometry,
324 const Standard_Boolean KeepOrientation) const
325{
326 myLabel.ForgetAllAttributes();
327 Handle(TNaming_NamedShape)NS;
328 Standard_Boolean aKeepOrientation((Selection.ShapeType() == TopAbs_VERTEX) ? Standard_False : KeepOrientation);
329 if(Selection.ShapeType() == TopAbs_COMPOUND) {
330 Standard_Boolean isVertex(Standard_True);
331 TopoDS_Iterator it(Selection);
332 for(;it.More();it.Next())
333 if(it.Value().ShapeType() != TopAbs_VERTEX) {
334 isVertex = Standard_False;
335 break;
336 }
337 if(isVertex) aKeepOrientation = Standard_False;
338 }
339 /*
340 // for debug opposite orientation
341 TopoDS_Shape selection;
342 Standard_Boolean found(Standard_False);
343 TopExp_Explorer exp(Context,TopAbs_EDGE);
344 for(;exp.More();exp.Next()) {
345 TopoDS_Shape E = exp.Current();
346 if(E.IsSame(Selection) && E.Orientation() != Selection.Orientation()) {
347 selection = E;
348 found = Standard_True;
349 cout <<" FOUND: Entity orientation = " << selection.Orientation() <<endl;
350 }
351 }
352 if (!found)
353 selection = Selection;
354 */
355
356#ifdef MDTV_DEB_SEL
357 cout << "SELECTION ORIENTATION = " << Selection.Orientation() <<", TShape = " << Selection.TShape() <<endl;
358 //cout << "SELECTION ORIENTATION = " << selection.Orientation() <<", TShape = " << selection.TShape() <<endl;
359 PrintEntry(myLabel, 0);
360 TNaming::Print(myLabel, cout);
361#endif
362
363 if(aKeepOrientation) {
364#ifdef ORIENTATION_DSOPT
365 const Standard_Boolean aBNproblem = IsSpecificCase(myLabel, Context) || IsSpecificCase2(myLabel, Selection);
366
367 NS = TNaming_Naming::Name (myLabel,Selection,Context,Geometry,aKeepOrientation,aBNproblem);
368#else
369 NS = TNaming_Naming::Name (myLabel,Selection,Context,Geometry,aKeepOrientation);
370#endif
371 }
372 else
373 if (!IsIdentified (myLabel,Selection,NS,Geometry)) {
374 NS = TNaming_Naming::Name (myLabel,Selection,Context,Geometry,aKeepOrientation);
375 }
376 if (NS.IsNull()) return Standard_False;
377 //
378 // namedshape with SELECTED Evolution
379 //
380 TNaming_Builder B (myLabel);
381#ifdef OCC351
382 // mpv: if oldShape for selection is some shape from used map of shapes,
383 // then naming structure becomes more complex, can be cycles
384 const TopoDS_Shape& aSelection = TNaming_Tool::CurrentShape(NS); //szy
385#ifdef MDTV_DEB_CHECK_TYPE
386 if(!Selection.IsSame(aSelection) && Selection.ShapeType() != TopAbs_COMPOUND) {
387 TCollection_AsciiString entry;
388 TDF_Tool::Entry(NS->Label(), entry);
389 cout << "Selection is Not Same (NSLabel = " <<entry<<"): " << "TShape1 = " <<
390 Selection.TShape()->This() << " TShape2 = " <<aSelection.TShape()->This() <<endl;
391 }
392#endif
393 if(aSelection.ShapeType() == TopAbs_COMPOUND && aSelection.ShapeType() != Selection.ShapeType())
394 B.Select(aSelection,aSelection); // type migration
395 else
396 B.Select(Selection,Selection);
397#else
398 B.Select(Selection,Context);
399#endif
400 //
401 // naming with IDENTITY NameType
402 //
403 Handle(TNaming_Naming) N = new TNaming_Naming ();
404 N->ChangeName().Type(TNaming_IDENTITY);
405 N->ChangeName().Append(NS);
406
407#ifdef BUC60862
408// inserted by vro 06.09.00:
409 N->ChangeName().ShapeType(Selection.ShapeType());
410#endif
411
412 myLabel.AddAttribute(N);
413 return Standard_True;
414}
415
416//=======================================================================
417//function : Select
418//purpose :
419//=======================================================================
420Standard_Boolean TNaming_Selector::Select (const TopoDS_Shape& Selection,
421 const Standard_Boolean Geometry,
422 const Standard_Boolean KeepOrientation) const
423{
424 // we give a Null shape. How to guess what is the good context ?
425 TopoDS_Shape Context;
426// return Select (Selection,Context,Geometry);
427// temporary!!!
428 return Select (Selection,Selection,Geometry, KeepOrientation);
429
430}
431
432//=======================================================================
433//function : Solve
434//purpose :
435//=======================================================================
436Standard_Boolean TNaming_Selector::Solve (TDF_LabelMap& Valid) const
437{
438 Handle(TNaming_Naming) name;
439#ifdef MDTV_DEB_SEL
440 cout <<"TNaming_Selector::Solve==> ";
441 PrintEntry(myLabel,0);
442#endif
443 if (myLabel.FindAttribute(TNaming_Naming::GetID(),name)) {
444 return name->Solve(Valid);
445 }
446 return Standard_False;
447}
448
449//=======================================================================
450//function : Arguments
451//purpose :
452//=======================================================================
453void TNaming_Selector::Arguments (TDF_AttributeMap& args) const
454{
455 TDF_Tool::OutReferences(myLabel,args);
456}
457
458//=======================================================================
459//function : TNaming_Selector
460//purpose :
461//=======================================================================
462
463Handle(TNaming_NamedShape) TNaming_Selector::NamedShape() const
464{
465 Handle(TNaming_NamedShape) NS;
466 myLabel.FindAttribute(TNaming_NamedShape::GetID(),NS);
467 return NS;
468}