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