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