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