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