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