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