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