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