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