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