Salome HOME
Bugs 20300 and 20361: Error occured during check of geometric coincidence.
[modules/geom.git] / src / GEOMAlgo / GEOMAlgo_Gluer1.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_Gluer1.cxx
23 // Created:     Wed Jan 24 11:52:27 2007
24 // Author:      Peter KURNEV
25 //              <pkv@irinox>
26 //
27 #include <GEOMAlgo_Gluer1.ixx>
28
29 #include <Geom_Surface.hxx>
30
31 #include <TopLoc_Location.hxx>
32
33 #include <TopoDS.hxx>
34 #include <TopoDS_Shape.hxx>
35 #include <TopoDS_Face.hxx>
36 #include <TopoDS_Iterator.hxx>
37
38 #include <BRep_Builder.hxx>
39 #include <BRep_Tool.hxx>
40
41 #include <TopExp.hxx>
42
43 #include <TopTools_DataMapIteratorOfDataMapOfShapeShape.hxx>
44 #include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
45 #include <TopTools_ListOfShape.hxx>
46 #include <TopTools_ListIteratorOfListOfShape.hxx>
47 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
48 #include <TopTools_MapOfShape.hxx>
49 #include <TopTools_MapOfShape.hxx>
50 #include <TopTools_DataMapOfShapeShape.hxx>
51
52 #include <GEOMAlgo_CoupleOfShapes.hxx>
53 #include <GEOMAlgo_PassKeyShape.hxx>
54 #include <GEOMAlgo_ListIteratorOfListOfCoupleOfShapes.hxx>
55 #include <GEOMAlgo_DataMapOfPassKeyShapeShape.hxx>
56 #include <GEOMAlgo_DataMapIteratorOfDataMapOfPassKeyShapeShape.hxx>
57  
58 //=======================================================================
59 //class : GEOMAlgo_CoupleOfInteger
60 //purpose  : 
61 //=======================================================================
62 class GEOMAlgo_CoupleOfInteger {
63  //
64  public:
65   //
66   GEOMAlgo_CoupleOfInteger() {
67     myInt1=0;
68     myInt2=0;
69   }
70   //
71   ~GEOMAlgo_CoupleOfInteger() {
72   }
73   //
74   void SetValues(const Standard_Integer aI1,
75                  const Standard_Integer aI2) {
76     myInt1=aI1;    
77     myInt2=aI2;
78   }
79   //
80   void SetValue1(const Standard_Integer aI1) {
81     myInt1=aI1;    
82   }
83   //
84   void SetValue2(const Standard_Integer aI1) {
85     myInt1=aI1;    
86   }
87   //
88   void Values(Standard_Integer& aI1,
89               Standard_Integer& aI2) const {
90     aI1=myInt1;    
91     aI2=myInt2;
92   }
93   //
94   Standard_Integer Value1()const {
95     return myInt1;    
96   }
97   //
98   Standard_Integer Value2()const {
99     return myInt2;    
100   }
101   //
102  protected:
103   Standard_Integer myInt1;
104   Standard_Integer myInt2;
105 };
106 //
107 //=======================================================================
108 //
109 static
110   void SortShell(const Standard_Integer , 
111                  GEOMAlgo_CoupleOfInteger* );
112 static
113   void RefineSolid(const TopoDS_Shape& ,
114                    const TopTools_DataMapOfShapeShape& ,
115                    TopTools_DataMapOfShapeShape& );
116 static
117   void MakeFaceToReplace(const TopoDS_Face& ,
118                          TopoDS_Face& );
119 //
120 //=======================================================================
121 //function : GEOMAlgo_Gluer1
122 //purpose  : 
123 //=======================================================================
124   GEOMAlgo_Gluer1::GEOMAlgo_Gluer1()
125 :
126   GEOMAlgo_Gluer()
127 {
128 }
129 //=======================================================================
130 //function : 
131 //purpose  : 
132 //=======================================================================
133   GEOMAlgo_Gluer1::~GEOMAlgo_Gluer1()
134 {
135 }
136 //=======================================================================
137 //function : SetFacesToUnglue
138 //purpose  : 
139 //=======================================================================
140   void GEOMAlgo_Gluer1::SetFacesToUnglue(const GEOMAlgo_ListOfCoupleOfShapes& aLCS)
141 {
142   myFacesToUnglue=aLCS;
143 }
144 //=======================================================================
145 //function : FacesToUnglue
146 //purpose  : 
147 //=======================================================================
148   const GEOMAlgo_ListOfCoupleOfShapes& GEOMAlgo_Gluer1::FacesToUnglue()const
149 {
150   return myFacesToUnglue;
151 }
152 //=======================================================================
153 //function : GluedFaces
154 //purpose  : 
155 //=======================================================================
156   const GEOMAlgo_ListOfCoupleOfShapes& GEOMAlgo_Gluer1::GluedFaces()const
157 {
158   return myGluedFaces;
159 }
160 //=======================================================================
161 //function : RejectedFaces
162 //purpose  : 
163 //=======================================================================
164   const GEOMAlgo_ListOfCoupleOfShapes& GEOMAlgo_Gluer1::RejectedFaces()const
165 {
166   return myRejectedFaces;
167 }
168 //=======================================================================
169 //function : Perform
170 //purpose  : 
171 //=======================================================================
172   void GEOMAlgo_Gluer1::Perform()
173 {
174   // 1.
175   GEOMAlgo_Gluer::Perform();
176   if (myErrorStatus) {
177     return;
178   }
179   //
180   FillGluedFaces();
181     if (myErrorStatus) {
182     return;
183   }
184 }
185 //=======================================================================
186 //function : FillGluedFaces
187 //purpose  : 
188 //=======================================================================
189   void GEOMAlgo_Gluer1::FillGluedFaces()
190 {
191   myErrorStatus=0;
192   //
193   Standard_Integer aNbIm, aNbS, i;
194   TopAbs_ShapeEnum aType;
195   TopTools_ListIteratorOfListOfShape aItLS;
196   TopTools_DataMapIteratorOfDataMapOfShapeListOfShape aItIm;
197   GEOMAlgo_CoupleOfShapes aCS;
198   GEOMAlgo_PassKeyShape aPKS;
199   //
200   myMapGN.Clear();
201   myGluedFaces.Clear();
202   //
203   aNbIm=myImages.Extent();
204   aItIm.Initialize(myImages);
205   for (; aItIm.More(); aItIm.Next()) {
206     const TopoDS_Shape& aSnew=aItIm.Key();
207     aType=aSnew.ShapeType();
208     if (aType!=TopAbs_FACE) {
209       continue;
210     }
211     //
212     const TopTools_ListOfShape& aLS=aItIm.Value();
213     aNbS=aLS.Extent();
214     if (aNbS!=2) {
215       continue;
216     }
217     //
218     TopoDS_Shape aSold[2];
219     aItLS.Initialize(aLS);
220     for (i=0; aItLS.More(); aItLS.Next(), ++i) {
221       const TopoDS_Shape& aSi=aItLS.Value();
222       aSold[i]=aItLS.Value();
223     }
224     //
225     aCS.SetShapes(aSold[0], aSold[1]);
226     myGluedFaces.Append(aCS);
227     //
228     aPKS.Clear();
229     aPKS.SetShapes(aSold[0], aSold[1]);
230     myMapGN.Bind(aPKS, aSnew);
231   }
232 }
233 //=======================================================================
234 //function : UnglueFaces
235 //purpose  : 
236 //=======================================================================
237   void GEOMAlgo_Gluer1::UnglueFaces()
238 {
239   if (myErrorStatus) {
240     return;
241   }
242   //
243   Standard_Boolean bFound;
244   Standard_Integer i, aNbUN, aNbS, aNbF, iX;
245   TopTools_IndexedDataMapOfShapeListOfShape aMFSR, aMFS, aMSF;
246   TopTools_ListIteratorOfListOfShape aItLS, aItLS1;
247   GEOMAlgo_PassKeyShape aPKS;
248   GEOMAlgo_ListIteratorOfListOfCoupleOfShapes aItCS;
249   GEOMAlgo_DataMapOfPassKeyShapeShape aMapUN;
250   GEOMAlgo_DataMapIteratorOfDataMapOfPassKeyShapeShape aItUN;
251   GEOMAlgo_CoupleOfInteger *pIx;
252   //
253   if (myResult.IsNull()) {
254     myErrorStatus=200; // no result
255     return;
256   }
257   myWarningStatus=0;
258   myRejectedFaces.Clear();
259   //
260   // 0. Fill map [Face]/Solid for myResult: aMFSR
261   TopExp::MapShapesAndAncestors(myResult, TopAbs_FACE, TopAbs_SOLID, aMFSR);
262   //
263   // 1. Fill Faces to process:  aMapUN : [Fold1, Fold2] / Fnew
264   aNbUN=myFacesToUnglue.Extent();
265   if (!aNbUN) {
266     // all faces that can be unglued will be unglued
267     aMapUN=myMapGN;
268     myFacesToUnglue=myGluedFaces;
269   }
270   else {
271     aItCS.Initialize(myFacesToUnglue);
272     for (; aItCS.More(); aItCS.Next()) {
273       const GEOMAlgo_CoupleOfShapes& aCS=aItCS.Value();
274       const TopoDS_Shape& aS1=aCS.Shape1();
275       const TopoDS_Shape& aS2=aCS.Shape2();
276       aPKS.Clear();
277       aPKS.SetShapes(aS1, aS2);
278       if (!myMapGN.IsBound(aPKS)) {
279         //some faces, wanted to unglue, are not glued at all;
280         myWarningStatus=2; 
281         myRejectedFaces.Append(aCS);
282         continue;
283       }
284       //
285       const TopoDS_Shape& aFN=myMapGN.Find(aPKS);
286       aMapUN.Bind(aPKS, aFN);
287     }
288   }
289   //
290   // 2 Fill map FN/Solids for myResult: aMFS
291   aNbUN=aMapUN.Extent();
292   aItUN.Initialize(aMapUN);
293   for (; aItUN.More(); aItUN.Next()) {
294     const TopoDS_Shape& aFN=aItUN.Value();
295     if (!aMFSR.Contains(aFN)) {
296       myWarningStatus=3; // how can it be
297       continue;
298     }
299     //
300     const TopTools_ListOfShape& aLS=aMFSR.FindFromKey(aFN);
301     aNbS=aLS.Extent();
302     if (aNbS!=2) {
303       // wrong result: More than 2 solids shared one face
304       myWarningStatus=4; 
305       continue;
306     }
307     aMFS.Add(aFN, aLS);
308   }
309   //
310   // 3 Fill map Solids/FN for myResult: aMSF
311   aNbUN=aMFS.Extent();
312   for (i=1; i<=aNbUN; ++i) {
313     const TopoDS_Shape& aFN=aMFS.FindKey(i);
314     const TopTools_ListOfShape& aLS=aMFS(i);
315     aItLS.Initialize(aLS);
316     for (; aItLS.More(); aItLS.Next()) {
317       const TopoDS_Shape& aS=aItLS.Value();
318       if (aMSF.Contains(aS)) {
319         TopTools_ListOfShape& aLF=aMSF.ChangeFromKey(aS);
320         aLF.Append(aFN);
321       }
322       else {
323         TopTools_ListOfShape aLF;
324         aLF.Append(aFN);
325         aMSF.Add(aS, aLF); 
326       }
327     }
328   }
329   //
330   // 4 Sort indices of aMSF
331   aNbS=aMSF.Extent();
332   if (aNbS<2) {
333     // wrong number of solids that have shared face 
334     myWarningStatus=5;
335   }
336   //
337   pIx=new GEOMAlgo_CoupleOfInteger[aNbS];
338   //
339   for (i=1; i<=aNbS; ++i) {
340     const TopTools_ListOfShape& aLF=aMSF(i);
341     aNbF=aLF.Extent();
342     pIx[i-1].SetValues(aNbF, i);
343   }
344   SortShell(aNbS, pIx);
345   //
346   // 5 Refine solids
347   //
348   TopTools_DataMapOfShapeShape aMFNFN2, aMFNFD;
349   TopTools_DataMapIteratorOfDataMapOfShapeShape aItMSS;
350   TopTools_MapOfShape aMFNP;
351   TopTools_IndexedMapOfShape aMFD;
352   //
353   for (iX=aNbS-1; iX>=0; --iX) {
354     i=pIx[iX].Value2();
355     // solid from myResult aSN
356     const TopoDS_Shape& aSN=aMSF.FindKey(i);
357     //
358     // candidates to be faces to replace for aSN 
359     const TopTools_ListOfShape& aLFN=aMSF(i);
360     aNbF=aLFN.Extent();
361     // 
362     // original solid for aSN -> aSD
363     const TopTools_ListOfShape& aLSD=myImages.Find(aSN);
364     const TopoDS_Shape& aSD=aLSD.First();
365     //
366     // faces of original solid -> aMFD
367     aMFD.Clear();
368     TopExp::MapShapes(aSD, TopAbs_FACE, aMFD);
369     //
370     // faces to replace for aSN [FN]/FD -> aMFNFD
371     aMFNFD.Clear();
372     aItLS.Initialize(aLFN);
373     for (; aItLS.More(); aItLS.Next()) {
374       const TopoDS_Shape& aFN=aItLS.Value();
375       if (!aMFNP.Add(aFN)) {
376         continue;
377       }
378       // 
379       // original face from original solid -> FD  
380       TopoDS_Shape aFD;
381       //
382       bFound=Standard_False;
383       const TopTools_ListOfShape& aLFD=myImages.Find(aFN);
384       aItLS1.Initialize(aLFD);
385       for (; aItLS1.More(); aItLS1.Next()) {
386         const TopoDS_Shape& aFDx=aItLS1.Value();
387         if (aMFD.Contains(aFDx)) {
388           aFD=aFDx;
389           bFound=Standard_True;
390           break;
391         }
392       }
393       //if (!bFound) {...}
394       aMFNFD.Bind(aFN, aFD);
395     } // for (; aItLS.More(); aItLS.Next()) {
396     //
397     aNbF=aMFNFD.Extent();
398     if (!aNbF) {
399       // nothing to do here
400       continue;
401     }
402     // update solid SN (and its shells)
403     RefineSolid(aSN, aMFNFD, aMFNFN2);
404     //
405     // update myOrigins / myImages
406     aItMSS.Initialize(aMFNFD);
407     for (; aItMSS.More(); aItMSS.Next()) {
408       const TopoDS_Shape& aFN=aItMSS.Key();      // face removed from aSN
409       const TopoDS_Shape& aFD=aItMSS.Value();    // old face from aSD
410       const TopoDS_Shape& aFN2=aMFNFN2.Find(aFN);// face added to aSN 
411       //
412       // myOrigins
413       myOrigins.ChangeFind(aFD)=aFN2;
414       //
415       // myImages
416       TopTools_ListOfShape aLFDx;
417       //
418       TopTools_ListOfShape& aLFD=myImages.ChangeFind(aFN);
419       aItLS.Initialize(aLFD);
420       for (; aItLS.More(); aItLS.Next()) {
421         const TopoDS_Shape& aFDx=aItLS.Value();
422         if (!aFDx.IsSame(aFD)) {
423           aLFDx.Append(aFDx);
424         }
425       }
426       aLFD=aLFDx;
427       //
428       aLFDx.Clear();
429       aLFDx.Append(aFD);
430       myImages.Bind(aFN2, aLFDx);
431     } // for (; aItMSS.More(); aItMSS.Next()) {
432   } // for (iX=aNbS-1; iX>=0; --iX) {
433   //
434   delete [] pIx;
435 }
436 //=======================================================================
437 // function: RefineSolid
438 // purpose : replace faces (aMFN) of solid aSd by new ones 
439 //=======================================================================
440 void RefineSolid(const TopoDS_Shape& aSd,
441                  const TopTools_DataMapOfShapeShape& aMFNFD,
442                  TopTools_DataMapOfShapeShape& aMFNFN2)
443 {
444   TopoDS_Shape *pSh;
445   TopoDS_Face aF2;
446   TopoDS_Iterator aItSd, aItSh;
447   BRep_Builder aBB;
448   TopTools_ListOfShape aLF;
449   TopTools_ListIteratorOfListOfShape aItLF;
450   //
451   aItSd.Initialize(aSd);
452   for (; aItSd.More(); aItSd.Next()) {
453     const TopoDS_Shape& aSh=aItSd.Value();
454     pSh=(TopoDS_Shape *)&aSh;
455     pSh->Free(Standard_True);
456     aLF.Clear();
457     aItSh.Initialize(*pSh);
458     for (; aItSh.More(); aItSh.Next()) {
459       const TopoDS_Shape& aF=aItSh.Value();
460       if (aMFNFD.IsBound(aF)) {
461         aLF.Append(aF);
462       }
463     }
464     //
465     aItLF.Initialize(aLF);
466     for (; aItLF.More(); aItLF.Next()) {
467       const TopoDS_Face& aF=TopoDS::Face(aItLF.Value());
468       //
469       MakeFaceToReplace(aF, aF2);
470       //
471       aMFNFN2.Bind(aF, aF2);
472       aBB.Remove(*pSh, aF);
473       aBB.Add(*pSh, aF2);
474     }
475     pSh->Free(Standard_False);
476   }
477 }
478 //=======================================================================
479 //function : MakeFaceToReplace
480 //purpose  : 
481 //=======================================================================
482 void MakeFaceToReplace(const TopoDS_Face& aF,
483                        TopoDS_Face& aFR)
484 {
485   Standard_Real aTol;
486   Handle(Geom_Surface) aS;
487   TopLoc_Location aLoc;
488   TopoDS_Face aFFWD, aFnew;
489   TopoDS_Iterator aItF;
490   BRep_Builder aBB;
491   //
492   aFFWD=aF;
493   aFFWD.Orientation(TopAbs_FORWARD);
494   aS=BRep_Tool::Surface(aFFWD, aLoc);
495   aTol=BRep_Tool::Tolerance(aFFWD);
496   //
497   aBB.MakeFace (aFnew, aS, aLoc, aTol);
498   aItF.Initialize(aFFWD);
499   for (; aItF.More(); aItF.Next()) {
500     const TopoDS_Shape& aW=aItF.Value();
501     aBB.Add(aFnew, aW);
502   }
503   aFnew.Orientation(aF.Orientation());
504   aFR=aFnew;
505 }
506 //=======================================================================
507 // function: SortShell
508 // purpose : 
509 //=======================================================================
510 void SortShell(const Standard_Integer n, 
511                GEOMAlgo_CoupleOfInteger* a) 
512 {
513   Standard_Integer nd, i, j, l, d=1;
514   GEOMAlgo_CoupleOfInteger x;
515   //
516   while(d<=n) {
517     d*=2;
518   }
519   //
520   while (d) {
521     d=(d-1)/2;
522     //
523     nd=n-d;
524     for (i=0; i<nd; ++i) {
525       j=i;
526     m30:;
527       l=j+d;
528       if (a[l].Value1() < a[j].Value1()) {
529         x=a[j];
530         a[j]=a[l];
531         a[l]=x;
532         j-=d;
533         if (j > -1) { 
534           goto m30;
535         }
536       }//if (a[l] < a[j]){
537     }//for (i=0; i<nd; ++i) 
538   }//while (1)
539 }
540 //
541 // ErrorStatus
542 //
543 // 200; - result shape is Null