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