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