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