Salome HOME
IPAL19834: Incorrect result after make Partition of 2 objects. A fix by PKV.
[modules/geom.git] / src / NMTTools / NMTTools_DEProcessor.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_DEProcessor.cxx
21 // Created:     Wed Sep 12 12:10:52 2001
22 // Author:      Peter KURNEV
23 //              <pkv@irinox>
24
25 #include <NMTTools_DEProcessor.ixx>
26
27 #include <Precision.hxx>
28
29 #include <TColStd_ListIteratorOfListOfInteger.hxx>
30 #include <TColStd_ListOfInteger.hxx>
31
32 #include <gp_Pnt2d.hxx>
33 #include <gp_Pnt.hxx>
34 #include <gp_Lin2d.hxx>
35
36 #include <ElCLib.hxx>
37
38 #include <Geom2d_Curve.hxx>
39 #include <Geom2d_Line.hxx>
40 #include <Geom2d_TrimmedCurve.hxx>
41 #include <Geom2dAdaptor_Curve.hxx>
42 #include <Geom2dInt_GInter.hxx>
43
44 #include <IntRes2d_IntersectionPoint.hxx>
45
46 #include <TopoDS_Shape.hxx>
47 #include <TopoDS_Edge.hxx>
48 #include <TopoDS.hxx>
49 #include <TopoDS_Face.hxx>
50 #include <TopoDS_Vertex.hxx>
51 #include <TopoDS_Solid.hxx>
52
53 #include <TopExp.hxx>
54 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
55 #include <TopTools_ListOfShape.hxx>
56 #include <TopTools_ListIteratorOfListOfShape.hxx>
57
58 #include <BRep_Tool.hxx>
59 #include <BRep_Builder.hxx>
60
61 #include <BRepAdaptor_Surface.hxx>
62
63 #include <BooleanOperations_AncestorsSeqAndSuccessorsSeq.hxx>
64
65 #include <IntTools_Tools.hxx>
66 #include <IntTools_Context.hxx>
67
68 #include <BOPTools_DEInfo.hxx>
69 #include <BOPTools_Pave.hxx>
70 #include <BOPTools_ListOfPave.hxx>
71 #include <BOPTools_ListIteratorOfListOfPave.hxx>
72 #include <BOPTools_PaveBlock.hxx>
73 #include <BOPTools_ListOfPaveBlock.hxx>
74 #include <BOPTools_ListIteratorOfListOfPaveBlock.hxx>
75 #include <BOPTools_PaveBlockIterator.hxx>
76 #include <BOPTools_SSInterference.hxx>
77 #include <BOPTools_PavePool.hxx>
78 #include <BOPTools_PaveSet.hxx>
79 #include <BOPTools_Tools3D.hxx>
80 #include <BOPTools_SequenceOfCurves.hxx>
81 #include <BOPTools_Curve.hxx>
82 #include <BOPTools_CArray1OfSSInterference.hxx>
83 #include <BOPTools_SplitShapesPool.hxx>
84
85 #include <NMTDS_ShapesDataStructure.hxx>
86 #include <NMTDS_InterfPool.hxx>
87
88 #include <NMTTools_PaveFiller.hxx>
89
90 //=======================================================================
91 // function: 
92 // purpose: 
93 //=======================================================================
94   NMTTools_DEProcessor::NMTTools_DEProcessor(NMTTools_PaveFiller& aPaveFiller)
95 :
96   myIsDone(Standard_False)
97 {
98   myFiller=(NMTTools_PaveFiller*) &aPaveFiller;
99   myDS=myFiller->DS();
100 }
101 //=======================================================================
102 // function: IsDone
103 // purpose: 
104 //=======================================================================
105   Standard_Boolean NMTTools_DEProcessor::IsDone() const
106 {
107   return myIsDone;
108 }
109 //=======================================================================
110 // function:  Do
111 // purpose: 
112 //=======================================================================
113   void NMTTools_DEProcessor::Do()
114 {
115   Standard_Integer aNbE;
116   //
117   myIsDone=Standard_False;
118   //
119   FindDegeneratedEdges();
120   //
121   aNbE=myDEMap.Extent();
122   if (!aNbE) {
123     myIsDone=!myIsDone;
124     return;
125   }
126   //
127   DoPaves();
128 }
129 //=======================================================================
130 // function:  FindDegeneratedEdges
131 // purpose: 
132 //=======================================================================
133   void NMTTools_DEProcessor::FindDegeneratedEdges()
134 {
135   Standard_Integer i, aNb, nV, nF, nVx, ip, iRankE;
136   TopoDS_Vertex aV;
137   TopTools_IndexedDataMapOfShapeListOfShape aMEF;
138   //
139   aNb=myDS->NumberOfShapesOfTheObject();
140   for (i=1; i<=aNb; ++i) {
141     const TopoDS_Shape aF=myDS->Shape(i);
142     if (aF.ShapeType()==TopAbs_FACE) {
143       TopExp::MapShapesAndAncestors (aF, TopAbs_EDGE, TopAbs_FACE, aMEF);
144     }
145   }
146   //
147   for (i=1; i<=aNb; ++i) {
148     const TopoDS_Shape aS=myDS->Shape(i);
149     if (aS.ShapeType()==TopAbs_EDGE) {
150       const TopoDS_Edge& aE=TopoDS::Edge(aS);
151       
152       if (BRep_Tool::Degenerated(aE)) {
153         iRankE=myDS->Rank(i);
154         aV=TopExp::FirstVertex(aE);
155         nVx=myDS->ShapeIndex(aV, iRankE);
156         //
157         nV=nVx;
158         ip=myFiller->FindSDVertex(nV);
159         if (ip) {
160           nV=ip;
161         }
162         //
163         TColStd_ListOfInteger aLFn;
164         const TopTools_ListOfShape& aLF=aMEF.FindFromKey(aE);
165         TopTools_ListIteratorOfListOfShape anIt(aLF);
166         for (; anIt.More(); anIt.Next()) {
167           const TopoDS_Shape& aF=anIt.Value();
168           nF=myDS->ShapeIndex(aF, iRankE);
169           aLFn.Append(nF);
170         }
171         BOPTools_DEInfo aDEInfo;
172         aDEInfo.SetVertex(nV);
173         aDEInfo.SetFaces(aLFn);
174
175         myDEMap.Add (i, aDEInfo);
176       }
177     }
178   }
179 }
180 //=======================================================================
181 // function:  DoPaves
182 // purpose: 
183 //=======================================================================
184   void NMTTools_DEProcessor::DoPaves()
185 {
186
187   Standard_Integer i, aNbE, nED, nVD, aNbLPB, nFD;
188   //
189   nFD=0;
190   aNbE=myDEMap.Extent();
191   for (i=1; i<=aNbE; ++i) {
192     nED=myDEMap.FindKey(i);
193     //
194     const BOPTools_DEInfo& aDEInfo=myDEMap(i);
195     nVD=aDEInfo.Vertex();
196     //
197     // Fill PaveSet for the edge nED
198     const TColStd_ListOfInteger& nLF=aDEInfo.Faces();
199     TColStd_ListIteratorOfListOfInteger anIt(nLF);
200     for (; anIt.More(); anIt.Next()) {
201       nFD=anIt.Value();
202       
203       BOPTools_ListOfPaveBlock aLPB;
204       FindPaveBlocks(nED, nVD, nFD, aLPB);
205       //
206       aNbLPB=aLPB.Extent();
207       if (!aNbLPB) {
208         continue;
209       }
210       //
211       FillPaveSet (nED, nVD, nFD, aLPB);
212     }
213     // 
214     // Fill aSplitEdges for the edge nED
215     FillSplitEdgesPool(nED);
216     //
217     // MakeSplitEdges
218     MakeSplitEdges(nED, nFD);
219     //
220   }// next nED
221 }
222 //=======================================================================
223 // function:  FindPaveBlocks
224 // purpose: 
225 //=======================================================================
226   void NMTTools_DEProcessor::FindPaveBlocks(const Standard_Integer ,
227                                             const Standard_Integer nVD,
228                                             const Standard_Integer nFD,
229                                             BOPTools_ListOfPaveBlock& aLPBOut)
230 {
231   BOPTools_ListIteratorOfListOfPaveBlock anIt;
232   Standard_Integer i, aNb, nF2, nV;
233   //
234   BOPTools_CArray1OfSSInterference& aFFs=(myFiller->IP())->SSInterferences();
235   //
236   aNb=aFFs.Extent();
237   for (i=1; i<=aNb; ++i) {
238     BOPTools_SSInterference& aFF=aFFs(i);
239     //
240     nF2=aFF.OppositeIndex(nFD);
241     if (!nF2) {
242       continue;
243     }
244     //
245     // Split Parts 
246     const BOPTools_ListOfPaveBlock& aLPBSplits=aFF.PaveBlocks();
247     anIt.Initialize(aLPBSplits);
248     for (; anIt.More(); anIt.Next()) {
249       const BOPTools_PaveBlock& aPBSp=anIt.Value();
250       //
251       const BOPTools_Pave& aPave1=aPBSp.Pave1();
252       nV=aPave1.Index();
253       if (nV==nVD) {
254         aLPBOut.Append(aPBSp);
255         continue;
256       }
257       //
258       const BOPTools_Pave& aPave2=aPBSp.Pave2();
259       nV=aPave2.Index();
260       if (nV==nVD) {
261         aLPBOut.Append(aPBSp);
262         continue;
263       }
264     }
265     //
266     // Section Parts
267     Standard_Integer j, aNbCurves;   
268     //
269     BOPTools_SequenceOfCurves& aSC=aFF.Curves();
270     aNbCurves=aSC.Length();
271     for (j=1; j<=aNbCurves; ++j) {
272       const BOPTools_Curve& aBC=aSC(j);
273       const BOPTools_ListOfPaveBlock& aLPBSe=aBC.NewPaveBlocks();
274       //
275       anIt.Initialize(aLPBSe);
276       for (; anIt.More(); anIt.Next()) {
277         const BOPTools_PaveBlock& aPBSe=anIt.Value();
278         //
279         const BOPTools_Pave& aPv1=aPBSe.Pave1();
280         nV=aPv1.Index();
281         if (nV==nVD) {
282           aLPBOut.Append(aPBSe);
283           continue;
284         }
285         //
286         const BOPTools_Pave& aPv2=aPBSe.Pave2();
287         nV=aPv2.Index();
288         if (nV==nVD) {
289           aLPBOut.Append(aPBSe);
290           continue;
291         }
292       }
293     }
294   }
295 }
296 //=======================================================================
297 // function:  FillPaveSet
298 // purpose: 
299 //=======================================================================
300   void NMTTools_DEProcessor::FillPaveSet (const Standard_Integer nED,
301                                           const Standard_Integer nVD,
302                                           const Standard_Integer nFD,
303                                           const BOPTools_ListOfPaveBlock& aLPB)
304 {
305   Standard_Boolean bIsDone, bXDir, bRejectFlag;
306   Standard_Integer nE, aNbPoints, j;
307   Standard_Real aTD1, aTD2, aT1, aT2, aTolInter, aX, aDT, aXx;
308   gp_Pnt2d aP2d1, aP2d2, aP2D;
309   gp_Lin2d aLDE;
310   //
311   aDT=Precision::PConfusion();
312   //
313   BOPTools_PaveSet& aPaveSet= 
314     (myFiller->ChangePavePool()).ChangeValue(myDS->RefEdge(nED));
315   //
316   // Clear aPaveSet, aSplitEdges
317   aPaveSet.ChangeSet().Clear();
318   //
319   const TopoDS_Edge aDE=TopoDS::Edge(myDS->Shape(nED));
320   const TopoDS_Face aDF=TopoDS::Face(myDS->Shape(nFD));
321   //
322   // 2D Curve of degenerated edge on the face aDF
323   Handle(Geom2d_Curve) aC2DDE1=BRep_Tool::CurveOnSurface(aDE, aDF, aTD1, aTD2);
324   Handle(Geom2d_TrimmedCurve)aC2DDE=new Geom2d_TrimmedCurve(aC2DDE1, aTD1, aTD2);
325   //
326   // Choose direction for degenerated edge
327   aC2DDE->D0(aTD1, aP2d1);
328   aC2DDE->D0(aTD2, aP2d2);
329
330   bXDir=Standard_False;
331   if (fabs(aP2d1.Y()-aP2d2.Y()) < aDT){
332     bXDir=!bXDir;
333   }
334   //
335   // Prepare bounding Paves
336   BOPTools_Pave aPave1 (nVD, aTD1, BooleanOperations_UnknownInterference);
337   aPaveSet.Append(aPave1);
338   BOPTools_Pave aPave2 (nVD, aTD2, BooleanOperations_UnknownInterference);
339   aPaveSet.Append(aPave2);
340   //
341   // Fill other paves 
342   BOPTools_ListIteratorOfListOfPaveBlock anIt(aLPB);
343   for (; anIt.More(); anIt.Next()) {
344     const BOPTools_PaveBlock& aPB=anIt.Value();
345     nE=aPB.Edge();
346     const TopoDS_Edge aE=TopoDS::Edge(myDS->Shape(nE));
347     
348     Handle(Geom2d_Curve) aC2D=BRep_Tool::CurveOnSurface(aE, aDF, aT1, aT2);
349     //
350     // Intersection
351     Geom2dAdaptor_Curve aGAC1, aGAC2;
352     //
353     aGAC1.Load(aC2DDE, aTD1, aTD2);
354     Handle(Geom2d_Line) aL2D= Handle(Geom2d_Line)::DownCast(aC2D);
355     if (!aL2D.IsNull()) {
356       aGAC2.Load(aC2D);
357     }
358     else {
359       aGAC2.Load(aC2D, aT1, aT2);
360     }
361     //
362     aTolInter=0.001;
363     Geom2dInt_GInter aGInter(aGAC1, aGAC2, aTolInter, aTolInter);
364     bIsDone=aGInter.IsDone();
365     if(bIsDone) {
366       aNbPoints=aGInter.NbPoints();
367       if (aNbPoints) { 
368         for (j=1; j<=aNbPoints; ++j) {
369           aP2D=aGInter.Point(j).Value();
370           Handle(Geom2d_Line) aCLDE;
371           //
372           //modified by NIZNHY-PKV Thu Mar 20 17:37:32 2008f
373           Handle(Geom2d_TrimmedCurve) aCLDET1=
374             Handle(Geom2d_TrimmedCurve)::DownCast(aC2DDE1);
375           if (aCLDET1.IsNull()) {
376             aCLDE=Handle(Geom2d_Line)::DownCast(aC2DDE1);
377           }
378           else {
379             Handle(Geom2d_Curve) aBasisCurve=aCLDET1->BasisCurve();
380             aCLDE=Handle(Geom2d_Line)::DownCast(aBasisCurve);
381           }
382           //aCLDE=Handle(Geom2d_Line)::DownCast(aC2DDE1);
383           //modified by NIZNHY-PKV Thu Mar 20 17:37:37 2008t
384           
385           if (aCLDE.IsNull()) {
386             continue;
387           }
388
389           aLDE=aCLDE->Lin2d();
390           aX=ElCLib::Parameter(aLDE, aP2D);
391           //
392           if (fabs (aX-aTD1) < aDT || fabs (aX-aTD2) < aDT) {
393             continue; 
394           }
395           if (aX < aTD1 || aX > aTD2) {
396             continue; 
397           }
398           //
399           bRejectFlag=Standard_False;
400           const BOPTools_ListOfPave& aListOfPave=aPaveSet.Set();
401           BOPTools_ListIteratorOfListOfPave aPaveIt(aListOfPave);
402           for (; aPaveIt.More(); aPaveIt.Next()) {
403             const BOPTools_Pave& aPavex=aPaveIt.Value();
404             aXx=aPavex.Param();
405             if (fabs (aX-aXx) < aDT) {
406               bRejectFlag=Standard_True;
407               break;
408             }
409           }
410           if (bRejectFlag) {
411             continue; 
412           }
413           //
414           BOPTools_Pave aPave(nVD, aX, BooleanOperations_UnknownInterference);
415           aPaveSet.Append(aPave);
416         }
417       }
418     }
419   }
420 }
421 //=======================================================================
422 // function:  FillSplitEdgesPool
423 // purpose: 
424 //=======================================================================
425   void NMTTools_DEProcessor::FillSplitEdgesPool (const Standard_Integer nED)
426 {
427   BOPTools_SplitShapesPool& aSplitShapesPool=
428     myFiller->ChangeSplitShapesPool();
429   BOPTools_ListOfPaveBlock& aSplitEdges=
430     aSplitShapesPool.ChangeValue(myDS->RefEdge(nED));
431   //
432   aSplitEdges.Clear();
433   //
434   const BOPTools_PavePool& aPavePool=myFiller->PavePool();
435   BOPTools_PavePool* pPavePool=(BOPTools_PavePool*) &aPavePool;
436   BOPTools_PaveSet& aPaveSet= pPavePool->ChangeValue(myDS->RefEdge(nED));
437   
438   BOPTools_PaveBlockIterator aPBIt(nED, aPaveSet);
439   for (; aPBIt.More(); aPBIt.Next()) {
440     BOPTools_PaveBlock& aPB=aPBIt.Value();
441     aSplitEdges.Append(aPB);
442   }
443 }
444 //=======================================================================
445 // function:  MakeSplitEdges
446 // purpose: 
447 //=======================================================================
448   void NMTTools_DEProcessor::MakeSplitEdges (const Standard_Integer nED,
449                                              const Standard_Integer nFD)
450 {
451   const BOPTools_SplitShapesPool& aSplitShapesPool=myFiller->SplitShapesPool();
452   const BOPTools_ListOfPaveBlock& aSplitEdges=aSplitShapesPool(myDS->RefEdge(nED));
453
454   Standard_Integer nV1, nV2, aNewShapeIndex;
455   Standard_Real    t1, t2;
456   TopoDS_Edge aE, aESplit;
457   TopoDS_Vertex aV1, aV2;
458
459   const TopoDS_Edge aDE=TopoDS::Edge(myDS->Shape(nED));
460   const TopoDS_Face aDF=TopoDS::Face(myDS->Shape(nFD));
461
462   BOPTools_ListIteratorOfListOfPaveBlock aPBIt(aSplitEdges);
463
464   for (; aPBIt.More(); aPBIt.Next()) {
465     BOPTools_PaveBlock& aPB=aPBIt.Value();
466     
467     const BOPTools_Pave& aPave1=aPB.Pave1();
468     nV1=aPave1.Index();
469     t1=aPave1.Param();
470     aV1=TopoDS::Vertex(myDS->GetShape(nV1));
471     aV1.Orientation(TopAbs_FORWARD);
472     
473     const BOPTools_Pave& aPave2=aPB.Pave2();
474     nV2=aPave2.Index();
475     t2=aPave2.Param();
476     aV2=TopoDS::Vertex(myDS->GetShape(nV2));
477     aV2.Orientation(TopAbs_REVERSED);
478     
479     MakeSplitEdge(aDE, aDF, aV1, t1, aV2, t2, aESplit); 
480     //
481     // Add Split Part of the Original Edge to the DS
482     BooleanOperations_AncestorsSeqAndSuccessorsSeq anASSeq;
483     
484     anASSeq.SetNewSuccessor(nV1);
485     anASSeq.SetNewOrientation(aV1.Orientation());
486     
487     anASSeq.SetNewSuccessor(nV2);
488     anASSeq.SetNewOrientation(aV2.Orientation());
489     
490     myDS->InsertShapeAndAncestorsSuccessors(aESplit, anASSeq);
491     aNewShapeIndex=myDS->NumberOfInsertedShapes();
492     myDS->SetState(aNewShapeIndex, BooleanOperations_UNKNOWN);
493     //
494     // Fill Split Set for the Original Edge
495     aPB.SetEdge(aNewShapeIndex);
496     //
497   }
498 }
499 //=======================================================================
500 // function:  MakeSplitEdge
501 // purpose: 
502 //=======================================================================
503   void NMTTools_DEProcessor::MakeSplitEdge (const TopoDS_Edge&   aE,
504                                             const TopoDS_Face&   aF,
505                                             const TopoDS_Vertex& aV1,
506                                             const Standard_Real  aP1,
507                                             const TopoDS_Vertex& aV2,
508                                             const Standard_Real  aP2,
509                                             TopoDS_Edge& aNewEdge)
510 {
511   Standard_Real aTol=1.e-7;
512
513   TopoDS_Edge E=aE;
514
515   E.EmptyCopy();
516   BRep_Builder BB;
517   BB.Add  (E, aV1);
518   BB.Add  (E, aV2);
519
520   BB.Range(E, aF, aP1, aP2);
521
522   BB.Degenerated(E, Standard_True);
523
524   BB.UpdateEdge(E, aTol);
525   aNewEdge=E;
526 }
527