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