Salome HOME
76bba07cceb1e4da88e635e9e2875e504e1b0877
[modules/geom.git] / src / GEOMAlgo / GEOMAlgo_Gluer.cxx
1 // File:        GEOMAlgo_Gluer.cxx
2 // Created:     Sat Dec 04 12:45:53 2004
3 // Author:      Peter KURNEV
4 //              <peter@PREFEX>
5
6
7 #include <GEOMAlgo_Gluer.ixx>
8
9 #include <TColStd_ListOfInteger.hxx>
10 #include <TColStd_ListIteratorOfListOfInteger.hxx>
11
12 #include <gp_Pnt.hxx>
13 #include <gp_Dir.hxx>
14 #include <gp_XYZ.hxx>
15
16 #include <Geom_Curve.hxx>
17 #include <Geom_Surface.hxx>
18
19 #include <Bnd_Box.hxx>
20 #include <Bnd_HArray1OfBox.hxx>
21 #include <Bnd_BoundSortBox.hxx>
22
23 #include <TopLoc_Location.hxx>
24 #include <TopAbs_ShapeEnum.hxx>
25 #include <TopAbs_Orientation.hxx>
26
27 #include <TopoDS.hxx>
28 #include <TopoDS_Edge.hxx>
29 #include <TopoDS_Vertex.hxx>
30 #include <TopoDS_Shape.hxx>
31 #include <TopoDS_Compound.hxx>
32 #include <TopoDS_Wire.hxx>
33 #include <TopoDS_Shell.hxx>
34 #include <TopoDS_Solid.hxx>
35 #include <TopoDS_Iterator.hxx>
36
37 #include <TopTools_IndexedMapOfShape.hxx>
38 #include <TopTools_ListOfShape.hxx>
39 #include <TopTools_ListIteratorOfListOfShape.hxx>
40 #include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
41 #include <TopTools_MapOfShape.hxx>
42 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
43
44 #include <TopExp.hxx>
45 #include <TopExp_Explorer.hxx>
46
47 #include <BRep_Tool.hxx>
48 #include <BRep_Builder.hxx>
49 #include <BRepLib.hxx>
50 #include <BRepTools.hxx>
51 #include <BRepBndLib.hxx>
52
53 #include <IntTools_Context.hxx>
54 #include <BOPTools_Tools.hxx>
55 #include <BOPTools_Tools3D.hxx>
56 #include <BOPTools_Tools2D.hxx>
57 #include <BOP_CorrectTolerances.hxx>
58
59 #include <GEOMAlgo_IndexedDataMapOfIntegerShape.hxx>
60 #include <GEOMAlgo_IndexedDataMapOfShapeBox.hxx>
61 #include <GEOMAlgo_IndexedDataMapOfPassKeyShapeListOfShape.hxx>
62 #include <GEOMAlgo_PassKeyShape.hxx>
63 #include <GEOMAlgo_Tools.hxx>
64 //
65
66 static 
67   void GetSubShapes(const TopoDS_Shape& aS,
68                     TopTools_IndexedMapOfShape& aMSS);
69
70 //=======================================================================
71 //function : GEOMAlgo_Gluer
72 //purpose  : 
73 //=======================================================================
74 GEOMAlgo_Gluer::GEOMAlgo_Gluer()
75 :
76   GEOMAlgo_ShapeAlgo()
77 {
78   myTolerance=0.0001;
79   myTol=myTolerance;
80   myCheckGeometry=Standard_True;
81   myNbAlone=0;
82 }
83 //=======================================================================
84 //function : ~GEOMAlgo_Gluer
85 //purpose  : 
86 //=======================================================================
87 GEOMAlgo_Gluer::~GEOMAlgo_Gluer()
88 {
89 }
90 //=======================================================================
91 //function : SetCheckGeometry
92 //purpose  : 
93 //=======================================================================
94 void GEOMAlgo_Gluer::SetCheckGeometry(const Standard_Boolean aFlag)
95 {
96   myCheckGeometry=aFlag;
97 }
98 //=======================================================================
99 //function : CheckGeometry
100 //purpose  : 
101 //=======================================================================
102 Standard_Boolean GEOMAlgo_Gluer::CheckGeometry() const
103 {
104   return myCheckGeometry;
105 }
106 //=======================================================================
107 //function : AloneShapes
108 //purpose  : 
109 //=======================================================================
110 Standard_Integer GEOMAlgo_Gluer::AloneShapes()const
111 {
112   return myNbAlone;
113 }
114 //=======================================================================
115 //function : Images
116 //purpose  : 
117 //=======================================================================
118 const TopTools_DataMapOfShapeListOfShape& GEOMAlgo_Gluer::Images()const
119 {
120   return myImages;
121 }
122 //=======================================================================
123 //function : Origins
124 //purpose  : 
125 //=======================================================================
126 const TopTools_DataMapOfShapeShape& GEOMAlgo_Gluer::Origins()const
127 {
128   return myOrigins;
129 }
130 //=======================================================================
131 //function : Perform
132 //purpose  : 
133 //=======================================================================
134 void GEOMAlgo_Gluer::Perform()
135 {
136   myErrorStatus=0;
137   myWarningStatus=0;
138   //
139   Standard_Integer i;
140   const Standard_Integer aNb=8;
141   void (GEOMAlgo_Gluer::* pF[aNb])()={
142     &GEOMAlgo_Gluer::CheckData,       &GEOMAlgo_Gluer::InnerTolerance,
143     &GEOMAlgo_Gluer::MakeVertices,    &GEOMAlgo_Gluer::MakeEdges,
144     &GEOMAlgo_Gluer::MakeFaces,       &GEOMAlgo_Gluer::MakeShells,
145     &GEOMAlgo_Gluer::MakeSolids,      &GEOMAlgo_Gluer::CheckResult
146   };
147   //
148   for (i=0; i<aNb; ++i) {
149     (this->*pF[i])();
150     if (myErrorStatus) {
151       return;
152     }
153   }
154 }
155 //=======================================================================
156 //function : MakeVertices
157 //purpose  : 
158 //=======================================================================
159 void GEOMAlgo_Gluer::MakeVertices()
160 {
161   myErrorStatus=0;
162   //
163   Standard_Integer j, i, aNbV, aIndex, aNbVSD;
164   TColStd_ListIteratorOfListOfInteger aIt;
165   Handle(Bnd_HArray1OfBox) aHAB;
166   Bnd_BoundSortBox aBSB;
167   TopoDS_Shape aSTmp, aVF;
168   TopoDS_Vertex aVnew;
169   TopTools_IndexedMapOfShape aMV, aMVProcessed;
170   TopTools_ListIteratorOfListOfShape aItS;
171   TopTools_DataMapIteratorOfDataMapOfShapeListOfShape aItIm;
172   TopTools_DataMapOfShapeListOfShape aMVV;
173   GEOMAlgo_IndexedDataMapOfIntegerShape aMIS;
174   GEOMAlgo_IndexedDataMapOfShapeBox aMSB;
175   //
176   TopExp::MapShapes(myShape, TopAbs_VERTEX, aMV);
177   aNbV=aMV.Extent();
178   if (!aNbV) {
179     myErrorStatus=2; // no vertices in source shape
180     return;
181   }
182   //
183   aHAB=new Bnd_HArray1OfBox(1, aNbV);
184   //
185   for (i=1; i<=aNbV; ++i) {
186     const TopoDS_Shape& aV=aMV(i);
187     Bnd_Box aBox;
188     //
189     aBox.SetGap(myTol); 
190     BRepBndLib::Add(aV, aBox);
191     aHAB->SetValue(i, aBox);
192     aMIS.Add(i, aV);
193     aMSB.Add(aV, aBox); 
194   }
195   //
196   aBSB.Initialize(aHAB);
197   //
198   for (i=1; i<=aNbV; ++i) {
199     const TopoDS_Shape& aV=aMV(i);
200     //
201     if (aMVProcessed.Contains(aV)) {
202       continue;
203     }
204     //
205     const Bnd_Box& aBoxV=aMSB.FindFromKey(aV);
206     const TColStd_ListOfInteger& aLI=aBSB.Compare(aBoxV);
207     aNbVSD=aLI.Extent();
208     if (!aNbVSD) {
209       myErrorStatus=3; // it must not be 
210       return;
211     }
212     //
213     // Images
214     //
215     TopTools_ListOfShape aLVSD;
216     //
217     aIt.Initialize(aLI);
218     for (j=0; aIt.More(); aIt.Next(), ++j) {
219       aIndex=aIt.Value();
220       const TopoDS_Shape& aVx=aMIS.FindFromKey(aIndex);
221       if(!j) {
222         aVF=aVx;
223       }
224       aLVSD.Append(aVx);
225       aMVProcessed.Add(aVx);
226     }
227     //
228     myImages.Bind(aVF, aLVSD);
229   }
230   //
231   // Make new vertices
232   aMV.Clear();
233   aItIm.Initialize(myImages);
234   for (; aItIm.More(); aItIm.Next()) {
235     const TopoDS_Shape& aV=aItIm.Key();
236     const TopTools_ListOfShape& aLVSD=aItIm.Value();
237     aNbVSD=aLVSD.Extent();
238     if (aNbVSD>1) {
239       aMV.Add(aV);
240       MakeVertex(aLVSD, aVnew);
241       aMVV.Bind(aVnew, aLVSD);
242     }
243   }
244   //
245   // UnBind old vertices
246   aNbV=aMV.Extent();
247   for (i=1; i<=aNbV; ++i) {
248     const TopoDS_Shape& aV=aMV(i);
249     myImages.UnBind(aV);
250   }
251   //
252   // Bind new vertices
253   aItIm.Initialize(aMVV);
254   for (; aItIm.More(); aItIm.Next()) {
255     const TopoDS_Shape& aV=aItIm.Key();
256     const TopTools_ListOfShape& aLVSD=aItIm.Value();
257     myImages.Bind(aV, aLVSD);
258   }
259   //
260   // Origins
261   aItIm.Initialize(myImages);
262   for (; aItIm.More(); aItIm.Next()) {
263     const TopoDS_Shape& aV=aItIm.Key();
264     const TopTools_ListOfShape& aLVSD=aItIm.Value();
265     //
266     aItS.Initialize(aLVSD);
267     for (; aItS.More(); aItS.Next()) {
268       const TopoDS_Shape& aVSD=aItS.Value();
269       if (!myOrigins.IsBound(aVSD)) {
270         myOrigins.Bind(aVSD, aV);
271       }
272     }
273   }
274 }
275 //=======================================================================
276 //function : MakeSolids
277 //purpose  : 
278 //=======================================================================
279 void GEOMAlgo_Gluer::MakeSolids()
280 {
281   myErrorStatus=0;
282   //
283   Standard_Integer aNbS;
284   TopAbs_Orientation anOr;
285   TopoDS_Compound aCmp;
286   TopoDS_Solid aNewSolid;
287   TopTools_IndexedMapOfShape aMS;
288   TopExp_Explorer aExpS, aExp;
289   BRep_Builder aBB;
290   //
291   aBB.MakeCompound(aCmp);
292   //
293   aNbS=aMS.Extent();
294   aExpS.Init(myShape, TopAbs_SOLID);
295   for (; aExpS.More(); aExpS.Next()) {
296     const TopoDS_Solid& aSolid=TopoDS::Solid(aExpS.Current());
297     if (aMS.Contains(aSolid)) {
298       continue;
299     }
300     aMS.Add(aSolid);
301     //
302     anOr=aSolid.Orientation();
303     //
304     aBB.MakeSolid(aNewSolid);
305     aNewSolid.Orientation(anOr);
306     //
307     aExp.Init(aSolid, TopAbs_SHELL);
308     for (; aExp.More(); aExp.Next()) {
309       const TopoDS_Shape& aShell=aExp.Current();
310       const TopoDS_Shape& aShellR=myOrigins.Find(aShell);
311       aBB.Add(aNewSolid, aShellR);
312     }
313     //
314     TopTools_ListOfShape aLS;
315     //
316     aLS.Append(aSolid);
317     myImages.Bind(aNewSolid, aLS);
318     myOrigins.Bind(aSolid, aNewSolid);
319     //
320     aBB.Add(aCmp, aNewSolid);
321   }
322   //
323   myResult=aCmp;
324   //
325   aNbS=aMS.Extent();
326   if (aNbS) {
327     Standard_Real aTol=1.e-7;
328     BOP_CorrectTolerances::CorrectCurveOnSurface(myResult);
329   }
330 }
331 //=======================================================================
332 //function : MakeShells
333 //purpose  : 
334 //=======================================================================
335 void GEOMAlgo_Gluer::MakeShells()
336 {
337   myErrorStatus=0;
338   //
339   Standard_Boolean bIsToReverse;
340   Standard_Integer i, aNbS;
341   TopAbs_Orientation anOr;
342   TopoDS_Shell aNewShell;
343   TopoDS_Face aFR;
344   TopTools_IndexedMapOfShape aMS;
345   TopExp_Explorer aExp;
346   BRep_Builder aBB;
347   //
348   TopExp::MapShapes(myShape, TopAbs_SHELL, aMS);
349   //
350   aNbS=aMS.Extent();
351   for (i=1; i<=aNbS; ++i) {
352     const TopoDS_Shell& aShell=TopoDS::Shell(aMS(i));
353     anOr=aShell.Orientation();
354     //
355     aBB.MakeShell(aNewShell);
356     aNewShell.Orientation(anOr);
357     aExp.Init(aShell, TopAbs_FACE);
358     for (; aExp.More(); aExp.Next()) {
359       const TopoDS_Face& aF=TopoDS::Face(aExp.Current());
360       aFR=TopoDS::Face(myOrigins.Find(aF));
361       if (aFR.IsSame(aF)) {
362         aBB.Add(aNewShell, aF);
363         continue;
364       }
365       bIsToReverse=IsToReverse(aFR, aF);
366       if (bIsToReverse) {
367         aFR.Reverse();
368       }
369       aBB.Add(aNewShell, aFR);
370     }
371     //
372     TopTools_ListOfShape aLS;
373     //
374     aLS.Append(aShell);
375     myImages.Bind(aNewShell, aLS);
376     myOrigins.Bind(aShell, aNewShell);
377   }
378 }
379 //=======================================================================
380 //function : MakeFaces
381 //purpose  : 
382 //=======================================================================
383 void GEOMAlgo_Gluer::MakeFaces()
384 {
385   MakeShapes(TopAbs_FACE);
386 }
387 //=======================================================================
388 //function : MakeEdges
389 //purpose  : 
390 //=======================================================================
391 void GEOMAlgo_Gluer::MakeEdges()
392 {
393   MakeShapes(TopAbs_EDGE);
394 }
395 //=======================================================================
396 //function : MakeShapes
397 //purpose  : 
398 //=======================================================================
399 void GEOMAlgo_Gluer::MakeShapes(const TopAbs_ShapeEnum aType)
400 {
401   myErrorStatus=0;
402   //
403   Standard_Boolean bHasNewSubShape;
404   Standard_Integer i, aNbF, aNbSDF, iErr;
405   TopoDS_Shape aNewShape;
406   TopTools_IndexedMapOfShape aMF;
407   TopTools_ListIteratorOfListOfShape aItS;
408   GEOMAlgo_PassKeyShape aPKF;
409   GEOMAlgo_IndexedDataMapOfPassKeyShapeListOfShape aMPKLF;
410   //
411   TopExp::MapShapes(myShape, aType, aMF);
412   //
413   aNbF=aMF.Extent();
414   for (i=1; i<=aNbF; ++i) {
415     const TopoDS_Shape& aS=aMF(i);
416     // 
417     aPKF.Clear();
418     if (aType==TopAbs_FACE) {
419       const TopoDS_Face& aF=TopoDS::Face(aS);
420       FacePassKey(aF, aPKF);
421     }
422     else if (aType==TopAbs_EDGE) {
423       const TopoDS_Edge& aE=TopoDS::Edge(aS);
424       EdgePassKey(aE, aPKF);
425     }
426     //
427     if (myErrorStatus) {
428       return;
429     }
430     //
431     if (aMPKLF.Contains(aPKF)) {
432       TopTools_ListOfShape& aLSDF=aMPKLF.ChangeFromKey(aPKF);
433       aLSDF.Append(aS);
434     }
435     else {
436       TopTools_ListOfShape aLSDF;
437       //
438       aLSDF.Append(aS);
439       aMPKLF.Add(aPKF, aLSDF);
440     }
441   }
442   // check geometric coincidence
443   if (myCheckGeometry) {
444     iErr=GEOMAlgo_Tools::RefineSDShapes(aMPKLF, myTol, myContext); 
445     if (iErr) {
446       myErrorStatus=200;
447       return;
448     }
449   }
450   //
451   // Images/Origins
452   //
453   aNbF=aMPKLF.Extent();
454   for (i=1; i<=aNbF; ++i) {
455     const TopTools_ListOfShape& aLSDF=aMPKLF(i);
456     aNbSDF=aLSDF.Extent();
457     if (!aNbSDF) {
458       myErrorStatus=4; // it must not be
459     }
460     //
461     const TopoDS_Shape& aS1=aLSDF.First();
462     //
463     bHasNewSubShape=Standard_True;
464     // prevent creation of a new shape if there are not
465     // new subshapes of aSS among the originals
466     if (aNbSDF==1) {
467       bHasNewSubShape=HasNewSubShape(aS1);
468       if (!bHasNewSubShape) {
469         aNewShape=aS1;
470         aNewShape.Orientation(TopAbs_FORWARD);
471       }
472     }
473     //
474     if (bHasNewSubShape) { 
475       if (aType==TopAbs_FACE) {
476         TopoDS_Face aNewFace;
477         //
478         const TopoDS_Face& aF1=TopoDS::Face(aS1);
479         MakeFace(aF1, aNewFace);
480         aNewShape=aNewFace;
481       }
482       else if (aType==TopAbs_EDGE) {
483         TopoDS_Edge aNewEdge;
484         //
485         const TopoDS_Edge& aE1=TopoDS::Edge(aS1);
486         MakeEdge(aE1, aNewEdge);
487         aNewShape=aNewEdge;
488       }
489     }
490     //
491     myImages.Bind(aNewShape, aLSDF);
492     // origins
493     aItS.Initialize(aLSDF);
494     for (; aItS.More(); aItS.Next()) {
495       const TopoDS_Shape& aFSD=aItS.Value();
496       if (!myOrigins.IsBound(aFSD)) {
497         myOrigins.Bind(aFSD, aNewShape);
498       }
499     }
500   }
501 }
502 //=======================================================================
503 //function : CheckResult
504 //purpose  : 
505 //=======================================================================
506 void GEOMAlgo_Gluer::CheckResult()
507 {
508   myErrorStatus=0;
509   //
510   if (myResult.IsNull()) {
511     myErrorStatus=6;
512     return; 
513   }
514   // 
515   Standard_Boolean bFound;
516   Standard_Integer i, j, aNbS, aNbFS, aNbSx;
517   TopTools_IndexedMapOfShape aMS, aMFS;
518   TopTools_IndexedDataMapOfShapeListOfShape aMFR;
519   //
520   TopExp::MapShapesAndAncestors(myResult, TopAbs_FACE, TopAbs_SOLID, aMFR);
521   TopExp::MapShapes(myResult, TopAbs_SOLID, aMS);
522   //
523   
524   myNbAlone=0;
525   aNbS=aMS.Extent();
526   for (i=1; i<=aNbS; ++i) {
527     const TopoDS_Shape& aSolid=aMS(i);
528     //
529     aMFS.Clear();
530     TopExp::MapShapes(aSolid, TopAbs_FACE, aMFS);
531     //
532     bFound=Standard_False;
533     aNbFS=aMFS.Extent();
534     for (j=1; j<=aNbFS; ++j) {
535       const TopoDS_Shape& aFS=aMFS(j);
536       if (aMFR.Contains(aFS)) {
537         const TopTools_ListOfShape& aLSx=aMFR.FindFromKey(aFS);
538         aNbSx=aLSx.Extent();
539         if (aNbSx==2) {
540           bFound=!bFound;
541           break;
542         }
543       }
544     }
545     //
546     if (!bFound) {
547       myWarningStatus=1;
548       ++myNbAlone;
549       //break;
550     }
551   }
552 }
553 //=======================================================================
554 //function : CheckData
555 //purpose  : 
556 //=======================================================================
557 void GEOMAlgo_Gluer::CheckData()
558 {
559   myErrorStatus=0;
560   //
561   if (myShape.IsNull()) {
562     myErrorStatus=5;
563     return; 
564   }
565 }
566 //=======================================================================
567 //function : InnerTolerance
568 //purpose  : 
569 //=======================================================================
570 void GEOMAlgo_Gluer::InnerTolerance()
571 {
572   myErrorStatus=0;
573   //
574   /*
575   Standard_Integer i;
576   Standard_Real aX[3][2], dH, dHmin, aCoef, aTolTresh;
577   Bnd_Box aBox;
578   //
579   BRepBndLib::Add(myShape, aBox);
580   aBox.Get(aX[0][0], aX[1][0], aX[2][0], aX[0][1], aX[1][1], aX[2][1]);
581   //
582   dHmin=aX[0][1]-aX[0][0];
583   for (i=1; i<3; ++i) {
584     dH=aX[i][1]-aX[i][0];
585     if (dH<dHmin) {
586       dHmin=dH;
587     }
588   }
589   //
590   myTol=myTolerance;
591   aCoef=0.01;
592   aTolTresh=aCoef*dHmin;
593   if (myTol>aTolTresh) {
594     myTol=aTolTresh;
595   }
596   */
597   myTol=myTolerance;
598 }
599 //=======================================================================
600 //function : FacePassKey
601 //purpose  : 
602 //=======================================================================
603 void GEOMAlgo_Gluer::FacePassKey(const TopoDS_Face& aF, 
604                                  GEOMAlgo_PassKeyShape& aPK)
605 {
606   Standard_Integer i, aNbE, aNbMax;
607   TopTools_ListOfShape aLE;
608   TopTools_IndexedMapOfShape aME;
609   //
610   TopExp::MapShapes(aF, TopAbs_EDGE, aME);
611   aNbE=aME.Extent();
612   aNbMax=aPK.NbMax();
613   if (!aNbE || aNbE>aNbMax) {
614      myErrorStatus=101; // temprorary
615      return;
616   }
617   //
618   for (i=1; i<=aNbE; ++i) {
619     const TopoDS_Shape& aE=aME(i);
620     if (!myOrigins.IsBound(aE)) {
621       myErrorStatus=102;
622       return;
623     }
624     const TopoDS_Shape& aER=myOrigins.Find(aE);
625     aLE.Append(aER);
626   }
627   aPK.SetIds(aLE);
628 }
629 //=======================================================================
630 //function : EdgePassKey
631 //purpose  : 
632 //=======================================================================
633 void GEOMAlgo_Gluer::EdgePassKey(const TopoDS_Edge& aE, 
634                                  GEOMAlgo_PassKeyShape& aPK)
635 {
636   TopoDS_Vertex aV1, aV2;
637   //
638   TopExp::Vertices(aE, aV1, aV2);
639   //
640   if (!myOrigins.IsBound(aV1) || !myOrigins.IsBound(aV2) ) {
641      myErrorStatus=100;
642      return;
643   }
644   const TopoDS_Shape& aVR1=myOrigins.Find(aV1);
645   const TopoDS_Shape& aVR2=myOrigins.Find(aV2);
646   aPK.SetIds(aVR1, aVR2);
647 }
648 //=======================================================================
649 //function : MakeVertex
650 //purpose  : 
651 //=======================================================================
652 void GEOMAlgo_Gluer::MakeVertex(const TopTools_ListOfShape& aLV, 
653                                 TopoDS_Vertex& aNewVertex)
654 {
655   Standard_Integer aNbV;
656   Standard_Real aTolV, aD, aDmax;
657   gp_XYZ aGC;
658   gp_Pnt aP3D, aPGC;
659   TopoDS_Vertex aVx;
660   BRep_Builder aBB;
661   TopTools_ListIteratorOfListOfShape aIt;
662   //
663   aNbV=aLV.Extent();
664   if (!aNbV) {
665     return;
666   }
667   //
668   // center of gravity
669   aGC.SetCoord(0.,0.,0.);
670   aIt.Initialize(aLV);
671   for (; aIt.More(); aIt.Next()) {
672     aVx=TopoDS::Vertex(aIt.Value());
673     aP3D=BRep_Tool::Pnt(aVx);
674     aGC+=aP3D.XYZ();
675   }
676   aGC/=(Standard_Real)aNbV;
677   aPGC.SetXYZ(aGC);
678   //
679   // tolerance value
680   aDmax=-1.;
681   aIt.Initialize(aLV);
682   for (; aIt.More(); aIt.Next()) {
683     aVx=TopoDS::Vertex(aIt.Value());
684     aP3D=BRep_Tool::Pnt(aVx);
685     aTolV=BRep_Tool::Tolerance(aVx);
686     aD=aPGC.Distance(aP3D)+aTolV;
687     if (aD>aDmax) {
688       aDmax=aD;
689     }
690   }
691   //
692   aBB.MakeVertex (aNewVertex, aPGC, aDmax);
693 }
694 //=======================================================================
695 //function : MakeEdge
696 //purpose  : 
697 //=======================================================================
698 void GEOMAlgo_Gluer::MakeEdge(const TopoDS_Edge& aE, 
699                               TopoDS_Edge& aNewEdge)
700 {
701   myErrorStatus=0;
702   //
703   Standard_Boolean bIsDE;
704   Standard_Real aT1, aT2;
705   TopoDS_Vertex aV1, aV2, aVR1, aVR2;
706   TopoDS_Edge aEx;
707   //
708   bIsDE=BRep_Tool::Degenerated(aE);
709   //
710   aEx=aE;
711   aEx.Orientation(TopAbs_FORWARD);
712   //
713   TopExp::Vertices(aEx, aV1, aV2);
714   //
715   aT1=BRep_Tool::Parameter(aV1, aEx);
716   aT2=BRep_Tool::Parameter(aV2, aEx);
717   //
718   aVR1=TopoDS::Vertex(myOrigins.Find(aV1));
719   aVR1.Orientation(TopAbs_FORWARD);
720   aVR2=TopoDS::Vertex(myOrigins.Find(aV2));
721   aVR2.Orientation(TopAbs_REVERSED);
722   //
723   if (bIsDE) {
724     Standard_Real aTol;
725     BRep_Builder aBB;
726     TopoDS_Edge E;
727     TopAbs_Orientation anOrE;
728     //
729     anOrE=aE.Orientation();
730     aTol=BRep_Tool::Tolerance(aE);
731     //
732     E=aEx;
733     E.EmptyCopy();
734     //
735     aBB.Add  (E, aVR1);
736     aBB.Add  (E, aVR2);
737     aBB.Range(E, aT1, aT2);
738     aBB.Degenerated(E, Standard_True);
739     aBB.UpdateEdge(E, aTol);
740     //
741     aNewEdge=E;
742   }
743   //
744   else {
745     BOPTools_Tools::MakeSplitEdge(aEx, aVR1, aT1, aVR2, aT2, aNewEdge); 
746   }
747 }
748 //
749 //=======================================================================
750 //function : MakeFace
751 //purpose  : 
752 //=======================================================================
753 void GEOMAlgo_Gluer::MakeFace(const TopoDS_Face& aF, 
754                               TopoDS_Face& aNewFace)
755 {
756   myErrorStatus=0;
757   //
758   Standard_Boolean bIsToReverse, bIsUPeriodic;
759   Standard_Real aTol, aUMin, aUMax, aVMin, aVMax;
760   TopoDS_Edge aER;
761   TopoDS_Wire newWire;
762   TopoDS_Face aFFWD, newFace;
763   TopLoc_Location aLoc;
764   Handle(Geom_Surface) aS;
765   Handle(Geom2d_Curve) aC2D;
766   TopExp_Explorer aExpW, aExpE;
767   BRep_Builder aBB;
768   //
769   aFFWD=aF;
770   aFFWD.Orientation(TopAbs_FORWARD);
771   //
772   aS=BRep_Tool::Surface(aFFWD, aLoc);
773   bIsUPeriodic=GEOMAlgo_Tools::IsUPeriodic(aS);
774   aTol=BRep_Tool::Tolerance(aFFWD);
775   BRepTools::UVBounds(aF, aUMin, aUMax, aVMin, aVMax);
776   //
777   aBB.MakeFace (newFace, aS, aLoc, aTol);
778   //
779   aExpW.Init(aFFWD, TopAbs_WIRE);
780   for (; aExpW.More(); aExpW.Next()) {
781     aBB.MakeWire(newWire);
782     const TopoDS_Wire& aW=TopoDS::Wire(aExpW.Current());
783     aExpE.Init(aW, TopAbs_EDGE);
784     for (; aExpE.More(); aExpE.Next()) {
785       const TopoDS_Edge& aE=TopoDS::Edge(aExpE.Current());
786       aER=TopoDS::Edge(myOrigins.Find(aE));
787       //
788       aER.Orientation(TopAbs_FORWARD);
789       if (!BRep_Tool::Degenerated(aER)) {
790         // build p-curve
791         if (bIsUPeriodic) {
792           GEOMAlgo_Tools::RefinePCurveForEdgeOnFace(aER, aFFWD, aUMin, aUMax);
793         }
794         BOPTools_Tools2D::BuildPCurveForEdgeOnFace(aER, aFFWD);
795         
796         // orient image 
797         bIsToReverse=BOPTools_Tools3D::IsSplitToReverse1(aER, aE, myContext);
798         if (bIsToReverse) {
799           aER.Reverse();
800         }
801       }
802       else {
803         aER.Orientation(aE.Orientation());
804       }
805       //
806       aBB.Add(newWire, aER);
807     }
808     //modified by NIZNHY-PKV Mon Jan 31 17:26:36 2005f
809     //
810     TopTools_ListOfShape aLW;
811     //
812     aLW.Append(aW);
813     myImages.Bind(newWire, aLW);
814     myOrigins.Bind(aW, newWire);
815     //
816     //modified by NIZNHY-PKV Mon Jan 31 17:26:41 2005 t
817     aBB.Add(newFace, newWire);
818   }
819   aNewFace=newFace;
820 }
821 //=======================================================================
822 //function : IsToReverse
823 //purpose  : 
824 //=======================================================================
825 Standard_Boolean GEOMAlgo_Gluer::IsToReverse(const TopoDS_Face& aFR,
826                                              const TopoDS_Face& aF)
827 {
828   Standard_Boolean bRet;
829   Standard_Real aT, aT1, aT2, aTR, aScPr;
830   TopExp_Explorer aExp;
831   Handle(Geom_Curve)aC3D;
832   gp_Pnt aP;
833   gp_Dir aDNF, aDNFR;
834   //
835   bRet=Standard_False;
836   //
837   aExp.Init(aF, TopAbs_EDGE);
838   for (; aExp.More(); aExp.Next()) {
839     const TopoDS_Edge& aE=TopoDS::Edge(aExp.Current());
840     //
841     if (BRep_Tool::Degenerated(aE)) {
842       continue;
843     }
844     //
845     const TopoDS_Edge& aER=TopoDS::Edge(myOrigins.Find(aE));
846     //
847     aC3D=BRep_Tool::Curve(aE, aT1, aT2);
848     aT=BOPTools_Tools2D::IntermediatePoint(aT1, aT2);
849     aC3D->D0(aT, aP);
850     myContext.ProjectPointOnEdge(aP, aER, aTR);
851     //
852     BOPTools_Tools3D::GetNormalToFaceOnEdge (aE, aF, aT, aDNF);
853     if (aF.Orientation()==TopAbs_REVERSED) {
854       aDNF.Reverse();
855     }
856     //
857     BOPTools_Tools3D::GetNormalToFaceOnEdge (aER, aFR, aTR, aDNFR);
858     if (aFR.Orientation()==TopAbs_REVERSED) {
859       aDNFR.Reverse();
860     }
861     //
862     aScPr=aDNF*aDNFR;
863     return (aScPr<0.);
864   }
865   return bRet;
866 }
867 //=======================================================================
868 //function : HasNewSubShape
869 //purpose  : 
870 //=======================================================================
871 Standard_Boolean GEOMAlgo_Gluer::HasNewSubShape(const TopoDS_Shape& aS)const
872 {
873   Standard_Boolean bRet;
874   Standard_Integer i, aNbSS;
875   TopTools_IndexedMapOfShape aMSS;
876   //
877   GetSubShapes(aS, aMSS);
878   //
879   bRet=Standard_False;
880   aNbSS=aMSS.Extent();
881   for (i=1; i<=aNbSS; ++i) {
882     const TopoDS_Shape& aSS=aMSS(i);
883     if (aSS.ShapeType()==TopAbs_WIRE) {
884       continue;
885     }
886     //
887     bRet=!myOrigins.IsBound(aSS);
888     if (bRet) {
889       return bRet;
890     }
891     //
892     const TopoDS_Shape& aSSIm=myOrigins.Find(aSS);
893     bRet=!aSSIm.IsSame(aSS);
894     if (bRet) {
895       return bRet;
896     }
897   }
898   return bRet;
899 }
900 //=======================================================================
901 //function : GetSubShapes
902 //purpose  : 
903 //=======================================================================
904 void GetSubShapes(const TopoDS_Shape& aS,
905                   TopTools_IndexedMapOfShape& aMSS)
906 {
907   Standard_Integer aR;
908   TopAbs_ShapeEnum aType;
909   TopoDS_Iterator aIt;
910   //
911   aType=aS.ShapeType();
912   aR=(Standard_Integer)aType+1;
913   if (aR>TopAbs_VERTEX) {
914     return;
915   }
916   //
917   aIt.Initialize(aS);
918   for (; aIt.More(); aIt.Next()) {
919     const TopoDS_Shape& aSS=aIt.Value();
920     aMSS.Add(aSS);
921     GetSubShapes(aSS, aMSS);
922   }
923 }
924 //=======================================================================
925 //function : Modified
926 //purpose  : 
927 //=======================================================================
928 const TopTools_ListOfShape& GEOMAlgo_Gluer::Modified (const TopoDS_Shape& aS) 
929 {
930   TopAbs_ShapeEnum aType;
931   //
932   myGenerated.Clear();
933   //
934   aType=aS.ShapeType();
935   if (aType==TopAbs_VERTEX ||
936       aType==TopAbs_EDGE   || 
937       aType==TopAbs_WIRE   || //modified by NIZNHY-PKV Mon Jan 31 17:18:36 2005ft
938       aType==TopAbs_FACE   || 
939       aType==TopAbs_SHELL  || //modified by NIZNHY-PKV Mon Jan 31 17:18:36 2005ft
940       aType==TopAbs_SOLID) {  //modified by NIZNHY-PKV Mon Jan 31 17:18:36 2005ft
941     if(myOrigins.IsBound(aS)) {
942       const TopoDS_Shape& aSnew=myOrigins.Find(aS);
943       if (!aSnew.IsSame(aS)) {
944         myGenerated.Append(aSnew);
945       }
946     }
947   }
948   //
949   return myGenerated;
950 }
951 //=======================================================================
952 //function : Generated
953 //purpose  : 
954 //=======================================================================
955 const TopTools_ListOfShape& GEOMAlgo_Gluer::Generated(const TopoDS_Shape& )
956 {
957   myGenerated.Clear();
958   return myGenerated;
959 }
960 //=======================================================================
961 //function : IsDeleted
962 //purpose  : 
963 //=======================================================================
964 Standard_Boolean GEOMAlgo_Gluer::IsDeleted (const TopoDS_Shape& aS)
965 {
966   Standard_Boolean bRet=Standard_False;
967   //
968   const TopTools_ListOfShape& aL=Modified(aS);
969   bRet=!aL.IsEmpty();
970   //
971   return bRet;
972 }
973 //
974 // ErrorStatus
975 //
976 // 1   - the object is just initialized 
977 // 2   - no vertices found in source shape
978 // 3   - nb same domain vertices for the vertex Vi =0
979 // 4   - nb same domain edges(faces) for the edge Ei(face Fi)  =0
980 // 5   - source shape is Null
981 // 6   - result shape is Null
982 // 101 - nb edges > PassKey.NbMax() in FacesPassKey()
983 // 102 - the edge Ei can not be found in myOrigins Map
984 // 100 - the vertex Vi can not be found in myOrigins Map
985 //
986 // WarningStatus
987 //
988 // 1   - some shapes can not be glued by faces
989 //