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