0030901: Visualization - OSD_MemInfo moving memory computation out of the constructor
[occt.git] / src / BOPAlgo / BOPAlgo_PaveFiller_8.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 #include <BOPAlgo_PaveFiller.hxx>
19 #include <BOPAlgo_SectionAttribute.hxx>
20 #include <BOPDS_Curve.hxx>
21 #include <BOPDS_DS.hxx>
22 #include <BOPDS_FaceInfo.hxx>
23 #include <BOPDS_MapOfPaveBlock.hxx>
24 #include <BOPDS_Pave.hxx>
25 #include <BOPDS_PaveBlock.hxx>
26 #include <BOPDS_ShapeInfo.hxx>
27 #include <BRep_Builder.hxx>
28 #include <BRep_Tool.hxx>
29 #include <ElCLib.hxx>
30 #include <Geom2d_Curve.hxx>
31 #include <Geom2d_Line.hxx>
32 #include <Geom2d_TrimmedCurve.hxx>
33 #include <Geom2dAdaptor_Curve.hxx>
34 #include <Geom2dAPI_ProjectPointOnCurve.hxx>
35 #include <Geom2dInt_GInter.hxx>
36 #include <gp_Lin2d.hxx>
37 #include <gp_Pnt.hxx>
38 #include <gp_Pnt2d.hxx>
39 #include <IntRes2d_IntersectionPoint.hxx>
40 #include <IntTools_Context.hxx>
41 #include <Precision.hxx>
42 #include <TColStd_ListOfInteger.hxx>
43 #include <TopoDS_Edge.hxx>
44 #include <TopoDS_Face.hxx>
45 #include <TopoDS_Vertex.hxx>
46
47 static
48   void MakeSplitEdge1 (const TopoDS_Edge&   aE,
49                        const TopoDS_Face&   aF,
50                        const TopoDS_Vertex& aV1,
51                        const Standard_Real  aP1,
52                        const TopoDS_Vertex& aV2,
53                        const Standard_Real  aP2,
54                        TopoDS_Edge& aNewEdge);
55
56 static
57   Standard_Boolean AddSplitPoint(const Handle(BOPDS_PaveBlock)& thePBD,
58                                  const BOPDS_Pave& thePave,
59                                  const Standard_Real theTol);
60
61 //=======================================================================
62 //function : ProcessDE
63 //purpose  : 
64 //=======================================================================
65 void BOPAlgo_PaveFiller::ProcessDE()
66 {
67   Standard_Integer nF, aNb, nE, nV, nVSD, aNbPB;
68   Handle(NCollection_BaseAllocator) aAllocator;
69   Handle(BOPDS_PaveBlock) aPBD;
70   TColStd_ListIteratorOfListOfInteger aItLI;
71   //
72   // 1. Find degnerated edges
73   //-----------------------------------------------------scope f
74   //
75   aAllocator=
76     NCollection_BaseAllocator::CommonBaseAllocator();
77   BOPDS_ListOfPaveBlock aLPBOut(aAllocator);
78   //
79   aNb=myDS->NbSourceShapes();
80   for (nE=0; nE<aNb; ++nE) {
81     const BOPDS_ShapeInfo& aSIE=myDS->ShapeInfo(nE);
82     if (aSIE.ShapeType()==TopAbs_EDGE) {
83       if (aSIE.HasFlag(nF)) {
84         const BOPDS_ShapeInfo& aSIF=myDS->ShapeInfo(nF);
85         nV=aSIE.SubShapes().First();
86         if (myDS->HasShapeSD(nV, nVSD)) {
87           nV=nVSD;
88         }
89         //nV,nE,nF
90         //
91         if (aSIF.ShapeType() == TopAbs_FACE) {
92           // 1. Find PaveBlocks that are go through nV for nF
93           FindPaveBlocks(nV, nF, aLPBOut);
94           aNbPB=aLPBOut.Extent();
95           if (aNbPB) {
96             //
97             // 2.
98             BOPDS_ListOfPaveBlock& aLPBD = myDS->ChangePaveBlocks(nE);
99             Standard_ASSERT_VOID(!aLPBD.IsEmpty(), "ListOfPaveBlock is unexpectedly empty");
100             if (aLPBD.IsEmpty())
101               continue;
102             aPBD = aLPBD.First();
103             //
104             FillPaves(nV, nE, nF, aLPBOut, aPBD);
105             //
106             myDS->UpdatePaveBlock(aPBD);
107           }
108           //
109           MakeSplitEdge(nE, nF);
110           //
111           aLPBOut.Clear();
112         }
113         if (aSIF.ShapeType() == TopAbs_EDGE) {
114           Standard_Real aTol=1.e-7;
115           Standard_Integer nEn;
116           BRep_Builder BB;
117           const TopoDS_Edge& aDE=(*(TopoDS_Edge *)(&myDS->Shape(nE))); 
118           const TopoDS_Vertex& aVn = (*(TopoDS_Vertex *)(&myDS->Shape(nV)));
119           //
120           TopoDS_Edge aE=aDE;
121           aE.EmptyCopy();
122           BB.Add(aE, aVn);
123           BB.Degenerated(aE, Standard_True);
124           BB.UpdateEdge(aE, aTol);
125           BOPDS_ShapeInfo aSI;
126           aSI.SetShapeType(TopAbs_EDGE);
127           aSI.SetShape(aE);
128           nEn=myDS->Append(aSI);
129           BOPDS_ListOfPaveBlock& aLPBD=myDS->ChangePaveBlocks(nE);
130           aPBD=aLPBD.First();
131           aPBD->SetEdge(nEn);
132         }
133       }
134     }
135   }
136 }
137
138 //=======================================================================
139 //function : FindPaveBlocks
140 //purpose  : 
141 //=======================================================================
142   void BOPAlgo_PaveFiller::FindPaveBlocks(const Standard_Integer nV,
143                                           const Standard_Integer nF,
144                                           BOPDS_ListOfPaveBlock& aLPBOut)
145 {
146   Standard_Integer i, aNbPBOn, aNbPBIn, aNbPBSc, nV1, nV2;
147   //
148   const BOPDS_FaceInfo& aFI=myDS->ChangeFaceInfo(nF);
149   // In
150   const BOPDS_IndexedMapOfPaveBlock& aMPBIn=aFI.PaveBlocksIn();
151   aNbPBIn = aMPBIn.Extent();
152   for (i = 1; i <= aNbPBIn; ++i) {
153     const Handle(BOPDS_PaveBlock)& aPB = aMPBIn(i);
154     aPB->Indices(nV1, nV2);
155     if (nV==nV1 || nV==nV2) {
156       aLPBOut.Append(aPB);
157     }
158   }
159   // On
160   const BOPDS_IndexedMapOfPaveBlock& aMPBOn=aFI.PaveBlocksOn();
161   aNbPBOn = aMPBOn.Extent();
162   for (i = 1; i <= aNbPBOn; ++i) {
163     const Handle(BOPDS_PaveBlock)& aPB = aMPBOn(i);
164     aPB->Indices(nV1, nV2);
165     if (nV==nV1 || nV==nV2) {
166       aLPBOut.Append(aPB);
167     }
168   }
169   // Sections
170   const BOPDS_IndexedMapOfPaveBlock& aMPBSc=aFI.PaveBlocksSc();
171   aNbPBSc = aMPBSc.Extent();
172   for (i = 1; i <= aNbPBSc; ++i) {
173     const Handle(BOPDS_PaveBlock)& aPB = aMPBSc(i);
174     aPB->Indices(nV1, nV2);
175     if (nV==nV1 || nV==nV2) {
176       aLPBOut.Append(aPB);
177     }
178   }
179 }
180
181 //=======================================================================
182 //function : MakeSplitEdge
183 //purpose  : 
184 //=======================================================================
185   void BOPAlgo_PaveFiller::MakeSplitEdge (const Standard_Integer nDE,
186                                           const Standard_Integer nDF)
187
188   Standard_Integer nSp, nV1, nV2, aNbPB;
189   Standard_Real aT1, aT2;
190   TopoDS_Edge aDE, aSp;
191   TopoDS_Vertex aV1, aV2;
192   BOPDS_ListIteratorOfListOfPaveBlock aItLPB;
193   BOPDS_ShapeInfo aSI;
194   //
195   aSI.SetShapeType(TopAbs_EDGE);
196   //
197   aDE=(*(TopoDS_Edge *)(&myDS->Shape(nDE))); 
198   aDE.Orientation(TopAbs_FORWARD);
199   //
200   const TopoDS_Face& aDF=(*(TopoDS_Face *)(&myDS->Shape(nDF)));
201   //
202   BOPDS_ListOfPaveBlock& aLPB=myDS->ChangePaveBlocks(nDE);
203   aNbPB=aLPB.Extent();
204   //
205   aItLPB.Initialize(aLPB);
206   for (; aItLPB.More(); aItLPB.Next()) {
207     Handle(BOPDS_PaveBlock)& aPB=aItLPB.ChangeValue();
208     //
209     const BOPDS_Pave& aPave1=aPB->Pave1();
210     aPave1.Contents(nV1, aT1);
211     //
212     const BOPDS_Pave& aPave2=aPB->Pave2();
213     aPave2.Contents(nV2, aT2);
214     //
215     if (myDS->IsNewShape(nV1) || aNbPB>1) {
216       aV1=(*(TopoDS_Vertex *)(&myDS->Shape(nV1)));
217       aV1.Orientation(TopAbs_FORWARD); 
218       //
219       aV2=(*(TopoDS_Vertex *)(&myDS->Shape(nV2)));
220       aV2.Orientation(TopAbs_REVERSED); 
221       //
222       MakeSplitEdge1(aDE, aDF, aV1, aT1, aV2, aT2, aSp); 
223       //
224       aSI.SetShape(aSp);
225       nSp=myDS->Append(aSI);
226       aPB->SetEdge(nSp);
227     }
228     else {
229       myDS->ChangeShapeInfo(nDE).SetReference(-1);
230       aLPB.Clear();
231       break;
232     }
233   }
234 }
235
236 //=======================================================================
237 //function : FillPaves
238 //purpose  : Find all pave blocks passing through the vertex <nVD> and
239 //           intersecting the 2D curve of the degenerated edge
240 //           somewhere in the middle. Save intersection points into
241 //           Extra paves of the pave block of degenerated edge for future
242 //           splitting.
243 //=======================================================================
244   void BOPAlgo_PaveFiller::FillPaves(const Standard_Integer nVD,
245                                      const Standard_Integer nED,
246                                      const Standard_Integer nFD,
247                                      const BOPDS_ListOfPaveBlock& aLPBOut,
248                                      const Handle(BOPDS_PaveBlock)& aPBD)
249 {
250   // Prepare pave to put to pave block as an Extra pave
251   BOPDS_Pave aPave;
252   aPave.SetIndex(nVD);
253   //
254   const TopoDS_Vertex& aDV = (*(TopoDS_Vertex *)(&myDS->Shape(nVD)));
255   const TopoDS_Edge& aDE = (*(TopoDS_Edge *)(&myDS->Shape(nED)));
256   const TopoDS_Face& aDF = (*(TopoDS_Face *)(&myDS->Shape(nFD)));
257   //
258   Standard_Real aTolV = BRep_Tool::Tolerance(aDV);
259   const BRepAdaptor_Surface& aBAS = myContext->SurfaceAdaptor(aDF);
260   //
261   // 2D intersection tolerance should be computed as a resolution
262   // from the tolerance of vertex to resolve the touching cases
263   Standard_Real aTolInt = Precision::PConfusion();
264   // UResolution from the tolerance of the vertex
265   Standard_Real aURes = aBAS.UResolution(aTolV);
266   // VResolution from the tolerance of the vertex
267   Standard_Real aVRes = aBAS.VResolution(aTolV);
268   //
269   aTolInt = Max(aTolInt, Max(aURes, aVRes));
270   //
271   // Parametric tolerance to compare intersection point with boundaries
272   // should be computed as a resolution from the tolerance of vertex
273   // in the direction of the 2D curve of degenerated edge
274   Standard_Real aTolCmp = Precision::PConfusion();
275   // Get 2D curve
276   Standard_Real aTD1, aTD2;
277   Handle(Geom2d_Curve) aC2DDE = BRep_Tool::CurveOnSurface(aDE, aDF, aTD1, aTD2);
278   // Get direction of the curve
279   Standard_Boolean bUDir = Abs(aC2DDE->Value(aTD1).Y() - aC2DDE->Value(aTD2).Y()) < Precision::PConfusion();
280   //
281   aTolCmp = Max(aTolCmp, (bUDir ? aURes : aVRes));
282   //
283   // Prepare adaptor for the degenerated edge for intersection
284   Geom2dAdaptor_Curve aGAC1;
285   aGAC1.Load(aC2DDE, aTD1, aTD2);
286   //
287   BOPDS_ListIteratorOfListOfPaveBlock aItLPB(aLPBOut);
288   for (; aItLPB.More(); aItLPB.Next()) {
289     const Handle(BOPDS_PaveBlock)& aPB = aItLPB.Value();
290     Standard_Integer nE = aPB->Edge();
291     if (nE < 0) {
292       continue;
293     }
294     const TopoDS_Edge& aE = (*(TopoDS_Edge *)(&myDS->Shape(nE)));
295     Standard_Real aT1, aT2;
296     Handle(Geom2d_Curve) aC2D = BRep_Tool::CurveOnSurface(aE, aDF, aT1, aT2);
297     if (aC2D.IsNull()) {
298       continue;
299     }
300     //
301     // Prepare adaptor for the passing edge for intersection
302     Geom2dAdaptor_Curve aGAC2;
303     //
304     Handle(Geom2d_Line) aL2D = Handle(Geom2d_Line)::DownCast(aC2D);
305     if (!aL2D.IsNull()) {
306       aGAC2.Load(aC2D);
307     }
308     else {
309       aGAC2.Load(aC2D, aT1, aT2);
310     }
311     // Intersection
312     Geom2dInt_GInter aGInter(aGAC1, aGAC2, aTolInt, aTolInt);
313     if (aGInter.IsDone() && aGInter.NbPoints())
314     {
315       // Analyze intersection points
316       Standard_Integer i, aNbPoints = aGInter.NbPoints();
317       for (i = 1; i <= aNbPoints; ++i) {
318         Standard_Real aX = aGInter.Point(i).ParamOnFirst();
319         aPave.SetParameter(aX);
320         AddSplitPoint(aPBD, aPave, aTolCmp);
321       }
322     }
323     else
324     {
325       // If the intersection did not succeed, try the projection of the end point
326       // of the curve corresponding to the vertex of degenerated edge
327       Standard_Real aT = (nVD == aPB->Pave1().Index() ?
328         aPB->Pave1().Parameter() : aPB->Pave2().Parameter());
329       gp_Pnt2d aP2d = aC2D->Value(aT);
330       Geom2dAPI_ProjectPointOnCurve aProj2d(aP2d, aC2DDE, aTD1, aTD2);
331       if (aProj2d.NbPoints())
332       {
333         Standard_Real aX = aProj2d.LowerDistanceParameter();
334         aPave.SetParameter(aX);
335         AddSplitPoint(aPBD, aPave, aTolCmp);
336       }
337     }
338   }
339 }
340 //=======================================================================
341 // function:  MakeSplitEdge1
342 // purpose: 
343 //=======================================================================
344   void MakeSplitEdge1 (const TopoDS_Edge&   aE,
345                        const TopoDS_Face&   aF,
346                        const TopoDS_Vertex& aV1,
347                        const Standard_Real  aP1,
348                        const TopoDS_Vertex& aV2,
349                        const Standard_Real  aP2,
350                        TopoDS_Edge& aNewEdge)
351 {
352   Standard_Real aTol=1.e-7;
353
354   TopoDS_Edge E=aE;
355
356   E.EmptyCopy();
357   BRep_Builder BB;
358   BB.Add  (E, aV1);
359   BB.Add  (E, aV2);
360
361   BB.Range(E, aF, aP1, aP2);
362
363   BB.Degenerated(E, Standard_True);
364
365   BB.UpdateEdge(E, aTol);
366   aNewEdge=E;
367 }
368
369 //=======================================================================
370 // function: AddSplitPoint
371 // purpose: Validates the point represented by the pave <thePave>
372 //          for the Pave Block <thePBD>.
373 //          In case the point passes the checks it is added as an
374 //          Extra Pave to the Pave Block for further splitting of the latter.
375 //          Returns TRUE if the point is added, otherwise returns FALSE.
376 //=======================================================================
377 Standard_Boolean AddSplitPoint(const Handle(BOPDS_PaveBlock)& thePBD,
378                                const BOPDS_Pave& thePave,
379                                const Standard_Real theTol)
380 {
381   Standard_Real aTD1, aTD2;
382   thePBD->Range(aTD1, aTD2);
383
384   Standard_Real aT = thePave.Parameter();
385   // Check that the parameter is inside the Pave Block
386   if (aT - aTD1 < theTol || aTD2 - aT < theTol)
387     return Standard_False;
388
389   // Check that the pave block does not contain the same parameter
390   Standard_Integer anInd;
391   if (thePBD->ContainsParameter(aT, theTol, anInd))
392     return Standard_False;
393
394   // Add the point as an Extra pave to the Pave Block for further
395   // splitting of the latter
396   thePBD->AppendExtPave1(thePave);
397   return Standard_True;
398 }