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