3e707d5d2be002e164d0a68afc6d14a58c74227f
[occt.git] / src / QANewBRepNaming / QANewBRepNaming_BooleanOperationFeat.cxx
1 // Created on: 1999-09-27
2 // Created by: Sergey ZARITCHNY
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
21 #include <QANewBRepNaming_BooleanOperationFeat.ixx>
22 #include <Standard_NullObject.hxx>
23 #include <Precision.hxx>
24 #include <TColgp_Array1OfPnt.hxx>
25 #include <TColStd_Array1OfInteger.hxx>
26 #include <TopTools_Array1OfShape.hxx>
27 #include <TColgp_Array1OfDir.hxx>
28 #include <BRep_Tool.hxx>
29 #include <BRepGProp.hxx>
30 #include <GProp_GProps.hxx>
31 #include <BRepAdaptor_Surface.hxx>
32 #include <BRep_Tool.hxx>
33 #include <Adaptor3d_HCurve.hxx>
34 #include <gp_Cylinder.hxx>
35 #include <gp_Cone.hxx>
36 #include <GeomAbs_SurfaceType.hxx>
37 #include <Geom_Ellipse.hxx>
38 #include <TopExp_Explorer.hxx>
39 #include <TopoDS_Iterator.hxx>
40 #include <TopoDS_Vertex.hxx>
41 #include <TopoDS_Edge.hxx>
42 #include <TopoDS.hxx>
43 #include <TopExp.hxx>
44 #include <TopTools_ListIteratorOfListOfShape.hxx>
45 #include <TopTools_IndexedMapOfShape.hxx>
46 #include <TopTools_MapOfShape.hxx>
47 #include <TDF_Label.hxx>
48 #include <TDF_TagSource.hxx>
49 #include <TDataStd_Integer.hxx>
50 #include <TDataStd_Real.hxx>
51 #include <TDataStd_IntegerArray.hxx>
52 #include <TDataStd_Name.hxx>
53 #include <TNaming_Builder.hxx>
54 #include <TNaming_NamedShape.hxx>
55 #include <gp.hxx>
56
57 #include <QANewBRepNaming_Loader.hxx>
58
59 #ifdef DEB
60 #include <TDataStd_Name.hxx>
61 #endif
62
63 #ifdef DEB
64 #include <TCollection_AsciiString.hxx>
65 #include <TDF_Tool.hxx>
66 #include <BRepTools.hxx>
67 #include <TNaming_Tool.hxx>
68 static void ModDbgTools_Write(const TopoDS_Shape& shape,
69                       const Standard_CString filename) 
70 {
71   ofstream save;
72   save.open(filename);
73   save << "DBRep_DrawableShape" << endl << endl;
74   if(!shape.IsNull()) BRepTools::Write(shape, save);
75   save.close();
76 }
77
78 static void ModDbgTools_WriteCurrentShape(const Handle(TNaming_NamedShape) & NS)
79 {
80   TCollection_AsciiString entry;
81   TDF_Tool::Entry(NS->Label(), entry);
82   if (!NS.IsNull())
83     {
84       TopoDS_Shape Sh = TNaming_Tool::CurrentShape (NS);
85       if(!Sh.IsNull()) {
86         TCollection_AsciiString Entry = entry.Cat("_Cur.brep");
87         ModDbgTools_Write(Sh, Entry.ToCString());
88       }
89       else 
90         cout << "ModDbgTools::Write>>> TopoDS_Shape IS NULL on Entry = "<< entry << endl;
91     }
92   else
93     cout << "ModDbgTools::Write>>>  CurrentShape of TNaming_NamedShape IS NULL on Entry = "<< entry << endl;
94 }
95 #endif
96
97 //=======================================================================
98 //function : QANewBRepNaming_BooleanOperationFeat
99 //purpose  : 
100 //=======================================================================
101
102 QANewBRepNaming_BooleanOperationFeat::QANewBRepNaming_BooleanOperationFeat() {}
103
104 //=======================================================================
105 //function : QANewBRepNaming_BooleanOperationFeat
106 //purpose  : 
107 //=======================================================================
108
109 QANewBRepNaming_BooleanOperationFeat::QANewBRepNaming_BooleanOperationFeat(const TDF_Label& ResultLabel):QANewBRepNaming_TopNaming(ResultLabel) {}
110
111 //=======================================================================
112 //function : Init
113 //purpose  : 
114 //=======================================================================
115
116 void QANewBRepNaming_BooleanOperationFeat::Init(const TDF_Label& ResultLabel) {  
117   if(ResultLabel.IsNull()) 
118     Standard_NullObject::Raise("QANewBRepNaming_BooleanOperationFeat::Init The Result label is Null ..."); 
119   myResultLabel = ResultLabel; 
120 }
121
122 //=======================================================================
123 //function : ModifiedFaces
124 //purpose  : 
125 //=======================================================================
126
127 TDF_Label QANewBRepNaming_BooleanOperationFeat::ModifiedFaces() const {
128 #ifdef DEB
129   const TDF_Label& ModifiedFacesLabel = ResultLabel().NewChild();
130   TDataStd_Name::Set(ModifiedFacesLabel, "ModifiedFaces");
131   return ModifiedFacesLabel;
132 #endif
133   return ResultLabel().NewChild();
134 }
135
136 //=======================================================================
137 //function : ModifiedEdges
138 //purpose  : 
139 //=======================================================================
140
141 TDF_Label QANewBRepNaming_BooleanOperationFeat::ModifiedEdges() const {
142 #ifdef DEB
143   const TDF_Label& ModifiedEdgesLabel = ResultLabel().NewChild();
144   TDataStd_Name::Set(ModifiedEdgesLabel, "ModifiedEdges");
145   return ModifiedEdgesLabel;
146 #endif
147   return ResultLabel().NewChild();
148 }
149
150 //=======================================================================
151 //function : DeletedFaces
152 //purpose  : 
153 //=======================================================================
154
155 TDF_Label QANewBRepNaming_BooleanOperationFeat::DeletedFaces() const {
156 #ifdef DEB
157   const TDF_Label& DeletedFacesLabel = ResultLabel().NewChild();
158   TDataStd_Name::Set(DeletedFacesLabel, "DeletedFaces");
159   return DeletedFacesLabel;
160 #endif
161   return ResultLabel().NewChild();
162 }
163
164 //=======================================================================
165 //function : DeletedEdges
166 //purpose  : 
167 //=======================================================================
168
169 TDF_Label QANewBRepNaming_BooleanOperationFeat::DeletedEdges() const {
170 #ifdef DEB
171   const TDF_Label& DeletedEdgesLabel = ResultLabel().NewChild();
172   TDataStd_Name::Set(DeletedEdgesLabel, "DeletedEdges");
173   return DeletedEdgesLabel;
174 #endif
175   return ResultLabel().NewChild();
176 }
177
178 //=======================================================================
179 //function : DeletedVertices
180 //purpose  : 
181 //=======================================================================
182
183 TDF_Label QANewBRepNaming_BooleanOperationFeat::DeletedVertices() const {
184 #ifdef DEB
185   const TDF_Label& DeletedVerticesLabel = ResultLabel().NewChild();
186   TDataStd_Name::Set(DeletedVerticesLabel, "DeletedVertices");
187   return DeletedVerticesLabel;
188 #endif
189   return ResultLabel().NewChild();
190 }
191
192 //=======================================================================
193 //function : NewShapes
194 //purpose  : 
195 //=======================================================================
196
197 TDF_Label QANewBRepNaming_BooleanOperationFeat::NewShapes() const {
198 #ifdef DEB
199   const TDF_Label& NewShapesLabel = ResultLabel().NewChild();
200   TDataStd_Name::Set(NewShapesLabel, "NewShapes");
201   return NewShapesLabel;
202 #endif
203   return ResultLabel().NewChild();
204 }
205
206 //=======================================================================
207 //function : Content
208 //purpose  : 
209 //=======================================================================
210
211 TDF_Label QANewBRepNaming_BooleanOperationFeat::Content() const {
212 #ifdef DEB
213   const TDF_Label& ContentLabel = ResultLabel().NewChild();
214   TDataStd_Name::Set(ContentLabel, "Content");
215   return ContentLabel;
216 #endif
217   return ResultLabel().NewChild();
218 }
219
220 //=======================================================================
221 //function : DeletedDegeneratedEdges
222 //purpose  : 
223 //=======================================================================
224
225 TDF_Label QANewBRepNaming_BooleanOperationFeat::DeletedDegeneratedEdges() const {
226 #ifdef DEB
227   const TDF_Label& DegeneratedLabel = ResultLabel().NewChild();
228   TDataStd_Name::Set(DegeneratedLabel, "DeletedDegeneratedEdges");
229   return DegeneratedLabel;
230 #endif
231   return ResultLabel().NewChild();
232 }
233
234 //=======================================================================
235 //function : ShapeType
236 //purpose  : 
237 //=======================================================================
238
239 TopAbs_ShapeEnum QANewBRepNaming_BooleanOperationFeat::ShapeType(const TopoDS_Shape& theShape) {
240   TopAbs_ShapeEnum TypeSh = theShape.ShapeType();
241   if (TypeSh == TopAbs_COMPOUND || TypeSh == TopAbs_COMPSOLID) {
242     TopoDS_Iterator itr(theShape);
243     if (!itr.More()) return TypeSh; 
244     TypeSh = ShapeType(itr.Value());
245     if(TypeSh == TopAbs_COMPOUND) return TypeSh;
246     itr.Next();
247     for(; itr.More(); itr.Next()) 
248       if(ShapeType(itr.Value()) != TypeSh) return TopAbs_COMPOUND;      
249   }
250   return TypeSh;
251
252
253 //=======================================================================
254 //function : GetShape
255 //purpose  : 
256 //=======================================================================
257
258 TopoDS_Shape QANewBRepNaming_BooleanOperationFeat::GetShape(const TopoDS_Shape& theShape) const {
259   if (theShape.ShapeType() == TopAbs_COMPOUND || theShape.ShapeType() == TopAbs_COMPSOLID) {
260     TopoDS_Iterator itr(theShape);
261     if (itr.More()) return itr.Value();
262   }
263   return theShape;
264 }
265
266 //=======================================================================
267 //function : LoadWire
268 //purpose  : 
269 //=======================================================================
270
271 void QANewBRepNaming_BooleanOperationFeat::LoadWire(BRepAlgoAPI_BooleanOperation& MS) const {
272   // Naming of modified edges:
273   TNaming_Builder ModBuilder(ModifiedEdges());
274   QANewBRepNaming_Loader::LoadModifiedShapes (MS, MS.Shape1(), TopAbs_EDGE, ModBuilder);
275
276   // load generated vertexes
277   if(MS.HasGenerated()) {  
278     TNaming_Builder nBuilder (NewShapes());
279     QANewBRepNaming_Loader::LoadGeneratedShapes (MS, MS.Shape1(), TopAbs_EDGE, nBuilder);
280     QANewBRepNaming_Loader::LoadGeneratedShapes (MS, MS.Shape2(), TopAbs_FACE, nBuilder);
281   }
282   // Naming of deleted edges, dangle vertices
283   if(MS.HasDeleted()){ 
284     TNaming_Builder DelEBuilder(DeletedEdges());
285     QANewBRepNaming_Loader::LoadDeletedShapes(MS, MS.Shape1(), TopAbs_EDGE, DelEBuilder);
286     TNaming_Builder DelVBuilder(DeletedVertices());
287     QANewBRepNaming_Loader::LoadDeletedShapes(MS, MS.Shape1(), TopAbs_VERTEX, DelEBuilder);
288   }
289  }
290
291 //=======================================================================
292 //function : LoadShell
293 //purpose  : 
294 //=======================================================================
295
296 void QANewBRepNaming_BooleanOperationFeat::LoadShell(BRepAlgoAPI_BooleanOperation& MS) const {
297 // Naming of modified faces and dangle edges
298   TNaming_Builder ModFBuilder(ModifiedFaces());
299   QANewBRepNaming_Loader::LoadModifiedShapes(MS, MS.Shape1(), TopAbs_FACE, ModFBuilder);
300   TNaming_Builder ModEBuilder(ModifiedEdges());    
301   QANewBRepNaming_Loader::LoadModifiedShapes(MS, MS.Shape1(), TopAbs_EDGE, ModEBuilder);
302   
303   if(MS.HasGenerated()) {  
304     TNaming_Builder nBuilder (NewShapes());
305 //  generated Edges
306     QANewBRepNaming_Loader::LoadGeneratedShapes (MS, MS.Shape2(), TopAbs_FACE, nBuilder);
307     QANewBRepNaming_Loader::LoadGeneratedShapes (MS, MS.Shape1(), TopAbs_FACE, nBuilder);
308   }
309   // Naming of deleted faces edges:
310   if(MS.HasDeleted()){ 
311     TNaming_Builder DelFBuilder(DeletedFaces());
312     QANewBRepNaming_Loader::LoadDeletedShapes(MS, MS.Shape1(), TopAbs_FACE, DelFBuilder);
313
314     TNaming_Builder DelEBuilder(DeletedEdges());
315     QANewBRepNaming_Loader::LoadDeletedShapes(MS, MS.Shape1(), TopAbs_EDGE, DelEBuilder);
316   }
317 }
318
319 //=======================================================================
320 //function : LoadContent
321 //purpose  : 
322 //=======================================================================
323
324 void QANewBRepNaming_BooleanOperationFeat::LoadContent(BRepAlgoAPI_BooleanOperation& MS) const {
325   if (MS.Shape().ShapeType() == TopAbs_COMPSOLID || MS.Shape().ShapeType() == TopAbs_COMPOUND) {
326     TopoDS_Iterator itr(MS.Shape());
327     Standard_Integer nbShapes = 0;
328     while (itr.More()) {
329       nbShapes++;
330       itr.Next();
331     }
332     if (nbShapes > 1) {
333       for (itr.Initialize(MS.Shape()); itr.More(); itr.Next()) {
334         TNaming_Builder bContent(Content());
335         bContent.Generated(itr.Value());      
336       }
337     }
338   } 
339 }  
340
341 //=======================================================================
342 //function : LoadResult
343 //purpose  : 
344 //=======================================================================
345
346 void QANewBRepNaming_BooleanOperationFeat::LoadResult(BRepAlgoAPI_BooleanOperation& MS) const {
347   Handle(TDF_TagSource) Tagger = TDF_TagSource::Set(ResultLabel());
348   if (Tagger.IsNull()) return;
349   Tagger->Set(0);
350   TNaming_Builder Builder (ResultLabel());
351   TopoDS_Shape aResult = MS.Shape();
352   if (aResult.ShapeType() == TopAbs_COMPOUND) {
353     Standard_Integer nbSubResults = 0;
354     TopoDS_Iterator itr(aResult);
355     for (; itr.More(); itr.Next()) nbSubResults++;
356     if (nbSubResults == 1) {
357       itr.Initialize(aResult);
358       if (itr.More()) aResult = itr.Value();
359     }
360   }
361   if (MS.Shape1().IsNull()) Builder.Generated(aResult);
362   else Builder.Modify(MS.Shape1(), aResult);  
363 }
364
365 //=======================================================================
366 //function : LoadDegenerated
367 //purpose  : 
368 //=======================================================================
369
370 void QANewBRepNaming_BooleanOperationFeat::LoadDegenerated(BRepAlgoAPI_BooleanOperation& MS) const {
371   TopTools_IndexedMapOfShape allEdges;
372   TopExp::MapShapes(MS.Shape1(), TopAbs_EDGE, allEdges);
373   Standard_Integer i = 1;
374   for (; i <= allEdges.Extent(); i++) {
375     if (BRep_Tool::Degenerated(TopoDS::Edge(allEdges.FindKey(i)))) {
376       if (MS.IsDeleted(allEdges.FindKey(i))) {
377         TNaming_Builder DegeneratedBuilder(DeletedDegeneratedEdges()); 
378         DegeneratedBuilder.Generated(allEdges.FindKey(i));
379 #ifdef DEB
380         TDataStd_Name::Set(DegeneratedBuilder.NamedShape()->Label(), "DeletedDegenerated");
381 #endif
382       }      
383     }
384   }
385 }
386
387 //=======================================================================
388 //function : IsResultChanged
389 //purpose  : 
390 //=======================================================================
391
392 Standard_Boolean QANewBRepNaming_BooleanOperationFeat::IsResultChanged(BRepAlgoAPI_BooleanOperation& MS) const {
393   TopoDS_Shape ResSh = MS.Shape();
394   if (MS.Shape().ShapeType() == TopAbs_COMPOUND) {
395     Standard_Integer nbSubResults = 0;
396     TopoDS_Iterator itr(MS.Shape());
397     for (; itr.More(); itr.Next()) nbSubResults++;
398     if (nbSubResults == 1) {
399       itr.Initialize(MS.Shape());
400       if (itr.More()) ResSh = itr.Value();
401     }
402   }
403   return MS.Shape1().IsSame(ResSh);
404 }
405 //=======================================================================
406 // Workaround for evolution 1:n
407 //=======================================================================
408 static Standard_Boolean IsValidSurfType(const TopoDS_Face& theFace) {
409   BRepAdaptor_Surface anAdapt(theFace);
410   Handle( Adaptor3d_HCurve ) aBasisCurve;
411   const GeomAbs_SurfaceType& aType = anAdapt.GetType();
412   if(aType == GeomAbs_Cylinder || aType == GeomAbs_Cone)
413     return Standard_True;
414   else if(aType == GeomAbs_SurfaceOfRevolution){
415     aBasisCurve = anAdapt.BasisCurve();
416     if (aBasisCurve->GetType() == GeomAbs_Line)
417       return Standard_True;
418   }
419   else if(aType == GeomAbs_SurfaceOfExtrusion) {
420     aBasisCurve = anAdapt.BasisCurve();
421     if (aBasisCurve->GetType() == GeomAbs_Circle || aBasisCurve->GetType() == GeomAbs_Ellipse)
422       return Standard_True;
423   }
424 #ifdef DEB
425   ModDbgTools_Write(theFace, "Surf");
426 #endif
427   return Standard_False;
428 }
429 //=======================================================================
430 //function : IsWRCase
431 //purpose  : 
432 //=======================================================================
433
434 Standard_Boolean QANewBRepNaming_BooleanOperationFeat::IsWRCase(const BRepAlgoAPI_BooleanOperation& MS) {
435   const TopoDS_Shape& ObjSh = MS.Shape1();
436   const TopoDS_Shape& ToolSh = MS.Shape2();
437   const TopAbs_ShapeEnum& Type1 = ShapeType(ObjSh);
438   if(Type1  == TopAbs_COMPOUND || Type1 > TopAbs_FACE) return Standard_False;
439   const TopAbs_ShapeEnum& Type2 = ShapeType(ToolSh);
440   if(Type2  == TopAbs_COMPOUND || Type2 > TopAbs_FACE) return Standard_False;
441   TopTools_ListOfShape aList;
442
443   
444   if(Type1 != TopAbs_FACE) {
445     TopExp_Explorer anExp(ObjSh, TopAbs_FACE);
446     for(;anExp.More();anExp.Next()) {      
447       if(IsValidSurfType(TopoDS::Face(anExp.Current())))
448         aList.Append(anExp.Current());
449     }
450   } else 
451        if(IsValidSurfType(TopoDS::Face(ObjSh)))
452         aList.Append(ObjSh);
453   if(aList.Extent() == 1) {
454     if(Type2 != TopAbs_FACE) {
455       TopExp_Explorer anExp(ToolSh, TopAbs_FACE);
456       for(;anExp.More();anExp.Next()) {      
457         if(IsValidSurfType(TopoDS::Face(anExp.Current())))
458           aList.Append(anExp.Current());
459       }
460     } else 
461       if(IsValidSurfType(TopoDS::Face(ToolSh)))
462         aList.Append(ToolSh);
463     if(aList.Extent() == 2) return Standard_True;      
464   }
465   return Standard_False;      
466 }
467
468 //=======================================================================
469 static gp_Ax1 ComputeAxis(const TopoDS_Shape& theShape) {
470   TopoDS_Face aFace;
471   TopExp_Explorer anExp(theShape, TopAbs_FACE);
472   for(;anExp.More();anExp.Next()) {      
473     aFace = TopoDS::Face(anExp.Current());
474     BRepAdaptor_Surface anAdapt(aFace);
475     Handle( Adaptor3d_HCurve ) aBasisCurve;
476     const GeomAbs_SurfaceType& aType = anAdapt.GetType();
477     if(aType == GeomAbs_Cylinder) 
478       return anAdapt.Cylinder().Axis();
479     else if(aType == GeomAbs_Cone)
480       return anAdapt.Cone().Axis();
481     else if(aType == GeomAbs_SurfaceOfRevolution)
482       return anAdapt.AxeOfRevolution();   
483     else if(aType == GeomAbs_SurfaceOfExtrusion) {
484       aBasisCurve = anAdapt.BasisCurve();
485       if (aBasisCurve->GetType() == GeomAbs_Circle)
486         return aBasisCurve->Circle().Axis();
487       else if(aBasisCurve->GetType() == GeomAbs_Ellipse)
488         return aBasisCurve->Ellipse().Axis();
489     }
490   }
491   return gp::OX();
492 }
493 //==============================================================================
494 //
495 //==========================================================================
496 static Standard_Integer Identify(const TopoDS_Face& theFace, const gp_Ax1& theAx) {
497   GProp_GProps aGProp;
498   BRepGProp::SurfaceProperties(theFace, aGProp);
499   gp_Pnt aPoint = aGProp.CentreOfMass();
500   gp_Vec aV1(theAx.Direction());
501   gp_Vec aV2(theAx.Location(), aPoint);
502 #ifdef DEB
503   gp_Vec v1 = aV1.Crossed(aV2);
504   cout <<" Z of V1 = " << v1.XYZ().Z() << endl;
505 #endif
506   if((aV1.Crossed(aV2)).XYZ().Z() >= 0) return 1; //right orientation
507   return (-1); //left orientation
508 }
509
510 //=======================================================================
511 //function : LoadModified11
512 //purpose  : 1 : 1
513 //=======================================================================
514
515 void QANewBRepNaming_BooleanOperationFeat::LoadModified11 (BRepAlgoAPI_BooleanOperation& MS,
516                                                       const TopoDS_Shape&     ShapeIn,
517                                                       const TopAbs_ShapeEnum  KindOfShape) const
518
519 {
520   TopTools_MapOfShape View;
521   Standard_Boolean found = Standard_False;
522   TopExp_Explorer ShapeExplorer (ShapeIn, KindOfShape);
523   for (; ShapeExplorer.More(); ShapeExplorer.Next ()) {
524     const TopoDS_Shape& Root = ShapeExplorer.Current ();
525     if (!View.Add(Root)) continue;
526     const TopTools_ListOfShape& Shapes = MS.Modified2 (Root);
527     if(Shapes.Extent() == 1) {found = Standard_True; break;}
528   }
529     
530   if(found) {
531     View.Clear();
532     ShapeExplorer.Init (ShapeIn, KindOfShape);
533     TNaming_Builder Builder(ModifiedFaces());
534     for (; ShapeExplorer.More(); ShapeExplorer.Next ()) {
535       const TopoDS_Shape& Root = ShapeExplorer.Current ();
536       if (!View.Add(Root)) continue;
537       const TopTools_ListOfShape& Shapes = MS.Modified2 (Root);
538       if(Shapes.Extent() > 1) continue;
539       TopTools_ListIteratorOfListOfShape ShapesIterator (Shapes);
540       for (;ShapesIterator.More (); ShapesIterator.Next ()) {
541         const TopoDS_Shape& newShape = ShapesIterator.Value ();
542         if (!Root.IsSame (newShape)) {
543           //put shapes with evolution 1:1 (may be Compound)
544 #ifdef DEB
545           TCollection_AsciiString entry;
546           TDF_Tool::Entry(Builder.NamedShape()->Label(), entry);
547           cout << "Add shape to Compound at Label = "<< entry <<endl;
548 #endif
549           Builder.Modify (Root,newShape);
550         }
551       }
552     }
553   }
554 }
555 //======================================================================
556 static gp_Pnt GetCenterPoint(const TopoDS_Shape& theEdge)
557 {
558   GProp_GProps aGProp;
559   BRepGProp::LinearProperties(theEdge, aGProp);
560   return aGProp.CentreOfMass();
561 }
562 //===================================================================
563 static void SortRootFaces(TopTools_ListOfShape& theList, const TopoDS_Shape& theShape)
564 {
565   TopTools_ListOfShape aList;
566   Standard_Integer aNum = theList.Extent();
567   if(aNum <= 1) return;
568   gp_Ax1 anAx  = ComputeAxis(theShape);
569   TopTools_Array1OfShape  ArS(1, aNum);
570   TColgp_Array1OfPnt      ArP(1, aNum);
571   TColStd_Array1OfInteger ArI(1, aNum); 
572   TopTools_ListIteratorOfListOfShape It(theList);
573   Standard_Integer i;
574   for(i=1;It.More();It.Next(),i++) {
575     ArS.SetValue(i, It.Value ());
576     ArI.SetValue(i,0);
577     ArP.SetValue(i, GetCenterPoint(It.Value()));
578
579   }
580   gp_Pnt aPnt = anAx.Location();
581   Standard_Integer I, j;
582   for(j=1;j <= aNum; j++) {
583     if(ArI.Value(j) == -1) continue;
584     Standard_Real aD1 = aPnt.Distance(ArP(j));
585     I = 0;
586     for(i=1;i <= aNum; i++) {
587       if(i==j) continue;
588       if(ArI.Value(i) == -1) continue;
589         Standard_Real aD2 = aPnt.Distance(ArP(i));
590         if(aD2 < aD1) {
591           I = i;
592           aD1 = aD2;
593         }
594       }
595     if (I == 0) continue;
596     ArI.SetValue(I, -1);
597     aList.Append(ArS.Value(I));
598     if(aList.Extent() == aNum -1) {
599       for(i=1; i<=aNum;i++)
600         if(ArI.Value(i) != -1) aList.Append(ArS.Value(i));
601     }
602   }
603   theList.Assign(aList);
604 }
605 //=======================================================================
606 static void Sort2Faces(const TopTools_ListOfShape& Shapes,
607                        const gp_Ax1& theAx, TopTools_ListOfShape& theList)
608 {
609
610   TopTools_ListIteratorOfListOfShape It(Shapes);
611   for(;It.More();It.Next()) {
612     if(Identify(TopoDS::Face(It.Value()), theAx) == 1)
613       theList.Prepend(It.Value());   //Pos
614     else theList.Append(It.Value()); //Neg
615   }
616 }
617
618 //=======================================================================
619 static void Sort3Faces(const TopTools_ListOfShape& theListIn, TopTools_ListOfShape& theListOut)
620 {
621   TopTools_ListIteratorOfListOfShape It (theListIn);
622   TopTools_Array1OfShape  ArS(1, theListIn.Extent());
623   TColgp_Array1OfPnt      ArP(1, theListIn.Extent());
624
625   Standard_Integer i;
626   for(i=1;It.More();It.Next(),i++) {
627     ArS.SetValue(i, It.Value());
628     ArP.SetValue(i, GetCenterPoint(It.Value()));
629   }
630
631   Standard_Boolean found = Standard_False;
632   Standard_Integer j, i1, i2, i3; 
633   TopoDS_Edge anEdge;
634   for(i=1;i<=3;i++) {
635     TopExp_Explorer anExp1(ArS.Value(i), TopAbs_EDGE);
636     for(;anExp1.More();anExp1.Next()) {         
637       for(j=1;j<=3;j++) {
638         if(i==j) continue;      
639         TopExp_Explorer anExp2(ArS.Value(j), TopAbs_EDGE);
640         for(;anExp2.More();anExp2.Next()) {  
641           if(anExp1.Current().IsSame(anExp2.Current())){
642             found = Standard_True;
643             anEdge = TopoDS::Edge(anExp1.Current());
644             break;
645           }
646         }
647         if(found) break;
648       }
649       if(found) {
650         switch(i+j) {
651         case 3: //12
652           i1=1;i2=2; i3=3;
653           break;
654         case 4: //13      
655           i1=1;i2=3; i3=2;
656           break;
657         case 5: //23
658           i1=2;i2=3; i3=1;
659         }
660         break;
661       }
662     }
663     if(found) break;
664   }
665
666 //i1,i2 - two adjacent faces via sim-edge
667   gp_Pnt aPnt1 = BRep_Tool::Pnt(TopExp::FirstVertex(anEdge));
668   gp_Pnt aPnt2 = BRep_Tool::Pnt(TopExp::LastVertex(anEdge));
669   gp_Vec aVec(aPnt1, aPnt2);
670   gp_Ax1 anAx(aPnt1, gp_Dir(aVec));
671   if (Identify(TopoDS::Face(ArS.Value(i1)), anAx) == -1) {//neg
672     i=i2; i2=i1; //i1 < = > i2
673     i1=i;
674   }
675   theListOut.Append(ArS.Value(i1));
676   theListOut.Append(ArS.Value(i2));
677   theListOut.Append(ArS.Value(i3)); //single
678 }
679 //=======================================================================
680 //function : Load1nFaces
681 //purpose  : 
682 //=======================================================================
683
684 void QANewBRepNaming_BooleanOperationFeat::Load1nFaces(BRepAlgoAPI_BooleanOperation& MS, const TopoDS_Shape& ShapeIn) const
685 {
686
687   TopTools_MapOfShape View;
688   TopTools_ListOfShape aListR;
689   TopExp_Explorer ShapeExplorer (ShapeIn, TopAbs_FACE);
690   for (; ShapeExplorer.More(); ShapeExplorer.Next ()) {
691     const TopoDS_Shape& Root = ShapeExplorer.Current ();
692     if (!View.Add(Root)) continue;
693     const TopTools_ListOfShape& Shapes = MS.Modified2 (Root);
694     if(Shapes.Extent() < 2) continue; 
695     aListR.Append(Root);
696   }
697   if(ShapeIn.IsEqual(MS.Shape1()))
698     if(aListR.Extent() > 1) SortRootFaces(aListR, ShapeIn);
699    
700   TopTools_ListIteratorOfListOfShape Itr(aListR);
701   for(;Itr.More();Itr.Next()) {
702     const TopoDS_Shape& Root = Itr.Value();
703     const TopTools_ListOfShape& Shapes = MS.Modified2 (Root);
704     TopTools_ListOfShape aList;
705     gp_Ax1 anAx = ComputeAxis(MS.Shape2());     
706     if(Shapes.Extent() == 2)
707       Sort2Faces(Shapes, anAx, aList);
708     else if(Shapes.Extent() == 3)
709       Sort3Faces(Shapes, aList);
710     TopTools_ListIteratorOfListOfShape It(aList);
711     for(;It.More();It.Next()) {
712       TNaming_Builder aBuilder(NewShapes());
713 //      aBuilder.Modify(Root,It.Value ());
714       aBuilder.Generated(It.Value ());
715     }
716   }
717 }
718
719 //=======================================================================
720 //function : LoadModified faces
721 //purpose  : 1 : n modification
722 //=======================================================================
723
724 void QANewBRepNaming_BooleanOperationFeat::LoadModified1n (BRepAlgoAPI_BooleanOperation& MS,
725                                                     const TopoDS_Shape&     ShapeIn,
726                                                     const TopAbs_ShapeEnum  KindOfShape) const
727
728
729 //fill modification 1:n
730   TopTools_MapOfShape View;
731   Standard_Integer aNum = 0;
732   TopExp_Explorer ShapeExplorer (ShapeIn, KindOfShape);
733   for (; ShapeExplorer.More(); ShapeExplorer.Next ()) {
734     const TopoDS_Shape& Root = ShapeExplorer.Current ();
735     if (!View.Add(Root)) continue;
736     const TopTools_ListOfShape& Shapes = MS.Modified2 (Root);
737     if(Shapes.Extent() >= 2) aNum += Shapes.Extent();
738   }
739   
740   View.Clear();
741   const TopoDS_Shape&     Tool = MS.Shape2();
742   ShapeExplorer.Init (Tool, KindOfShape);
743   for (; ShapeExplorer.More(); ShapeExplorer.Next ()) {
744     const TopoDS_Shape& Root = ShapeExplorer.Current ();
745     if (!View.Add(Root)) continue;
746     const TopTools_ListOfShape& Shapes = MS.Modified2 (Root);
747     if(Shapes.Extent() >= 2) aNum += Shapes.Extent();
748   }
749
750   Handle(TDataStd_IntegerArray) aSAR;
751   if(!ResultLabel().FindAttribute(TDataStd_IntegerArray::GetID(), aSAR) ) {
752     //not find
753     aSAR = TDataStd_IntegerArray::Set(ResultLabel(), 1, 2);
754     aSAR->SetValue(1, 0); //tag num for faces structure
755     aSAR->SetValue(2, 0); //tag num for edges structure
756   }
757
758   if(aSAR->Value(2))  {
759     Standard_Integer aNE =0;
760     TDF_Label aLab = ResultLabel().FindChild(aSAR->Value(2));
761     Handle(TDataStd_Integer) anAtt;
762     if(aLab.FindAttribute(TDataStd_Integer::GetID(), anAtt) ) 
763       aNE = anAtt->Get();    
764     TDF_Label aFLab = ResultLabel().FindChild(aLab.Tag() + aNE);
765     if(!aFLab.FindAttribute(TDataStd_Integer::GetID(), anAtt))
766       aSAR->SetValue(1, 0); 
767   }
768   TDF_Label aLabelFDS;
769   if(aSAR->Value(1)) 
770     aLabelFDS = ResultLabel().FindChild(aSAR->Value(1)); // !=0 -already exist
771   else {
772     // initial creation of FDS structure
773     Handle(TDF_TagSource) aTS;
774     ResultLabel().FindAttribute (TDF_TagSource::GetID (), aTS);    
775     aLabelFDS = NewShapes();
776 //    aLabelFDS = ResultLabel().FindChild(aSAR->Value(1)); 
777     aSAR->SetValue(1, aLabelFDS.Tag()); //keep tag
778     aTS->Set(aLabelFDS.Tag()-1);
779   }
780   Handle(TDataStd_Integer) anAtt;
781   if(aLabelFDS.FindAttribute(TDataStd_Integer::GetID(), anAtt) ) {
782     // modification : check compatibility
783     if(anAtt->Get() != aNum) {
784       cout << "WARNING: Case isn't mantained - Number of Faces was changed!"<<endl;
785       // mark all structure as Deleted
786       Standard_Integer aN = aLabelFDS.Tag()+anAtt->Get();
787       for(Standard_Integer i=aLabelFDS.Tag(); i < aN; i++) {
788         TDF_Label aLab =  ResultLabel().FindChild(i, Standard_False); 
789         if(!aLab.IsNull()) {
790           Handle(TNaming_NamedShape) aNS;
791           if(aLab.FindAttribute(TNaming_NamedShape::GetID(), aNS)) {
792             TopoDS_Shape aShape = aNS->Get();
793             TNaming_Builder aBuilder(aLab);
794             aBuilder.Delete(aShape); //Deleted
795           }
796         }
797       }
798 //
799       Handle(TDF_TagSource) aTS;
800       ResultLabel().FindAttribute (TDF_TagSource::GetID (), aTS);
801       if(!aTS.IsNull())
802         aTS->Set(aLabelFDS.Tag());
803       anAtt->Set(aNum);
804     }    
805   } else
806     TDataStd_Integer::Set(aLabelFDS, aNum); //keep number of faces
807
808   Load1nFaces(MS, ShapeIn);
809   Load1nFaces(MS, Tool);   
810 }
811
812
813 //======================================================================
814 static Standard_Boolean IsDirectionPositive (const gp_Ax1& theAx, const gp_Pnt thePnt1, 
815                                              const gp_Pnt thePnt2) {
816   Standard_Boolean isPositive;
817   gp_Vec aVec1(theAx.Direction());
818   gp_Vec aVec2(thePnt1, thePnt2);
819 #ifdef DEB
820 //  gp_Vec v1 = aVec1.Crossed(aVec2);
821 //  cout <<" Z of V1 = " << v1.XYZ().Z() << endl;
822 #endif
823   if((aVec1.Crossed(aVec2)).XYZ().Z() >= 0) isPositive = Standard_True;
824   else 
825     isPositive = Standard_False;
826   return isPositive;
827 }
828 //======================================================================
829 // i => ArS[i] : ArP[i] ; i = ArI[j]
830 //======================================================================
831 static void SortEdges2(const TColgp_Array1OfPnt& theArP, const gp_Ax1& theAx,
832                       TColStd_Array1OfInteger& theArI)
833 {
834   gp_Pnt aPnt = theAx.Location();  
835   //sort : the nearest point must be first
836   Standard_Real aD1 = aPnt.Distance(theArP.Value(1));
837   Standard_Real aD2 = aPnt.Distance(theArP.Value(2));
838   if(aD1 < aD2) {
839     theArI.SetValue(1, 1);
840     theArI.SetValue(2, 2);
841   } else  {
842     theArI.SetValue(1, 2); //change order
843     theArI.SetValue(2, 1);
844   }
845 }
846 //======================================================================
847 // i => ArS[i] : ArP[i] ; i = ArI[j]
848 //======================================================================
849 static void SortEdges3(const TopTools_Array1OfShape& theArS, const TColgp_Array1OfPnt& theArP, 
850                        const gp_Ax1& theAx, TColStd_Array1OfInteger& theArI)
851 {
852   Standard_Integer i, j, i1,i2, i3;
853   TopoDS_Shape aV;
854   Standard_Boolean adjacent = Standard_False;
855   for(i=1;i<=3;i++) {    
856     for(j=1;j<=3;j++) {
857       if(i==j) continue;
858       const TopoDS_Shape& aV11 = TopExp::FirstVertex(TopoDS::Edge(theArS.Value(i)));
859       const TopoDS_Shape& aV21 = TopExp::FirstVertex(TopoDS::Edge(theArS.Value(j)));
860       const TopoDS_Shape& aV22 = TopExp::LastVertex(TopoDS::Edge(theArS.Value(j)));      
861       if(aV11.IsSame(aV21) || aV11.IsSame(aV22)) {adjacent = Standard_True;aV = aV11;}
862       else {
863         const TopoDS_Shape& aV12 = TopExp::LastVertex(TopoDS::Edge(theArS.Value(i)));
864         if(aV12.IsSame(aV21) || aV12.IsSame(aV22)) {adjacent = Standard_True;aV = aV12;}
865       }
866       if(adjacent) {
867         Standard_Integer aSum = i+j;
868         switch(aSum) {
869         case 3: //12
870           i1 = 3;i2 = 1;i3 = 2;
871           break;
872         case 4: //13
873           i1 = 2; i2 = 1;i3 = 3;
874           break;
875         case 5: //23
876           i1 = 1; i2 = 2;i3 = 3;
877         }
878         break;
879       }
880     }
881     if(adjacent) break; 
882   }
883   gp_Pnt aPnt = theAx.Location(); 
884 // i1 - index of single edge
885   Standard_Real aD1 = aPnt.Distance(theArP.Value(i1));
886   Standard_Real aD2 = aPnt.Distance(theArP.Value(i2));
887   if(aD1 > aD2) { //cyclic shift
888     Standard_Integer aN = i3;// i1 => i3 - to the end
889     i3 = i1; i1 = aN;
890     // pair of adjacent i1, i2
891     gp_Pnt aCP = BRep_Tool::Pnt(TopoDS::Vertex(aV)); 
892     if(!IsDirectionPositive(theAx, aCP, theArP.Value(i1))) {//first must be positive direction       
893       // change i1 <=>i2
894       aN = i2; i2 = i1;
895       i1 = aN;
896     }    
897   } else {
898     // pair of adjacent i2, i3
899     gp_Pnt aCP = BRep_Tool::Pnt(TopoDS::Vertex(aV)); 
900     if(!IsDirectionPositive(theAx, aCP, theArP.Value(i2))) {//first must be positive direction
901       // change i2 <=>i3
902       Standard_Integer aN = i3; i3 = i2;
903       i2 = aN;
904       }
905   }
906 // order i1, i2, i3 
907   theArI.SetValue(1, i1); 
908   theArI.SetValue(2, i2);
909   theArI.SetValue(3, i3);
910 }
911
912 //======================================================================
913 // i => ArS[i] : ArP[i] ; i = ArI[j]
914 //======================================================================
915 static void SortEdges4(const TopTools_Array1OfShape& theArS, const TColgp_Array1OfPnt& theArP, 
916                        const gp_Ax1& theAx, TColStd_Array1OfInteger& theArI)
917 {
918 // 1. find adjacent edges, build pairs in ArI
919 // 2. find nearest pair, reorganize ArI
920 // 3. sort inside pairs
921 // =======================================
922   Standard_Integer i, j, i1,i2, i3, i4;
923 // 1.
924   TopoDS_Shape aV1;
925   for(i=1;i<=4;i++) { 
926     const TopoDS_Shape& aV11 = TopExp::FirstVertex(TopoDS::Edge(theArS.Value(i)));
927     const TopoDS_Shape& aV12 = TopExp::LastVertex(TopoDS::Edge(theArS.Value(i)));
928     Standard_Boolean aDjacent;
929     for(j=1;j<=4;j++) {
930       if(i==j) continue;
931       const TopoDS_Shape& aV21 = TopExp::FirstVertex(TopoDS::Edge(theArS.Value(j)));
932       const TopoDS_Shape& aV22 = TopExp::LastVertex(TopoDS::Edge(theArS.Value(j)));
933       aDjacent = Standard_False;
934       if(aV11.IsSame(aV21) || aV11.IsSame(aV22)) {aDjacent = Standard_True;aV1 = aV11;}
935       else 
936         if(aV12.IsSame(aV21) || aV12.IsSame(aV22)) {aDjacent = Standard_True;aV1 = aV12;}
937       if(aDjacent) {
938         aDjacent = Standard_True;
939         Standard_Integer aSum = i+j;
940         i1 = i; i2 = j; 
941         switch(aSum) {
942         case 3: //12
943           i3 = 3; i4 = 4;
944           break;
945         case 4: //13
946           i3 = 2; i4 = 4;
947           break;
948         case 5: //14
949           i3 = 2; i4 = 3;
950           break;
951         }
952         break;
953       }
954     }
955     if(aDjacent) break;
956   }
957 // i1,i2 - first pair of adjacent: aV1.
958 // i3,i4 - next  pair of adjacent: aV2.
959 // find agjacent V (i3-i4)
960   TopoDS_Shape aV2;
961   const TopoDS_Shape& aV11 = TopExp::FirstVertex(TopoDS::Edge(theArS.Value(i3)));
962   const TopoDS_Shape& aV21 = TopExp::FirstVertex(TopoDS::Edge(theArS.Value(i4)));
963   const TopoDS_Shape& aV22 = TopExp::LastVertex(TopoDS::Edge(theArS.Value(i4)));
964   if(aV11.IsSame(aV21) || aV11.IsSame(aV22)) aV2 = aV11;
965   else {
966     const TopoDS_Shape& aV12 = TopExp::LastVertex(TopoDS::Edge(theArS.Value(i3)));
967     if(aV12.IsSame(aV21) || aV12.IsSame(aV22)) aV2 = aV12;
968   }
969
970 // 2. find nearest pair
971   gp_Pnt aCP1 = BRep_Tool::Pnt(TopoDS::Vertex(aV1)); 
972   gp_Pnt aCP2 = BRep_Tool::Pnt(TopoDS::Vertex(aV2)); 
973   gp_Pnt aPnt = theAx.Location();
974   Standard_Real aD1 = aPnt.Distance(aCP1);//i1-i2
975   Standard_Real aD2 = aPnt.Distance(aCP2);//i3-i4
976   if(aD1 > aD2) { //change order of pairs
977     Standard_Integer a3 = i3;// i1,i2 => i3,i4 - to the end
978     Standard_Integer a4 = i4;
979     i3 = i1; i4 = i2;
980     i1 = a3; i2 = a4;
981     gp_Pnt aP = aCP2;
982     aCP2 = aCP1;
983     aCP1 = aP;
984     // pair of adjacent i1-i2 is the nearest
985   }    
986
987 // 3. sort inside pairs
988   if(!IsDirectionPositive(theAx, aCP1, theArP.Value(i1))) {//first must be positive direction
989     // change i1 <=> i2
990     Standard_Integer aN = i2; i2 = i1;
991     i1 = aN;
992   }
993
994   if(!IsDirectionPositive(theAx, aCP2, theArP.Value(i3))) {//first must be positive direction
995     // change i3 <=> i4
996 #ifdef DEB
997   cout << "SortEdges4: i3 = "<<i3<< "i4 = "<< i4 << endl;
998 #endif
999     Standard_Integer aN = i4; i4 = i3;
1000     i3 = aN;
1001   }
1002
1003 // 4. final order i1, i2, i3, i4 - Ok
1004 #ifdef DEB
1005   cout << "SortEdges4: i1 = " <<i1<<" i2 = "<<i2<< " i3 = "<<i3<< "i4 = "<< i4 << endl;
1006 #endif
1007   theArI.SetValue(1, i1); 
1008   theArI.SetValue(2, i2);
1009   theArI.SetValue(3, i3);
1010   theArI.SetValue(4, i4);
1011 }
1012 // ======================================================================
1013 static void SortEdges5 (const TopTools_Array1OfShape& theArS, const TColgp_Array1OfPnt& theArP, 
1014                        const gp_Ax1& theAx, TColStd_Array1OfInteger& theArI)
1015 {
1016 // =======================================
1017 // 1. find middle edge from gr. of 3 edges, build two groups in ArI
1018 // 2. find nearest group, reorganize ArI - nerest => top
1019 // 3. sort inside groups
1020 // 3.1. sort inside group of 2 edges
1021 // 3.2. sort inside group of 3 edges
1022 // =======================================
1023   Standard_Integer i, j, i1,i2, i3, i4, i5;
1024 // 1.
1025   TopoDS_Shape aV1, aV2, aV;
1026   Standard_Integer I=0, J1=0, J2=0;
1027   for(i=1;i<=5;i++) {    
1028     Standard_Boolean found = Standard_False;
1029     const TopoDS_Shape& aV11 = TopExp::FirstVertex(TopoDS::Edge(theArS.Value(i)));
1030     for(j=1;j<=5;j++) {
1031       if(i==j) continue;
1032       const TopoDS_Shape& aV21 = TopExp::FirstVertex(TopoDS::Edge(theArS.Value(j)));
1033       const TopoDS_Shape& aV22 = TopExp::LastVertex(TopoDS::Edge(theArS.Value(j)));
1034       if(aV11.IsSame(aV21) || aV11.IsSame(aV22)) {
1035         aV1 = aV11; I = i; J1 = j;
1036         found = Standard_True;
1037         break;
1038       }
1039     }
1040     if (found) {
1041       found = Standard_False;
1042       const TopoDS_Shape& aV12 = TopExp::LastVertex(TopoDS::Edge(theArS.Value(i)));
1043       for(j=1;j<=5;j++) {
1044         if(i==j) continue;
1045         const TopoDS_Shape& aV21 = TopExp::FirstVertex(TopoDS::Edge(theArS.Value(j)));
1046         const TopoDS_Shape& aV22 = TopExp::LastVertex(TopoDS::Edge(theArS.Value(j)));
1047         if(aV12.IsSame(aV21) || aV12.IsSame(aV22)) {
1048           aV2 = aV12; J2 = j;
1049 #ifdef DEB
1050           if(I != i) cout << "WARNING:: I != i, I = " << I << ", i = " << i <<endl; 
1051 #endif
1052           found = Standard_True;
1053           break;
1054         }
1055       }
1056     }
1057     if (found) break;
1058   }
1059 // aV1, aV2 - vetexes of middle Edge, I - index of middle Edge, J1, J2 = indexes of 
1060 // adjacent edges of the middle edge
1061
1062 // init & shift group from 3 edges on the top 
1063   i1=J1; i2=I; i3 = J2; i4=0; i5=0;
1064   for(i=1; i<=5;i++) {
1065     if(i==i1 || i==i2 ||i==i3) continue;
1066     if(!i4) i4=i;
1067     else i5 = i;
1068   }
1069
1070 // find agjacent V (i4-i5)
1071   TopoDS_Shape aV3;
1072   const TopoDS_Shape& aV11 = TopExp::FirstVertex(TopoDS::Edge(theArS.Value(i4)));
1073   const TopoDS_Shape& aV21 = TopExp::FirstVertex(TopoDS::Edge(theArS.Value(i5)));
1074   const TopoDS_Shape& aV22 = TopExp::LastVertex(TopoDS::Edge(theArS.Value(i5)));
1075   if(aV11.IsSame(aV21) || aV11.IsSame(aV22)) aV3 = aV11;
1076   else {
1077     const TopoDS_Shape& aV12 = TopExp::LastVertex(TopoDS::Edge(theArS.Value(i4)));
1078     if(aV12.IsSame(aV21) || aV12.IsSame(aV22)) aV3 = aV12;
1079   }
1080   
1081 // 2. find nearest group (aV1, aV3), reorganize ArI - nerest => top
1082   gp_Pnt aDP1 = BRep_Tool::Pnt(TopoDS::Vertex(aV1)); 
1083   gp_Pnt aDP2 = BRep_Tool::Pnt(TopoDS::Vertex(aV2));  
1084   gp_Pnt aDP3 = BRep_Tool::Pnt(TopoDS::Vertex(aV3)); 
1085   gp_Pnt aPnt = theAx.Location();
1086   Standard_Real aD1 = aPnt.Distance(aDP1);//i1-i2-i3
1087   Standard_Real aD2 = aPnt.Distance(aDP3);//i4-i5
1088   Standard_Integer aTop = 3;
1089   if(aD1 > aD2) { //change order of groups
1090     aTop = 2;
1091     Standard_Integer a4 = i4;// i1,i2 => i4,i5 - to the end
1092     Standard_Integer a5 = i5;
1093     i4 = i2; i5 = i1; // i4 - middle edge
1094     i1 = a4; i2 = a5;
1095     gp_Pnt aP1 = aDP1;    
1096     aDP1 = aDP3;
1097     aDP3 = aP1;
1098     // goup of 2 edges i1-i2 is the nearest
1099   }
1100 // 3.1. sort inside group of 2 edges
1101   gp_Pnt aDP, aCP;
1102   if(aTop == 2) {aDP = aDP1; aCP = theArP.Value(i1);} //i1,i2 
1103   else {aDP = aDP3; aCP = theArP.Value(i4);} //i4, i5 - group of 2 edges at the bottom
1104   if(!IsDirectionPositive(theAx, aDP, aCP)) {//first must be positive direction
1105     Standard_Integer aN;
1106     if(aTop == 2) {
1107     // change i1 <=> i2
1108       aN = i2; i2 = i1;
1109       i1 = aN;
1110     } else {
1111       // change i4 <=> i5
1112       aN = i5; i5 = i4;
1113       i4 = aN;
1114     }
1115   }
1116 // 3.2. sort inside group of 3 edges
1117   if(aTop == 2) {
1118     //i3,i4,i5
1119     aDP = theArP.Value(i4); //center of middle edge
1120     aCP = theArP.Value(i3); 
1121   } else {
1122     //i1,i2,i3
1123     aDP = theArP.Value(i2);
1124     aCP = theArP.Value(i1);
1125   }
1126
1127   if(!IsDirectionPositive(theAx, aDP, aCP)) {//first must be positive direction
1128     Standard_Integer aN;
1129     if(aTop == 2) {
1130     // change i3 <=> i5
1131       aN = i5; i5 = i3;
1132       i3 = aN;
1133     } else {
1134       // change i1 <=> i3
1135       aN = i3; i3 = i1;
1136       i1 = aN;
1137     }
1138   }
1139 // 4. final order i1, i2, i3, i4, i5 - Ok
1140   theArI.SetValue(1, i1); 
1141   theArI.SetValue(2, i2);
1142   theArI.SetValue(3, i3);
1143   theArI.SetValue(4, i4);
1144   theArI.SetValue(5, i5);
1145 }
1146 //=======================================================================
1147 static void FindAdjacent2(const TopTools_ListOfShape& theList, 
1148                          TopTools_ListOfShape& theListOfEdges) {
1149   TopTools_ListIteratorOfListOfShape It (theList);
1150   const TopoDS_Shape& aShape1 = It.Value (); It.Next ();
1151   const TopoDS_Shape& aShape2 = It.Value ();
1152   if(!aShape1.IsNull() && !aShape2.IsNull()) {
1153     TopExp_Explorer anExp1(aShape1, TopAbs_EDGE);
1154     for(;anExp1.More();anExp1.Next()) {      
1155       TopExp_Explorer anExp2(aShape2, TopAbs_EDGE);
1156       for(;anExp2.More();anExp2.Next()) {  
1157         if(anExp1.Current().IsSame(anExp2.Current()))
1158           theListOfEdges.Append(anExp1.Current());
1159       }
1160     }
1161   }
1162 }
1163 //=======================================================================
1164 static void FindAdjacent3(const TopTools_ListOfShape& theList, 
1165                           TopTools_ListOfShape& theListOfEdges) {
1166   TopTools_ListIteratorOfListOfShape It (theList);
1167   TopTools_Array1OfShape  ArS(1, theList.Extent());
1168   TColgp_Array1OfPnt      ArP(1, theList.Extent());
1169   TColgp_Array1OfDir      ArD(1, theList.Extent());
1170   Standard_Integer i;
1171   for(i=1;It.More();It.Next(),i++) {
1172     ArS.SetValue(i, It.Value());
1173     gp_Ax1 anAx = ComputeAxis(It.Value()); 
1174     ArP.SetValue(i, anAx.Location());
1175     ArD.SetValue(i, anAx.Direction());
1176   }
1177   Standard_Boolean aDjacent = Standard_False;
1178   Standard_Integer j, i2, i3; //i2, i3 - indexes of two adjacent faces having the same surface
1179   Standard_Integer i1 = 0; //single face
1180   for(i=1;i<=3;i++) {    
1181     for(j=1;j<=3;j++) {
1182       if(i==j) continue;
1183       if(ArP.Value(i).IsEqual(ArP.Value(j), Precision::Confusion()) 
1184          && ArD.Value(i).IsEqual(ArD.Value(j), Precision::Angular())) { 
1185         aDjacent = Standard_True;
1186         Standard_Integer aSum = i+j;
1187         switch(aSum) {
1188         case 3: //12
1189           i1 = 3; i2 = 1; i3 = 2;
1190           break;
1191         case 4: //13
1192           i1 = 2; i2 = 1; i3 = 3;
1193           break;
1194         case 5: //23
1195           i1 = 1; i2 = 2; i3 = 3;
1196           break;
1197         default:
1198           i1 = 1; i2 = 2; i3 = 3;
1199         }
1200         break;
1201       }
1202     }
1203     if(aDjacent) break;
1204   }
1205
1206   TopExp_Explorer anExp1(ArS.Value(i1), TopAbs_EDGE);
1207   for(;anExp1.More();anExp1.Next()) {
1208     Standard_Boolean found = Standard_False;
1209     TopExp_Explorer anExp2(ArS.Value(i2), TopAbs_EDGE);
1210     for(;anExp2.More();anExp2.Next()) {  
1211       if(anExp1.Current().IsSame(anExp2.Current()))
1212         {theListOfEdges.Append(anExp1.Current()); found=Standard_True; break;}
1213     }
1214     if(!found) {
1215       TopExp_Explorer anExp3(ArS.Value(i3), TopAbs_EDGE);
1216       for(;anExp3.More();anExp3.Next()) {  
1217         if(anExp1.Current().IsSame(anExp3.Current()))
1218           {theListOfEdges.Append(anExp1.Current());break;}
1219       }
1220     }
1221   }
1222 }
1223 //=======================================================================
1224 static void FindAdjacent4(const TopTools_ListOfShape& theList, 
1225                           TopTools_ListOfShape& theListOfEdges) {
1226   TopTools_ListIteratorOfListOfShape It (theList);
1227   TopTools_Array1OfShape  ArS(1, theList.Extent());
1228   TColgp_Array1OfPnt      ArP(1, theList.Extent());
1229   TColgp_Array1OfDir      ArD(1, theList.Extent());
1230   Standard_Integer i;
1231   for(i=1;It.More();It.Next(),i++) {
1232     ArS.SetValue(i, It.Value());
1233     gp_Ax1 anAx = ComputeAxis(It.Value()); 
1234     ArP.SetValue(i, anAx.Location());
1235     ArD.SetValue(i, anAx.Direction());
1236   }
1237   //find pairs
1238   Standard_Integer j, i3=0, i4 = 0;//i3, i4 - indexes of two adjacent faces having the same surface
1239   Standard_Integer i1 = 0, i2 = 0; 
1240   Standard_Boolean aDjacent = Standard_False;
1241   for(i=1;i<=4;i++) {    
1242     for(j=1;j<=4;j++) {
1243       if(i==j) continue;
1244       if(ArP.Value(i).IsEqual(ArP.Value(j), Precision::Confusion()) 
1245          && ArD.Value(i).IsEqual(ArD.Value(j), Precision::Angular())) {
1246         aDjacent = Standard_True;
1247         Standard_Integer aSum = i+j;
1248         i1 = i; i2 = j; 
1249         switch(aSum) {
1250         case 3: //12
1251           i3 = 3; i4 = 4;
1252           break;
1253         case 4: //13
1254           i3 = 2; i4 = 4;
1255           break;
1256         case 5: //14
1257           i3 = 2; i4 = 3;
1258           break;
1259         default:
1260           i3 = 3; i4 = 4;
1261         }
1262         break;
1263       }
1264     }
1265     if(aDjacent) break;
1266   }
1267
1268   TopExp_Explorer anExp1(ArS.Value(i1), TopAbs_EDGE);
1269   for(;anExp1.More();anExp1.Next()) {
1270     Standard_Boolean found = Standard_False;
1271     TopExp_Explorer anExp2(ArS.Value(i3), TopAbs_EDGE);
1272     for(;anExp2.More();anExp2.Next()) {  
1273       if(anExp1.Current().IsSame(anExp2.Current()))
1274         {theListOfEdges.Append(anExp1.Current()); found=Standard_True; break;}
1275     }
1276     if(!found) {
1277       TopExp_Explorer anExp3(ArS.Value(i4), TopAbs_EDGE);
1278       for(;anExp3.More();anExp3.Next()) {  
1279         if(anExp1.Current().IsSame(anExp3.Current()))
1280           {theListOfEdges.Append(anExp1.Current());break;}
1281       }
1282     }
1283   }
1284 //
1285   anExp1.Init(ArS.Value(i2), TopAbs_EDGE);
1286   for(;anExp1.More();anExp1.Next()) {
1287     Standard_Boolean found = Standard_False;
1288     TopExp_Explorer anExp2(ArS.Value(i3), TopAbs_EDGE);
1289     for(;anExp2.More();anExp2.Next()) {  
1290       if(anExp1.Current().IsSame(anExp2.Current()))
1291         {theListOfEdges.Append(anExp1.Current()); found=Standard_True; break;}
1292     }
1293     if(!found) {
1294       TopExp_Explorer anExp3(ArS.Value(i4), TopAbs_EDGE);
1295       for(;anExp3.More();anExp3.Next()) {  
1296         if(anExp1.Current().IsSame(anExp3.Current()))
1297           {theListOfEdges.Append(anExp1.Current());break;}
1298       }
1299     }
1300   }
1301 }
1302
1303 //=======================================================================
1304 // SortEdges: returns 
1305 //=======================================================================
1306 static void SortEdges(const TopTools_ListOfShape& theListE, const gp_Ax1& theAx, 
1307                      TopTools_Array1OfShape& theARS)
1308 {
1309   
1310   Standard_Integer aNE1 = theListE.Extent();
1311   TopTools_Array1OfShape  ArS(1, aNE1);
1312   TColgp_Array1OfPnt      ArP(1, aNE1);
1313   TColStd_Array1OfInteger ArI(1, aNE1); 
1314   TopTools_ListIteratorOfListOfShape It (theListE);//pairs of edges
1315   //for (Standard_Integer i=1;It.More (); It.Next (),i++) {
1316   Standard_Integer i;
1317   for (i=1;It.More (); It.Next (),i++) {
1318     ArS.SetValue(i, It.Value ());
1319     ArI.SetValue(i,0);
1320     ArP.SetValue(i, GetCenterPoint(It.Value()));
1321   }
1322   switch(aNE1) {
1323   case 2:
1324     // Identify position  
1325     SortEdges2(ArP, theAx, ArI);
1326     break;
1327   case 3:
1328     SortEdges3(ArS, ArP, theAx, ArI);
1329     break;
1330   case 4:
1331     SortEdges4(ArS, ArP, theAx, ArI);
1332     break;
1333   case 5:
1334     SortEdges5(ArS, ArP, theAx, ArI);
1335     break;
1336   }
1337   
1338   for(i=1;i<=ArI.Upper();i++) {
1339 #ifdef DEB
1340     cout << "SortEdges: i = " <<i<<" ArI.Value(i) = " <<ArI.Value(i)<< endl;
1341 #endif   
1342     theARS.SetValue(i, ArS.Value(ArI.Value(i)));  
1343
1344   }
1345 }
1346 //=======================================================================
1347 //function : LoadSymmetricalEdges
1348 //purpose  : 
1349 //=======================================================================
1350
1351 void QANewBRepNaming_BooleanOperationFeat::LoadSymmetricalEdges (BRepAlgoAPI_BooleanOperation& MS) const
1352 {
1353   const TopoDS_Shape& aResult   = MS.Shape();
1354   if(aResult.IsNull()) return;
1355   const TopoDS_Shape& ObjSh     = MS.Shape1();
1356   const TopoDS_Shape& ToolSh    = MS.Shape2();
1357   const TopAbs_ShapeEnum& Type1 = ShapeType(ObjSh);
1358   if(Type1  == TopAbs_COMPOUND || Type1 > TopAbs_FACE) return;
1359   const TopAbs_ShapeEnum& Type2 = ShapeType(ToolSh);
1360   if(Type2  == TopAbs_COMPOUND || Type2 > TopAbs_FACE) return;
1361   TopTools_ListOfShape aList0;
1362   if (aResult.ShapeType() == TopAbs_COMPOUND) {
1363     TopoDS_Iterator itr(aResult);
1364     for (; itr.More(); itr.Next())
1365       aList0.Append(itr.Value()); //collect separated entities (bodies)
1366     
1367   }
1368   if(aList0.Extent() > 2) return; // case > 2 ent. is not considered
1369   TopTools_ListOfShape aList1, aList2;
1370   TopTools_ListIteratorOfListOfShape It (aList0); //each item (body) must have at least 1 pair 
1371   // of "cyl/con" surfaces (in some cases may be 3 or 4 faces depending on sim-edge position)
1372   for (;It.More (); It.Next ()) {
1373     const TopoDS_Shape& aShape = It.Value (); //1-st solid/shell
1374     TopTools_ListOfShape aList;
1375     aList.Clear();
1376 #ifdef DEB
1377 //    ModDbgTools_Write(aShape, "S0");
1378 #endif
1379     if(aShape.ShapeType() != TopAbs_FACE) {
1380       TopExp_Explorer anExp(aShape, TopAbs_FACE);      
1381       for(;anExp.More();anExp.Next()) {      
1382         if(IsValidSurfType(TopoDS::Face(anExp.Current()))) 
1383           aList.Append(anExp.Current()); // faces of the current entity
1384       }
1385     } else 
1386       if(IsValidSurfType(TopoDS::Face(ObjSh)))
1387         aList.Append(aShape);
1388     
1389     if(aList1.Extent() == 0 )
1390       aList1.Assign(aList);
1391     else 
1392       aList2.Assign(aList);
1393   }
1394 // aList1,2 contain pairs of faces having more then 1 neghbour edge (each pair)
1395   const Standard_Integer aNF1 = aList1.Extent(); // keep n of faces of the first entity
1396   const Standard_Integer aNF2 = aList2.Extent(); // keep n of faces of the second entity
1397   if(aNF1 + aNF2 < 2) return;
1398
1399 //find Edges
1400   TopTools_ListOfShape aListE1, aListE2;
1401   Standard_Integer aNE1=0,aNE2=0;
1402   if(aNF1 == 2 && !aNF2) {//trivial case - only 2 faces
1403     FindAdjacent2(aList1, aListE1);
1404     aNE1 = aListE1.Extent();
1405   }
1406   else { // result is compound of two ent.
1407     if (aNF1 == 2)  //first ent. has 2 valid faces
1408       FindAdjacent2(aList1, aListE1); // find adjacent edges
1409     else if (aNF1 == 3) // first ent. has 3 valid faces
1410       FindAdjacent3(aList1, aListE1);
1411     else if (aNF1 == 4)  //first ent. has 4 valid faces
1412       FindAdjacent4(aList1, aListE1);
1413 // set number of symmetry Edges of the first ent. 
1414     aNE1 = aListE1.Extent();    
1415
1416 // Second ent.
1417     if (aNF2 == 2)  //second ent. has 2 valid faces
1418       FindAdjacent2(aList2, aListE2);  
1419     else if (aNF2 == 3) 
1420       FindAdjacent3(aList2, aListE2);
1421     else if (aNF2 == 4) 
1422       FindAdjacent4(aList2, aListE2);
1423     
1424     aNE2 =  aListE2.Extent();
1425   }
1426 //aListE1, aListE2 - contains Edges
1427 //  if(aNE1 < 2) return;
1428 // check topological compatibility
1429 //if exist
1430   Handle(TDataStd_IntegerArray) aSAR;
1431   if(!ResultLabel().FindAttribute(TDataStd_IntegerArray::GetID(), aSAR) ) {
1432     aSAR = TDataStd_IntegerArray::Set(ResultLabel(), 1, 2);
1433     aSAR->SetValue(1, 0); //tag num for faces structure
1434     aSAR->SetValue(2, 0); //tag num for edges structure
1435   }
1436   TDF_Label aLabelEDS;
1437   if(aSAR->Value(2)) aLabelEDS = ResultLabel().FindChild(aSAR->Value(2)); // !=0
1438   else {
1439     // initial creation of EDS structure
1440     aLabelEDS = NewShapes();
1441     aSAR->SetValue(2, aLabelEDS.Tag()); //keep tag
1442   }
1443   Handle(TDataStd_Integer) anAtt;
1444   if(aLabelEDS.FindAttribute(TDataStd_Integer::GetID(), anAtt) ) {
1445     // modification : check compatibility
1446     if(anAtt->Get() != aNE1+aNE2) {
1447       cout << "WARNING: Case isn't mantained - Number of Edges was changed!"<<endl;
1448       // mark all structure as Deleted
1449       Standard_Integer aN = aLabelEDS.Tag()+anAtt->Get();
1450       for(Standard_Integer i=aLabelEDS.Tag(); i < aN; i++) {
1451         TDF_Label aLab =  ResultLabel().FindChild(i, Standard_False); 
1452         if(!aLab.IsNull()) {
1453           Handle(TNaming_NamedShape) aNS;
1454           if(aLab.FindAttribute(TNaming_NamedShape::GetID(), aNS)) {
1455             TopoDS_Shape aShape = aNS->Get();
1456             TNaming_Builder aBuilder(aLab);
1457             aBuilder.Delete(aShape); //Deleted
1458           }
1459         }
1460       }
1461 //
1462       Handle(TDF_TagSource) aTS;
1463       ResultLabel().FindAttribute (TDF_TagSource::GetID (), aTS);
1464       if(!aTS.IsNull())
1465         aTS->Set(aLabelEDS.Tag());
1466       anAtt->Set(aNE1+aNE2);
1467     }
1468     
1469   } else
1470     TDataStd_Integer::Set(aLabelEDS, aNE1+aNE2); //keep number of edges 
1471   
1472 // Identification
1473 //  if(aNE1% 2 > 0) return;
1474   gp_Ax1 anAx  = ComputeAxis(MS.Shape2());
1475   Handle(TDF_TagSource) aTS;
1476   ResultLabel().FindAttribute (TDF_TagSource::GetID (), aTS);
1477   if(!aNE2 && aNE1) { // only 1 ent.
1478 //Top || Bot ?
1479     TopTools_Array1OfShape  ArS1(1, aNE1);
1480     SortEdges(aListE1, anAx, ArS1);
1481     for(Standard_Integer i=1; i <= aNE1; i++) {
1482       TopoDS_Shape aShape = ArS1.Value(i);
1483       Standard_Integer aLabTag = aLabelEDS.Tag() + i -1;
1484       TDF_Label aLab =  ResultLabel().FindChild(aLabTag); 
1485       aTS->Set(aLabTag);
1486       TNaming_Builder aBuilder(aLab);
1487       aBuilder.Generated(aShape);
1488     }
1489   } else if(aNE1 && aNE2) { //2 ent.
1490     TopTools_Array1OfShape  ArS1(1, aNE1);
1491     SortEdges(aListE1, anAx, ArS1);
1492     TopTools_Array1OfShape  ArS2(1, aNE2);
1493     SortEdges(aListE2, anAx, ArS2);
1494
1495     gp_Pnt aPnt1 = GetCenterPoint(aListE1.First());
1496 //    gp_Pnt aPnt2 = GetCenterPoint(aListE2.First());
1497     if(IsDirectionPositive(anAx, anAx.Location(), aPnt1)) {
1498       Standard_Integer i;
1499       for(i=1; i <= aNE1; i++) {
1500         TopoDS_Shape aShape = ArS1.Value(i);
1501         Standard_Integer aLabTag = aLabelEDS.Tag() + i - 1;
1502         TDF_Label aLab =  ResultLabel().FindChild(aLabTag); 
1503         aTS->Set(aLabTag);
1504         TNaming_Builder aBuilder(aLab);
1505         aBuilder.Generated(aShape);     
1506       }
1507       Standard_Integer start =  aLabelEDS.Tag() + aNE1;
1508       for(i=1; i <= aNE2; i++) {
1509         TopoDS_Shape aShape = ArS2.Value(i);
1510         Standard_Integer aLabTag = start + i - 1;
1511         TDF_Label aLab =  ResultLabel().FindChild(aLabTag); 
1512         aTS->Set(aLabTag);
1513         TNaming_Builder aBuilder(aLab);
1514         aBuilder.Generated(aShape);     
1515       }
1516     }
1517     else {
1518       Standard_Integer i;
1519       for(i=1; i <= aNE2; i++) {
1520         TopoDS_Shape aShape = ArS2.Value(i);
1521         Standard_Integer aLabTag = aLabelEDS.Tag() + i - 1;
1522         TDF_Label aLab =  ResultLabel().FindChild(aLabTag); 
1523         aTS->Set(aLabTag);
1524         TNaming_Builder aBuilder(aLab);
1525         aBuilder.Generated(aShape);     
1526       }
1527       Standard_Integer start =  aLabelEDS.Tag() + aNE2;
1528       for(i=1; i <= aNE1; i++) {
1529         TopoDS_Shape aShape = ArS1.Value(i);
1530         Standard_Integer aLabTag = start + i - 1;
1531         TDF_Label aLab =  ResultLabel().FindChild(aLabTag); 
1532         aTS->Set(aLabTag);
1533         TNaming_Builder aBuilder(aLab);
1534         aBuilder.Generated(aShape);     
1535       }
1536     }
1537   }
1538 }
1539
1540 //=======================================================================
1541 //function : ISWRCase2
1542 //purpose  : 
1543 //=======================================================================
1544 Standard_Boolean QANewBRepNaming_BooleanOperationFeat::IsWRCase2(const BRepAlgoAPI_BooleanOperation& MS) {
1545   const TopoDS_Shape& Result = MS.Shape();
1546   const TopAbs_ShapeEnum& ResType = ShapeType(Result);
1547   if(ResType  == TopAbs_COMPOUND || ResType >= TopAbs_FACE) return Standard_False;
1548   TopTools_ListOfShape aList;
1549
1550   TopExp_Explorer anExp(Result, TopAbs_FACE);
1551   for(;anExp.More();anExp.Next()) {
1552     if(IsValidSurfType(TopoDS::Face(anExp.Current()))) {
1553       TopExp_Explorer anExp1(Result, TopAbs_FACE);
1554       for(;anExp1.More();anExp1.Next()) {
1555         if(!anExp1.Current().IsSame(anExp.Current()) && !IsValidSurfType(TopoDS::Face(anExp1.Current()))) {
1556           TopTools_ListOfShape aList;
1557           aList.Append(anExp.Current());
1558           aList.Append(anExp1.Current());
1559           TopTools_ListOfShape anEList;
1560           FindAdjacent2(aList, anEList);
1561           if(anEList.Extent() == 2) {
1562             return Standard_True;
1563           }
1564         }
1565       }
1566     }
1567   }
1568   return Standard_False;
1569 }
1570
1571 //=======================================================================
1572 //function : LoadWRCase
1573 //purpose  : 
1574 //=======================================================================
1575
1576 void QANewBRepNaming_BooleanOperationFeat::LoadWRCase(BRepAlgoAPI_BooleanOperation& MS) const {
1577   const TopoDS_Shape& Result = MS.Shape();
1578   const TopAbs_ShapeEnum& ResType = ShapeType(Result);
1579   if(ResType  == TopAbs_COMPOUND || ResType >= TopAbs_FACE) return;
1580   TopTools_ListOfShape aList;
1581
1582   TopExp_Explorer anExp(Result, TopAbs_FACE);
1583   for(;anExp.More();anExp.Next()) {
1584     if(IsValidSurfType(TopoDS::Face(anExp.Current()))) {
1585       TopExp_Explorer anExp1(Result, TopAbs_FACE);
1586       for(;anExp1.More();anExp1.Next()) {
1587         if(!anExp1.Current().IsSame(anExp.Current()) && !IsValidSurfType(TopoDS::Face(anExp1.Current()))) {
1588           TopTools_ListOfShape aList;
1589           aList.Append(anExp.Current());
1590           aList.Append(anExp1.Current());
1591           TopTools_ListOfShape anEList;
1592           FindAdjacent2(aList, anEList);
1593           if(anEList.Extent() == 2) {
1594             
1595             TopTools_ListIteratorOfListOfShape anEIt(anEList);
1596             GProp_GProps anE1Props, anE2Props;
1597             BRepGProp::LinearProperties(anEList.First(), anE1Props);
1598             BRepGProp::LinearProperties(anEList.Last(), anE2Props);
1599
1600             const TDF_Label& WRE1Label = ResultLabel().NewChild();
1601             const TDF_Label& WRE2Label = ResultLabel().NewChild();
1602             const TDF_Label& WRV1Label = ResultLabel().NewChild();
1603             const TDF_Label& WRV2Label = ResultLabel().NewChild();
1604 #ifdef DEB
1605             TDataStd_Name::Set(WRE1Label, "WorkAroundEdge1");
1606             TDataStd_Name::Set(WRE2Label, "WorkAroundEdge2");
1607             TDataStd_Name::Set(WRV1Label, "WorkAroundVertex1");
1608             TDataStd_Name::Set(WRV2Label, "WorkAroundVertex2");
1609 #endif
1610
1611             TNaming_Builder anEBuilder1(WRE1Label);
1612             TNaming_Builder anEBuilder2(WRE2Label);
1613             TNaming_Builder aVBuilder1(WRV1Label);
1614             TNaming_Builder aVBuilder2(WRV2Label);
1615
1616             if(anE1Props.Mass() > anE2Props.Mass()) {
1617               anEBuilder1.Generated(anEList.Last());
1618               anEBuilder2.Generated(anEList.First());
1619               aVBuilder1.Generated(TopExp::FirstVertex(TopoDS::Edge(anEList.Last())));
1620               aVBuilder2.Generated(TopExp::LastVertex(TopoDS::Edge(anEList.Last())));
1621             } else {
1622               anEBuilder1.Generated(anEList.First());
1623               anEBuilder2.Generated(anEList.Last());
1624               aVBuilder1.Generated(TopExp::FirstVertex(TopoDS::Edge(anEList.First())));
1625               aVBuilder2.Generated(TopExp::LastVertex(TopoDS::Edge(anEList.First())));
1626             }
1627           }
1628         }
1629       }
1630     }
1631   }
1632 }