0032768: Coding - get rid of unused headers [BopAlgo to BRepBuilderAPI]
[occt.git] / src / BOPAlgo / BOPAlgo_PaveFiller_2.cxx
1 // Created by: Peter KURNEV
2 // Copyright (c) 2010-2014 OPEN CASCADE SAS
3 // Copyright (c) 2007-2010 CEA/DEN, EDF R&D, OPEN CASCADE
4 // Copyright (c) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, CEDRAT,
5 //                         EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 //
7 // This file is part of Open CASCADE Technology software library.
8 //
9 // This library is free software; you can redistribute it and/or modify it under
10 // the terms of the GNU Lesser General Public License version 2.1 as published
11 // by the Free Software Foundation, with special exception defined in the file
12 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
13 // distribution for complete text of the license and disclaimer of any warranty.
14 //
15 // Alternatively, this file may be used under the terms of Open CASCADE
16 // commercial license or contractual agreement.
17
18
19 #include <BOPAlgo_PaveFiller.hxx>
20 #include <BOPAlgo_Alerts.hxx>
21 #include <BOPAlgo_Tools.hxx>
22 #include <BOPDS_DS.hxx>
23 #include <BOPDS_Interf.hxx>
24 #include <BOPDS_Iterator.hxx>
25 #include <BOPDS_Pair.hxx>
26 #include <BOPDS_PaveBlock.hxx>
27 #include <BOPDS_VectorOfInterfVE.hxx>
28 #include <BOPTools_AlgoTools.hxx>
29 #include <BOPTools_Parallel.hxx>
30 #include <BRep_Builder.hxx>
31 #include <BRep_Tool.hxx>
32 #include <gp_Pnt.hxx>
33 #include <IntTools_Context.hxx>
34 #include <NCollection_Vector.hxx>
35 #include <TopoDS.hxx>
36 #include <TopoDS_Edge.hxx>
37 #include <TopoDS_Vertex.hxx>
38
39 //=======================================================================
40 //class    : BOPAlgo_VertexEdge
41 //purpose  : 
42 //=======================================================================
43 class BOPAlgo_VertexEdge : public BOPAlgo_ParallelAlgo {
44
45  public:
46   DEFINE_STANDARD_ALLOC
47
48   BOPAlgo_VertexEdge() : 
49     BOPAlgo_ParallelAlgo(),
50     myIV(-1), myIE(-1), myFlag(-1), myT(-1.), myTolVNew(-1.) {
51   };
52   //
53   virtual ~BOPAlgo_VertexEdge(){
54   };
55   //
56   void SetIndices(const Standard_Integer nV,
57                   const Standard_Integer nE) {
58     myIV=nV;
59     myIE=nE;
60   }
61   //
62   void Indices(Standard_Integer& nV,
63                Standard_Integer& nE) const {
64     nV=myIV;
65     nE=myIE;
66   }
67   //
68   void SetVertex(const TopoDS_Vertex& aV) {
69     myV=aV;
70   }
71   //
72   void SetEdge(const TopoDS_Edge& aE) {
73     myE=aE;
74   }
75   //
76   const TopoDS_Vertex& Vertex() const {
77     return myV;
78   }
79   //
80   const TopoDS_Edge& Edge() const {
81     return myE;
82   }
83   //
84   Standard_Integer Flag()const {
85     return myFlag;
86   }
87   //
88   Standard_Real Parameter()const {
89     return myT;
90   }
91   //
92   Standard_Real VertexNewTolerance()const {
93     return myTolVNew;
94   }
95   //
96   void SetContext(const Handle(IntTools_Context)& aContext) {
97     myContext=aContext;
98   }
99   //
100   const Handle(IntTools_Context)& Context()const {
101     return myContext;
102   }
103   //
104   void SetPaveBlock(const Handle(BOPDS_PaveBlock)& thePB) {
105     myPB = thePB;
106   }
107   //
108   const Handle(BOPDS_PaveBlock)& PaveBlock() const {
109     return myPB;
110   }
111   //
112   virtual void Perform() {
113     Message_ProgressScope aPS(myProgressRange, NULL, 1);
114     if (UserBreak(aPS))
115     {
116       return;
117     }
118     try
119     {
120       OCC_CATCH_SIGNALS
121
122       myFlag=myContext->ComputeVE (myV, myE, myT, myTolVNew, myFuzzyValue);
123     }
124     catch (Standard_Failure const&)
125     {
126       AddError(new BOPAlgo_AlertIntersectionFailed);
127     }
128   };
129   //
130  protected:
131   Standard_Integer myIV;
132   Standard_Integer myIE;
133   Standard_Integer myFlag;
134   Standard_Real myT;
135   Standard_Real myTolVNew;
136   TopoDS_Vertex myV;
137   TopoDS_Edge myE;
138   Handle(IntTools_Context) myContext;
139   Handle(BOPDS_PaveBlock) myPB;
140 };
141 //=======================================================================
142 typedef NCollection_Vector<BOPAlgo_VertexEdge> BOPAlgo_VectorOfVertexEdge;
143
144 //=======================================================================
145 // function: PerformVE
146 // purpose: 
147 //=======================================================================
148 void BOPAlgo_PaveFiller::PerformVE(const Message_ProgressRange& theRange)
149 {
150   FillShrunkData(TopAbs_VERTEX, TopAbs_EDGE);
151   //
152   myIterator->Initialize(TopAbs_VERTEX, TopAbs_EDGE);
153   Message_ProgressScope aPS(theRange, NULL, 1);
154
155   Standard_Integer iSize = myIterator->ExpectedLength();
156   if (!iSize) {
157     return; 
158   }
159   //
160   // Prepare pairs for intersection
161   BOPDS_IndexedDataMapOfPaveBlockListOfInteger aMVEPairs;
162   for (; myIterator->More(); myIterator->Next()) {
163     if (UserBreak(aPS))
164     {
165       return;
166     }
167     Standard_Integer nV, nE;
168     myIterator->Value(nV, nE);
169     //
170     const BOPDS_ShapeInfo& aSIE=myDS->ShapeInfo(nE);
171     if (aSIE.HasSubShape(nV)) {
172       continue;
173     }
174     //
175     if (aSIE.HasFlag()){
176       continue;
177     }
178     //
179     if (myDS->HasInterf(nV, nE)) {
180       continue;
181     }
182     //
183     if (myDS->HasInterfShapeSubShapes(nV, nE)) {
184       continue;
185     }
186     //
187     const BOPDS_ListOfPaveBlock& aLPB = myDS->PaveBlocks(nE);
188     if (aLPB.IsEmpty()) {
189       continue;
190     }
191     //
192     const Handle(BOPDS_PaveBlock)& aPB = aLPB.First();
193     if (!aPB->IsSplittable()) {
194       // this is a micro edge, ignore it
195       continue;
196     }
197     //
198     TColStd_ListOfInteger* pLV = aMVEPairs.ChangeSeek(aPB);
199     if (!pLV)
200       pLV = &aMVEPairs(aMVEPairs.Add(aPB, TColStd_ListOfInteger()));
201     pLV->Append(nV);
202   }
203   //
204   IntersectVE(aMVEPairs, aPS.Next());
205 }
206
207 //=======================================================================
208 // function: IntersectVE
209 // purpose: 
210 //=======================================================================
211 void BOPAlgo_PaveFiller::IntersectVE
212   (const BOPDS_IndexedDataMapOfPaveBlockListOfInteger& theVEPairs,
213    const Message_ProgressRange& theRange,
214    const Standard_Boolean theAddInterfs)
215 {
216   Standard_Integer i, aNbVE = theVEPairs.Extent();
217   if (!aNbVE) {
218     return;
219   }
220   //
221   BOPDS_VectorOfInterfVE& aVEs = myDS->InterfVE();
222   if (theAddInterfs) {
223     aVEs.SetIncrement(aNbVE);
224   }
225   //
226   // Prepare for intersection.
227   BOPAlgo_VectorOfVertexEdge aVVE;
228   // Map to collect all SD connections to add interferences
229   // for all vertices having the same SD vertex.
230   // It will also be used as a Fence map to avoid repeated
231   // intersection of the same SD vertex with edge
232   NCollection_DataMap<BOPDS_Pair, TColStd_ListOfInteger, BOPDS_PairMapHasher> aDMVSD;
233   //
234   Message_ProgressScope aPSOuter(theRange, NULL, 10);
235   for (i = 1; i <= aNbVE; ++i) {
236     if (UserBreak(aPSOuter))
237     {
238       return;
239     }
240     const Handle(BOPDS_PaveBlock)& aPB = theVEPairs.FindKey(i);
241     Standard_Integer nE = aPB->OriginalEdge();
242     //
243     TColStd_MapOfInteger aMVPB;
244     const BOPDS_ListOfPaveBlock& aLPB = myDS->PaveBlocks (nE);
245     for (BOPDS_ListOfPaveBlock::Iterator itPB (aLPB); itPB.More(); itPB.Next())
246     {
247       aMVPB.Add (itPB.Value()->Pave1().Index());
248       aMVPB.Add (itPB.Value()->Pave2().Index());
249     }
250
251     const TColStd_ListOfInteger& aLV = theVEPairs(i);
252     TColStd_ListIteratorOfListOfInteger aItLV(aLV);
253     for (; aItLV.More(); aItLV.Next()) {
254       Standard_Integer nV = aItLV.Value();
255       //
256       Standard_Integer nVSD = nV;
257       myDS->HasShapeSD(nV, nVSD);
258       //
259       if (aMVPB.Contains (nVSD))
260         continue;
261
262       BOPDS_Pair aPair(nVSD, nE);
263       TColStd_ListOfInteger* pLI = aDMVSD.ChangeSeek(aPair);
264       if (pLI) {
265         // Already added
266         pLI->Append(nV);
267         continue;
268       }
269       // New pair
270       pLI = aDMVSD.Bound(aPair, TColStd_ListOfInteger());
271       pLI->Append(nV);
272       //
273       const TopoDS_Vertex& aV = TopoDS::Vertex(myDS->Shape(nVSD));
274       const TopoDS_Edge& aE = TopoDS::Edge(myDS->Shape(nE));
275       //
276       BOPAlgo_VertexEdge& aVESolver = aVVE.Appended();
277       aVESolver.SetIndices(nVSD, nE);
278       aVESolver.SetVertex(aV);
279       aVESolver.SetEdge(aE);
280       aVESolver.SetPaveBlock(aPB);
281       aVESolver.SetFuzzyValue(myFuzzyValue);
282     }
283   }
284   //
285   aNbVE = aVVE.Length();
286
287   Message_ProgressScope aPS(aPSOuter.Next(9), "Performing Vertex-Edge intersection", aNbVE);
288   for (i = 0; i < aNbVE; i++)
289   {
290     BOPAlgo_VertexEdge& aVESolver = aVVE.ChangeValue(i);
291     aVESolver.SetProgressRange(aPS.Next());
292   }
293   // Perform intersection
294   //=============================================================
295   BOPTools_Parallel::Perform (myRunParallel, aVVE, myContext);
296   //=============================================================
297   if (UserBreak(aPSOuter))
298   {
299     return;
300   }
301   //
302   // Keep the modified edges for further update
303   TColStd_MapOfInteger aMEdges;
304   //
305   // Analyze intersections
306   for (i = 0; i < aNbVE; ++i) {
307     if (UserBreak(aPSOuter))
308     {
309       return;
310     }
311     const BOPAlgo_VertexEdge& aVESolver = aVVE(i);
312     if (aVESolver.Flag() != 0) {
313       if (aVESolver.HasErrors())
314       {
315         // Warn about failed intersection of sub-shapes
316         AddIntersectionFailedWarning(aVESolver.Vertex(), aVESolver.Edge());
317       }
318       continue;
319     }
320     //
321     Standard_Integer nV, nE;
322     aVESolver.Indices(nV, nE);
323     // Parameter of vertex on edge
324     Standard_Real aT = aVESolver.Parameter();
325     // 1. Update vertex V/E if necessary
326     Standard_Real aTolVNew = aVESolver.VertexNewTolerance();
327     Standard_Integer nVx = UpdateVertex(nV, aTolVNew);
328     // 2. Create new pave and add it as extra pave to pave block
329     //    for further splitting of the edge
330     const BOPDS_ListOfPaveBlock& aLPB = myDS->PaveBlocks (nE);
331     // Find the appropriate one
332     Handle(BOPDS_PaveBlock) aPB;
333     BOPDS_ListOfPaveBlock::Iterator itPB (aLPB);
334     for (; itPB.More(); itPB.Next())
335     {
336       aPB = itPB.Value();
337       Standard_Real aT1, aT2;
338       aPB->Range (aT1, aT2);
339       if (aT > aT1 && aT < aT2)
340         break;
341     }
342     if (!itPB.More())
343       continue;
344
345     BOPDS_Pave aPave;
346     aPave.SetIndex(nVx);
347     aPave.SetParameter(aT);
348     aPB->AppendExtPave(aPave);
349     aMEdges.Add(nE);
350     //
351     if (theAddInterfs) {
352       // Add interferences into DS
353       BOPDS_Pair aPair(nV, nE);
354       const TColStd_ListOfInteger& aLI = aDMVSD.Find(aPair);
355       TColStd_ListIteratorOfListOfInteger aItLI(aLI);
356       for (; aItLI.More(); aItLI.Next()) {
357         const Standard_Integer nVOld = aItLI.Value();
358         // 3. Create interference V/E
359         BOPDS_InterfVE& aVE = aVEs.Appended();
360         aVE.SetIndices(nVOld, nE);
361         aVE.SetParameter(aT);
362         // 2. Add a pair in the whole table of interferences
363         myDS->AddInterf(nVOld, nE);
364         // 4. Set index of new vertex in the interference
365         if (myDS->IsNewShape(nVx)) {
366           aVE.SetIndexNew(nVx);
367         }
368       }
369     }
370   }
371   //
372   // Split pave blocks of the intersected edges with the extra paves.
373   // At the same time compute shrunk data for the new pave blocks
374   // and in case there is no valid range for the pave block,
375   // the vertices of this pave block should be unified.
376   SplitPaveBlocks(aMEdges, theAddInterfs);
377 }
378
379 //=======================================================================
380 // function: MakeNewCommonBlock
381 // purpose: Make new Common Block from the given list of Pave Blocks
382 //=======================================================================
383 static
384   void MakeNewCommonBlock(const BOPDS_ListOfPaveBlock& theLPB,
385                           const TColStd_ListOfInteger& theLFaces,
386                           BOPDS_PDS& theDS)
387 {
388   // Make Common Block from the pave blocks in the list
389   Handle(BOPDS_CommonBlock) aCBNew = new BOPDS_CommonBlock;
390   aCBNew->SetPaveBlocks(theLPB);
391   aCBNew->SetFaces(theLFaces);
392   //
393   BOPDS_ListIteratorOfListOfPaveBlock aItLPB(theLPB);
394   for (; aItLPB.More(); aItLPB.Next()) {
395     theDS->SetCommonBlock(aItLPB.ChangeValue(), aCBNew);
396   }
397 }
398
399 //=======================================================================
400 // function: SplitPaveBlocks
401 // purpose: 
402 //=======================================================================
403 void BOPAlgo_PaveFiller::SplitPaveBlocks(const TColStd_MapOfInteger& theMEdges,
404                                          const Standard_Boolean theAddInterfs)
405 {
406   // Fence map to avoid unification of the same vertices twice
407   BOPDS_MapOfPair aMPairs;
408   // Map to treat the Common Blocks
409   NCollection_IndexedDataMap<Handle(BOPDS_CommonBlock),
410                              BOPDS_ListOfPaveBlock,
411                              TColStd_MapTransientHasher> aMCBNewPB;
412   //
413   // Map of vertices to init the pave blocks for them
414   TColStd_MapOfInteger aMVerticesToInitPB;
415
416   TColStd_MapIteratorOfMapOfInteger aItM(theMEdges);
417   for (; aItM.More(); aItM.Next()) {
418     Standard_Integer nE = aItM.Value();
419     BOPDS_ListOfPaveBlock& aLPB = myDS->ChangePaveBlocks(nE);
420     //
421     BOPDS_ListIteratorOfListOfPaveBlock aItLPB(aLPB);
422     for (; aItLPB.More();) {
423       Handle(BOPDS_PaveBlock)& aPB = aItLPB.ChangeValue();
424       //
425       if (!aPB->IsToUpdate()) {
426         aItLPB.Next();
427         continue;
428       }
429       //
430       const Handle(BOPDS_CommonBlock)& aCB = myDS->CommonBlock(aPB);
431       //
432       // Compute new pave blocks
433       BOPDS_ListOfPaveBlock aLPBN;
434       aPB->Update(aLPBN);
435       //
436       // Make sure that each new pave block has a valid range,
437       // otherwise unify the vertices of the pave block
438       BOPDS_ListIteratorOfListOfPaveBlock aItLPBN(aLPBN);
439       for (; aItLPBN.More(); aItLPBN.Next()) {
440         Handle(BOPDS_PaveBlock)& aPBN = aItLPBN.ChangeValue();
441         myDS->UpdatePaveBlockWithSDVertices(aPBN);
442         FillShrunkData(aPBN);
443         //
444         Standard_Boolean bHasValidRange = aPBN->HasShrunkData();
445         // Take into account that the edge could have really small valid range,
446         // so that the Pave Block cannot be further split. In this case, check if
447         // the vertices of the Pave Block do not interfere. And if they are, unify them.
448         Standard_Boolean bCheckDist = (bHasValidRange && !aPBN->IsSplittable());
449         if (!bHasValidRange || bCheckDist)
450         {
451           Standard_Integer nV1, nV2;
452           aPBN->Indices(nV1, nV2);
453           if (nV1 == nV2)
454             // Same vertices -> no valid range, no need to unify vertices
455             continue;
456
457           // Decide whether to unify vertices or not
458           if (bCheckDist)
459           {
460             const TopoDS_Vertex& aV1 = TopoDS::Vertex(myDS->Shape(nV1));
461             const TopoDS_Vertex& aV2 = TopoDS::Vertex(myDS->Shape(nV2));
462             if (BOPTools_AlgoTools::ComputeVV(aV1, aV2, myFuzzyValue) == 0)
463               // vertices are interfering -> no valid range, unify vertices
464               bHasValidRange = Standard_False;
465           }
466
467           if (!bHasValidRange)
468           {
469             BOPDS_Pair aPair;
470             aPair.SetIndices(nV1, nV2);
471             if (aMPairs.Add(aPair))
472             {
473               TColStd_ListOfInteger aLV;
474               aLV.Append(nV1);
475               aLV.Append(nV2);
476               MakeSDVertices(aLV, theAddInterfs);
477
478               // Save vertices to init pave blocks
479               aMVerticesToInitPB.Add(nV1);
480               aMVerticesToInitPB.Add(nV2);
481             }
482             continue;
483           }
484         }
485         //
486         // Update the list with new pave block
487         aLPB.Append(aPBN);
488         // Treat the common block
489         if (!aCB.IsNull()) {
490           // Store the new pave block to make new common block
491           BOPDS_ListOfPaveBlock* pLPBCB = aMCBNewPB.ChangeSeek(aCB);
492           if (!pLPBCB) {
493             pLPBCB = &aMCBNewPB(aMCBNewPB.Add(aCB, BOPDS_ListOfPaveBlock()));
494           }
495           pLPBCB->Append(aPBN);
496         }
497       }
498       // Remove old pave block
499       aLPB.Remove(aItLPB);
500     }
501   }
502   //
503   // Make Common Blocks
504   Standard_Integer i, aNbCB = aMCBNewPB.Extent();
505   for (i = 1; i <= aNbCB; ++i) {
506     const Handle(BOPDS_CommonBlock)& aCB = aMCBNewPB.FindKey(i);
507     const BOPDS_ListOfPaveBlock& aLPBN = aMCBNewPB(i);
508     //
509     // For each group of pave blocks with the same vertices make new common block
510     NCollection_IndexedDataMap<BOPDS_Pair, BOPDS_ListOfPaveBlock, BOPDS_PairMapHasher> aMInds;
511     BOPDS_ListIteratorOfListOfPaveBlock aItLPB(aLPBN);
512     for (; aItLPB.More(); aItLPB.Next()) {
513       const Handle(BOPDS_PaveBlock)& aPB = aItLPB.Value();
514       //
515       BOPDS_Pair aPair;
516       aPair.SetIndices(aPB->Pave1().Index(), aPB->Pave2().Index());
517       //
518       BOPDS_ListOfPaveBlock* pLPBx = aMInds.ChangeSeek(aPair);
519       if (!pLPBx) {
520         pLPBx = &aMInds(aMInds.Add(aPair, BOPDS_ListOfPaveBlock()));
521       }
522       pLPBx->Append(aPB);
523     }
524     //
525     Standard_Integer nV1, nV2;
526     aCB->PaveBlock1()->Indices(nV1, nV2);
527     Standard_Boolean bIsClosed = (nV1 == nV2);
528     //
529     Standard_Integer j, aNbPairs = aMInds.Extent();
530     for (j = 1; j <= aNbPairs; ++j) {
531       BOPDS_ListOfPaveBlock& aLPB = aMInds(j);
532       //
533       if (!bIsClosed) {
534         // Make Common Block from the pave blocks in the list
535         MakeNewCommonBlock(aLPB, aCB->Faces(), myDS);
536         continue;
537       }
538       //
539       // Find coinciding pave blocks
540       while (aLPB.Extent()) {
541         // Pave blocks forming the common block
542         BOPDS_ListOfPaveBlock aLPBCB;
543         // Point in the middle of the first pave block in the common block
544         gp_Pnt aPMFirst(0., 0., 0.);
545         // Tolerance of the first edge in the common block
546         Standard_Real aTolEFirst = 0.;
547         //
548         aItLPB.Initialize(aLPB);
549         for (; aItLPB.More();) {
550           const Handle(BOPDS_PaveBlock)& aPB = aItLPB.Value();
551           if (aLPBCB.IsEmpty()) {
552             aLPBCB.Append(aPB);
553             const TopoDS_Edge& aEFirst = TopoDS::Edge(myDS->Shape(aPB->OriginalEdge()));
554             aTolEFirst = BRep_Tool::MaxTolerance(aEFirst, TopAbs_VERTEX);
555             //
556             Standard_Real aTmFirst = (aPB->Pave1().Parameter() + aPB->Pave2().Parameter()) / 2.;
557             BOPTools_AlgoTools::PointOnEdge(aEFirst, aTmFirst, aPMFirst);
558             //
559             aLPB.Remove(aItLPB);
560             continue;
561           }
562           //
563           // Check pave blocks for coincidence
564           const TopoDS_Edge& aE = TopoDS::Edge(myDS->Shape(aPB->OriginalEdge()));
565           Standard_Real aTolE = BRep_Tool::MaxTolerance(aE, TopAbs_VERTEX);
566           //
567           Standard_Real aTOut, aDist;
568           Standard_Integer iErr =
569             myContext->ComputePE(aPMFirst, aTolEFirst + aTolE + myFuzzyValue, aE, aTOut, aDist);
570           if (!iErr && ((aTOut > aPB->Pave1().Parameter()) && (aTOut < aPB->Pave2().Parameter()))) {
571             aLPBCB.Append(aPB);
572             aLPB.Remove(aItLPB);
573             continue;
574           }
575           aItLPB.Next();
576         }
577         //
578         // Make Common Block from the pave blocks in the list
579         MakeNewCommonBlock(aLPBCB, aCB->Faces(), myDS);
580       }
581     }
582   }
583
584   // Init pave blocks for vertices which have acquired SD vertex
585   aItM.Initialize(aMVerticesToInitPB);
586   for (; aItM.More(); aItM.Next())
587     myDS->InitPaveBlocksForVertex(aItM.Value());
588 }
589
590 //=======================================================================
591 // function: AddIntersectionFailedWarning
592 // purpose: 
593 //=======================================================================
594 void BOPAlgo_PaveFiller::AddIntersectionFailedWarning(const TopoDS_Shape& theS1,
595                                                       const TopoDS_Shape& theS2)
596 {
597   // Create the warn shape
598   TopoDS_Compound aWC;
599   BRep_Builder().MakeCompound(aWC);
600   BRep_Builder().Add(aWC, theS1);
601   BRep_Builder().Add(aWC, theS2);
602   // Add the warning
603   AddWarning(new BOPAlgo_AlertIntersectionOfPairOfShapesFailed(aWC));
604 }