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