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