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