Salome HOME
30b69f3f02f5c69724f686f7048697776e7d7133
[modules/geom.git] / NMTTools_PaveFiller_7.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:        NMTTools_PaveFiller_7.cxx
21 // Created:     Thu Dec 18 15:14:55 2003
22 // Author:      Peter KURNEV
23 //              <pkv@irinox>
24
25
26 #include <NMTTools_PaveFiller.ixx>
27
28 #include <TopoDS_Vertex.hxx>
29 #include <TopoDS_Edge.hxx>
30 #include <TopoDS.hxx>
31
32 #include <NMTDS_ShapesDataStructure.hxx>
33 #include <TopAbs_Orientation.hxx>
34 #include <BOPTools_ListOfPaveBlock.hxx>
35 #include <BOPTools_ListIteratorOfListOfPaveBlock.hxx>
36 #include <BOPTools_PaveBlock.hxx>
37 #include <BOPTools_Pave.hxx>
38 #include <BOPTools_Tools.hxx>
39 #include <BooleanOperations_AncestorsSeqAndSuccessorsSeq.hxx>
40 #include <BRep_Tool.hxx>
41 #include <NMTTools_ListIteratorOfListOfCommonBlock.hxx>
42 #include <BOPTools_SSInterference.hxx>
43 #include <BOPTools_CArray1OfSSInterference.hxx>
44 #include <TopExp_Explorer.hxx>
45 #include <TopoDS_Shape.hxx>
46 #include <TopExp.hxx>
47 #include <TColStd_IndexedMapOfInteger.hxx>
48
49 //
50 #include <IntTools_SequenceOfPntOn2Faces.hxx>
51 #include <IntTools_PntOnFace.hxx>
52 #include <IntTools_PntOn2Faces.hxx>
53 #include <BOPTools_Tools.hxx>
54 #include <TopTools_DataMapOfShapeListOfInteger.hxx>
55 #include <TColStd_ListOfInteger.hxx>
56 #include <TopoDS_Compound.hxx>
57 #include <BRep_Builder.hxx>
58 #include <BOPTools_CArray1OfVVInterference.hxx>
59 #include <BOPTools_VVInterference.hxx>
60 #include <TopTools_DataMapOfShapeShape.hxx>
61 #include <TopTools_DataMapOfShapeListOfInteger.hxx>
62 #include <TopTools_DataMapIteratorOfDataMapOfShapeListOfInteger.hxx>
63 #include <TColStd_MapOfInteger.hxx>
64 #include <TColStd_ListIteratorOfListOfInteger.hxx>
65 #include <TopTools_DataMapOfIntegerShape.hxx>
66 #include <Bnd_HArray1OfBox.hxx>
67 #include <Bnd_BoundSortBox.hxx>
68 #include <Bnd_Box.hxx>
69 #include <BRepBndLib.hxx>
70 #include <TopTools_DataMapIteratorOfDataMapOfIntegerShape.hxx>
71 #include <TopTools_DataMapOfShapeInteger.hxx>
72 #include <TopTools_DataMapIteratorOfDataMapOfShapeInteger.hxx>
73 #include <TopTools_DataMapOfShapeInteger.hxx>
74 #include <BooleanOperations_AncestorsSeqAndSuccessorsSeq.hxx>
75
76 // Modified  Thu Sep 14 14:35:18 2006 
77 // Contribution of Samtech www.samcef.com BEGIN
78 static 
79   void FuseVertices(const TopoDS_Shape& aCompound,
80                     TopTools_DataMapOfShapeShape& aDMVV);
81 // Contribution of Samtech www.samcef.com END
82
83 //=======================================================================
84 // function: MakeSplitEdges
85 // purpose: 
86 //=======================================================================
87   void NMTTools_PaveFiller::MakeSplitEdges()
88 {
89   myIsDone=Standard_False;
90   //
91   Standard_Boolean bIsNewVertex1, bIsNewVertex2;
92   Standard_Integer i, aNbS, nV1, nV2, aNbPaveBlocks, aNewShapeIndex;
93   Standard_Real    t1, t2;
94   TopAbs_Orientation anOri;
95   TopoDS_Edge aE, aESplit;
96   TopoDS_Vertex aV1, aV2;
97   //
98   aNbS=myDS->NumberOfShapesOfTheObject();
99   for (i=1; i<=aNbS; ++i) {
100     if (myDS->GetShapeType(i) != TopAbs_EDGE)
101       continue;
102     //
103     // Original Edge
104     aE=TopoDS::Edge(myDS->Shape(i));
105     if (BRep_Tool::Degenerated(aE)){
106       continue;
107     }
108     //
109     anOri=aE.Orientation(); 
110     aE.Orientation(TopAbs_FORWARD);
111     //
112     // Making Split Edges
113     //
114     // Split Set for the Original Edge i
115     BOPTools_ListOfPaveBlock& aSplitEdges=mySplitShapesPool(myDS->RefEdge(i));
116     BOPTools_ListIteratorOfListOfPaveBlock aPBIt(aSplitEdges);
117     //
118     aNbPaveBlocks=aSplitEdges.Extent();
119   
120     for (; aPBIt.More(); aPBIt.Next()) {
121       BOPTools_PaveBlock& aPB=aPBIt.Value();
122       // aPave1
123       const BOPTools_Pave& aPave1=aPB.Pave1();
124       nV1=aPave1.Index();
125       t1=aPave1.Param();
126       aV1=TopoDS::Vertex(myDS->GetShape(nV1));
127       aV1.Orientation(TopAbs_FORWARD);
128       // aPave2
129       const BOPTools_Pave& aPave2=aPB.Pave2();
130       nV2=aPave2.Index();
131       t2=aPave2.Param();
132       aV2=TopoDS::Vertex(myDS->GetShape(nV2));
133       aV2.Orientation(TopAbs_REVERSED);
134       //xx
135       if (aNbPaveBlocks==1) {
136         bIsNewVertex1=myDS->IsNewShape (nV1);
137         bIsNewVertex2=myDS->IsNewShape (nV2);
138         if (!bIsNewVertex1 && !bIsNewVertex2) {
139           aPB.SetEdge(i);
140           continue;
141         }
142       }
143       //xx
144       BOPTools_Tools::MakeSplitEdge(aE, aV1, t1, aV2, t2, aESplit);  
145       //
146       // Add Split Part of the Original Edge to the DS
147       BooleanOperations_AncestorsSeqAndSuccessorsSeq anASSeq;
148
149       anASSeq.SetNewSuccessor(nV1);
150       anASSeq.SetNewOrientation(aV1.Orientation());
151
152       anASSeq.SetNewSuccessor(nV2);
153       anASSeq.SetNewOrientation(aV2.Orientation());
154       //
155       if (anOri==TopAbs_INTERNAL) {
156         anASSeq.SetNewAncestor(i);
157         aESplit.Orientation(anOri);
158       }
159       //
160       myDS->InsertShapeAndAncestorsSuccessors(aESplit, anASSeq);
161       aNewShapeIndex=myDS->NumberOfInsertedShapes();
162       myDS->SetState(aNewShapeIndex, BooleanOperations_UNKNOWN);
163       //
164       // Fill Split Set for the Original Edge
165       aPB.SetEdge(aNewShapeIndex);
166       //
167     }
168   } 
169   myIsDone=Standard_True;
170 }
171 //=======================================================================
172 // function: UpdateCommonBlocks
173 // purpose: 
174 //=======================================================================
175   void NMTTools_PaveFiller::UpdateCommonBlocks()
176 {
177   myIsDone=Standard_False;
178   //
179   Standard_Integer nE, aNbS,  nSp, nEx, nSpx;
180   NMTTools_ListIteratorOfListOfCommonBlock aCBIt;
181   BOPTools_ListIteratorOfListOfPaveBlock aPBIt;
182   //
183   aNbS=myDS->NumberOfShapesOfTheObject();
184   //
185   for (nE=1; nE<=aNbS; ++nE) {
186     if (myDS->GetShapeType(nE)!=TopAbs_EDGE){
187       continue;
188     }
189     if (BRep_Tool::Degenerated(TopoDS::Edge(myDS->Shape(nE)))){
190       continue;
191     }
192     //
193     NMTTools_ListOfCommonBlock& aLCB=myCommonBlockPool(myDS->RefEdge(nE));
194     BOPTools_ListOfPaveBlock& aLPB=mySplitShapesPool  (myDS->RefEdge(nE));
195     //
196     aCBIt.Initialize(aLCB);
197     for (; aCBIt.More(); aCBIt.Next()) {
198       NMTTools_CommonBlock& aCB=aCBIt.Value();
199       //
200       //modified by NIZNHY-PKV Wed Nov  8 15:59:46 2006f
201       // Among all PBs of aCB the first PB will be one
202       // that have max tolerance value 
203       {
204         Standard_Real aTolEx, aTolExMax;
205         BOPTools_ListOfPaveBlock *pLPB, aLPBx;
206         //
207         aTolExMax=-1.;
208         pLPB=(BOPTools_ListOfPaveBlock *)&aCB.PaveBlocks();
209         aPBIt.Initialize(*pLPB);
210         for (; aPBIt.More(); aPBIt.Next()) {
211           const BOPTools_PaveBlock& aPBx=aPBIt.Value();
212           nEx=aPBx.OriginalEdge();
213           const TopoDS_Edge& aEx=TopoDS::Edge(myDS->Shape(nEx));
214           aTolEx=BRep_Tool::Tolerance(aEx);
215           if (aTolEx>aTolExMax) {
216             aTolExMax=aTolEx;
217             aLPBx.Prepend(aPBx);
218           }
219           else{
220             aLPBx.Append(aPBx);
221           }
222         }
223         //
224         pLPB->Clear();
225         *pLPB=aLPBx;
226       }
227       //modified by NIZNHY-PKV Wed Nov  8 15:59:50 2006t
228       //
229       BOPTools_PaveBlock& aPB=aCB.PaveBlock1(nE);
230       nSp=SplitIndex(aPB);
231       aPB.SetEdge(nSp);
232       //
233       const BOPTools_ListOfPaveBlock& aCBLPB=aCB.PaveBlocks();
234       aPBIt.Initialize(aCBLPB);
235       for (; aPBIt.More(); aPBIt.Next()) {
236         BOPTools_PaveBlock& aPBx=aPBIt.Value();
237         nEx=aPBx.OriginalEdge();
238         if (nEx==nE) {
239           continue;
240         }
241         //
242         nSpx=SplitIndex(aPBx);
243         aPBx.SetEdge(nSpx);
244       }
245       //
246     }
247   }
248 }
249 //=======================================================================
250 // function: SplitIndex
251 // purpose: 
252 //=======================================================================
253   Standard_Integer NMTTools_PaveFiller::SplitIndex(const BOPTools_PaveBlock& aPBx)const 
254 {
255   Standard_Integer anOriginalEdge, anEdgeIndex=0;
256
257   anOriginalEdge=aPBx.OriginalEdge();
258
259   const BOPTools_ListOfPaveBlock& aLPB=mySplitShapesPool(myDS->RefEdge(anOriginalEdge));
260   //
261   BOPTools_ListIteratorOfListOfPaveBlock anIt(aLPB);
262   for (; anIt.More(); anIt.Next()) {
263     BOPTools_PaveBlock& aPB=anIt.Value();
264     if (aPB.IsEqual(aPBx)) {
265       anEdgeIndex=aPB.Edge();
266       return anEdgeIndex;
267     }
268   }
269   return anEdgeIndex;
270
271 //=======================================================================
272 // function: UpdatePaveBlocks
273 // purpose: 
274 //=======================================================================
275   void NMTTools_PaveFiller::UpdatePaveBlocks()
276 {
277   myIsDone=Standard_False;
278   //
279   
280   Standard_Integer i, aNbFFs, nF1, nF2, aNbF, nF, iRankF, nE, nV1, nV2, aNbPB;
281   Standard_Real aT1, aT2;
282   TColStd_IndexedMapOfInteger aMF, aME;
283   TopExp_Explorer aExp;
284   TopoDS_Vertex aV1, aV2;
285   TopoDS_Edge aE;
286   BOPTools_Pave aPave1, aPave2;
287   BOPTools_PaveBlock aPB;
288   //
289   BOPTools_CArray1OfSSInterference& aFFs=myIntrPool->SSInterferences();
290   //
291   aNbFFs=aFFs.Extent();
292   for (i=1; i<=aNbFFs; ++i) {
293     BOPTools_SSInterference& aFFi=aFFs(i);
294     aFFi.Indices(nF1, nF2);
295     aMF.Add(nF1);
296     aMF.Add(nF2);
297   }
298   //
299   aNbF=aMF.Extent();
300   for(i=1; i<=aNbF; ++i) {
301     nF=aMF(i);
302     iRankF=myDS->Rank(nF);
303     const TopoDS_Shape aF=myDS->Shape(nF);//mpv
304     aExp.Init(aF, TopAbs_EDGE);
305     for(; aExp.More();  aExp.Next()) {
306       aE=TopoDS::Edge(aExp.Current());
307       //
308       if (BRep_Tool::Degenerated(aE)) {
309         continue;
310       }
311       //
312       nE=myDS->ShapeIndex(aE, iRankF);
313       //
314       if (aME.Contains(nE)) {
315         continue;
316       }
317       aME.Add(nE);
318       //
319       BOPTools_ListOfPaveBlock& aLPB=mySplitShapesPool(myDS->RefEdge(nE));
320       aNbPB=aLPB.Extent();
321       if (aNbPB) {
322         continue;
323       }
324       TopExp::Vertices(aE, aV1, aV2);
325       //
326       nV1=myDS->ShapeIndex(aV1, iRankF);
327       aT1=BRep_Tool::Parameter(aV1, aE);
328       aPave1.SetIndex(nV1);
329       aPave1.SetParam(aT1);
330       //
331       nV2=myDS->ShapeIndex(aV2, iRankF);
332       aT2=BRep_Tool::Parameter(aV2, aE);
333       aPave2.SetIndex(nV2);
334       aPave2.SetParam(aT2);
335       //
336       aPB.SetEdge(nE);
337       aPB.SetOriginalEdge(nE);
338       aPB.SetPave1(aPave1);
339       aPB.SetPave2(aPave2);
340       //
341       aLPB.Append(aPB);
342     }
343   }
344
345 // Modified 
346 // to treat Alone Vertices between faces
347 // Thu Sep 14 14:35:18 2006 
348 // Contribution of Samtech www.samcef.com BEGIN
349 //=======================================================================
350 // function: MakeAloneVertices
351 // purpose: 
352 //=======================================================================
353   void NMTTools_PaveFiller::MakeAloneVertices()
354 {
355   Standard_Integer i, aNbFFs, nF1, nF2, j, aNbPnts, nFx, aNbV;
356   Standard_Real aTolF1, aTolF2, aTolSum, aTolV;
357   TColStd_ListIteratorOfListOfInteger aIt;
358   TColStd_ListOfInteger aLI;
359   TopoDS_Vertex aV;
360   TopoDS_Compound aCompound;
361   BRep_Builder aBB;
362   TopTools_DataMapOfShapeListOfInteger aDMVFF, aDMVFF1;
363   TopTools_DataMapIteratorOfDataMapOfShapeListOfInteger aItDMVFF;
364   TopTools_DataMapOfShapeShape aDMVV;
365   TopTools_DataMapOfIntegerShape aDMIV;
366   TopTools_DataMapOfShapeInteger aDMVI;
367   TopTools_DataMapIteratorOfDataMapOfShapeInteger aItDMVI;
368   TopTools_DataMapIteratorOfDataMapOfIntegerShape aItDMIV;
369   //
370   aBB.MakeCompound(aCompound);
371   //
372   myAloneVertices.Clear();
373   //
374   BOPTools_CArray1OfSSInterference& aFFs=myIntrPool->SSInterferences();
375   //
376   // 1. Collect alone vertices from FFs
377   aNbV=0;
378   aNbFFs=aFFs.Extent();
379   for (i=1; i<=aNbFFs; ++i) {
380     BOPTools_SSInterference& aFFi=aFFs(i);
381     aFFi.Indices(nF1, nF2);
382     //
383     const TopoDS_Face aF1=TopoDS::Face(myDS->Shape(nF1));//mpv
384     const TopoDS_Face aF2=TopoDS::Face(myDS->Shape(nF2));//mpv
385     //
386     aTolF1=BRep_Tool::Tolerance(aF1);
387     aTolF2=BRep_Tool::Tolerance(aF2);
388     aTolSum=aTolF1+aTolF2;
389     //
390     aLI.Clear();
391     aLI.Append(nF1);
392     aLI.Append(nF2);
393     //
394     const IntTools_SequenceOfPntOn2Faces& aSeqAlonePnts=aFFi.AlonePnts();
395     aNbPnts=aSeqAlonePnts.Length();
396     for (j=1; j<=aNbPnts; ++j) {
397       const gp_Pnt& aP=aSeqAlonePnts(j).P1().Pnt();
398       BOPTools_Tools::MakeNewVertex(aP, aTolSum, aV);
399       aDMVFF.Bind(aV, aLI);
400       aBB.Add(aCompound, aV);
401       ++aNbV;
402     }
403   }
404   if (!aNbV) {
405     return;
406   }
407   //
408   // 2. Try to fuse alone vertices themselves;
409   FuseVertices(aCompound, aDMVV);
410   //
411   // if some are fused, replace them by new ones 
412   aItDMVFF.Initialize(aDMVFF);
413   for (;  aItDMVFF.More(); aItDMVFF.Next()) {
414     const TopoDS_Shape& aVx=aItDMVFF.Key();
415     const TColStd_ListOfInteger& aLIx=aItDMVFF.Value();
416     //
417     if (!aDMVV.IsBound(aVx)) {
418       aDMVFF1.Bind(aVx, aLIx);
419     }
420     else {
421       const TopoDS_Shape& aVy=aDMVV.Find(aVx);
422       
423       if (aDMVFF1.IsBound(aVy)) {
424         TColStd_ListOfInteger& aLIy=aDMVFF1.ChangeFind(aVy);
425         aIt.Initialize(aLIx);
426         for(; aIt.More(); aIt.Next()) {
427           nFx=aIt.Value();
428           aLIy.Append(nFx);
429         }
430       }
431       else { 
432         aDMVFF1.Bind(aVy, aLIx);
433       }
434     }
435   }
436   aDMVFF.Clear();
437   //
438   // refine lists of faces in aDMVFF1; 
439   aItDMVFF.Initialize(aDMVFF1);
440   for (;  aItDMVFF.More(); aItDMVFF.Next()) {
441     TColStd_MapOfInteger aMIy;
442     TColStd_ListOfInteger aLIy;
443     //
444     const TopoDS_Shape& aVx=aItDMVFF.Key();
445     TColStd_ListOfInteger& aLIx=aDMVFF1.ChangeFind(aVx);
446     aIt.Initialize(aLIx);
447     for(; aIt.More(); aIt.Next()) {
448       nFx=aIt.Value();
449       if (aMIy.Add(nFx)) {
450         aLIy.Append(nFx);
451       }
452     }
453     aLIx.Clear();
454     aLIx.Append(aLIy);
455   }
456   //==================================
457   //
458   // 3. Collect vertices from DS
459   Standard_Integer aNbS, nV, nVSD, aNbVDS, i1, i2, aNbVSD;
460   //
461   aNbS=myDS->NumberOfShapesOfTheObject();
462   // old shapes
463   for (i=1; i<=aNbS; ++i) {
464     const TopoDS_Shape& aS=myDS->Shape(i);
465     if (aS.ShapeType() != TopAbs_VERTEX){
466       continue;
467     }
468     //
469     nVSD=FindSDVertex(i); 
470     nV=(nVSD) ? nVSD : i;
471     const TopoDS_Shape& aVx=myDS->Shape(nV);
472     if (!aDMVI.IsBound(aVx)) {
473       aDMVI.Bind(aVx, nV);
474     }
475   }
476   // new shapes
477   i1=myDS->NumberOfSourceShapes()+1;
478   i2=myDS->NumberOfInsertedShapes();
479   for (i=i1; i<=i2; ++i) {
480     const TopoDS_Shape aS=myDS->Shape(i);//mpv
481     if (aS.ShapeType() != TopAbs_VERTEX){
482       continue;
483     }
484     if (!aDMVI.IsBound(aS)) {
485       aDMVI.Bind(aS, i);
486     }
487   }
488   // 
489   // 4. Initialize BoundSortBox on aDMVI
490   //
491   Handle(Bnd_HArray1OfBox) aHAB;
492   Bnd_BoundSortBox aBSB;
493   //
494   aNbVDS=aDMVI.Extent();
495   aHAB=new Bnd_HArray1OfBox(1, aNbVDS);
496   //
497   aItDMVI.Initialize(aDMVI);
498   for (i=1; aItDMVI.More(); aItDMVI.Next(), ++i) {
499     Bnd_Box aBox;
500     //
501     nV=aItDMVI.Value();
502     aV=TopoDS::Vertex(aItDMVI.Key());
503     aTolV=BRep_Tool::Tolerance(aV);
504     aBox.SetGap(aTolV);
505     BRepBndLib::Add(aV, aBox);
506     aHAB->SetValue(i, aBox);
507     //
508     aDMIV.Bind(i, aV);
509   }
510   aBSB.Initialize(aHAB);
511   //
512   // 5. Compare 
513   aItDMVFF.Initialize(aDMVFF1);
514   for (;  aItDMVFF.More(); aItDMVFF.Next()) {
515     Bnd_Box aBoxV;
516     //
517     const TColStd_ListOfInteger& aLIFF=aItDMVFF.Value();
518     aV=TopoDS::Vertex(aItDMVFF.Key());
519     //
520     aTolV=BRep_Tool::Tolerance(aV);
521     aBoxV.SetGap(aTolV);
522     BRepBndLib::Add(aV, aBoxV);
523     //
524     const TColStd_ListOfInteger& aLIVSD=aBSB.Compare(aBoxV);
525     aNbVSD=aLIVSD.Extent();
526     if (aNbVSD==0) {
527       // add new vertex in DS and update map myAloneVertices
528       BooleanOperations_AncestorsSeqAndSuccessorsSeq anASSeq;
529       //
530       myDS->InsertShapeAndAncestorsSuccessors(aV, anASSeq);
531       nV=myDS->NumberOfInsertedShapes();
532       //
533       aIt.Initialize(aLIFF);
534       for (; aIt.More(); aIt.Next()) {
535         nFx=aIt.Value();
536         if (myAloneVertices.Contains(nFx)) {
537           TColStd_IndexedMapOfInteger& aMVx=myAloneVertices.ChangeFromKey(nFx);
538           aMVx.Add(nV);
539         }
540         else {
541           TColStd_IndexedMapOfInteger aMVx;
542           aMVx.Add(nV);
543           myAloneVertices.Add(nFx, aMVx);
544         }
545       }
546     }
547   }
548 }
549 //=======================================================================
550 // function: AloneVertices
551 // purpose: 
552 //=======================================================================
553   const NMTTools_IndexedDataMapOfIndexedMapOfInteger& NMTTools_PaveFiller::AloneVertices()const
554 {
555   return myAloneVertices;
556 }
557 //=======================================================================
558 // function: FuseVertices
559 // purpose: 
560 //=======================================================================
561 void FuseVertices(const TopoDS_Shape& aCompound,
562                   TopTools_DataMapOfShapeShape& aDMVV)
563 {
564   Standard_Integer i, aNbVV, n1, n2, nX;
565   NMTDS_ShapesDataStructure tDS;
566   //
567   tDS.SetCompositeShape(aCompound);
568   tDS.Init();
569   //
570   BOPTools_InterferencePool tInterfPool(tDS);
571   NMTTools_PaveFiller tPaveFiller(tInterfPool);
572   //
573   tPaveFiller.Init();
574   //
575   tPaveFiller.PerformVV();
576   tPaveFiller.PerformNewVertices();
577   //
578   const BOPTools_CArray1OfVVInterference& aVVt=tInterfPool.VVInterfs();
579   //
580   aNbVV=aVVt.Extent();
581   for (i=1; i<=aNbVV; ++i) {
582     const BOPTools_VVInterference& aVV=aVVt(i);
583     aVV.Indices(n1, n2);
584     nX=aVV.NewShape();
585     if (nX) {
586       const TopoDS_Shape& aV1=tDS.Shape(n1);
587       const TopoDS_Shape& aV2=tDS.Shape(n2);
588       const TopoDS_Shape& aVx=tDS.Shape(nX);
589       aDMVV.Bind(aV1, aVx);
590       aDMVV.Bind(aV2, aVx);
591     }
592   }
593 }
594 // Contribution of Samtech www.samcef.com END