32a36ee01335ae48c4e2bcaaea2a2b9dd125affb
[occt.git] / src / BOPTools / BOPTools_AlgoTools_2.cxx
1 // Created by: Peter KURNEV
2 // Copyright (c) 1999-2014 OPEN CASCADE SAS
3 //
4 // This file is part of Open CASCADE Technology software library.
5 //
6 // This library is free software; you can redistribute it and / or modify it
7 // under the terms of the GNU Lesser General Public version 2.1 as published
8 // by the Free Software Foundation, with special exception defined in the file
9 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
10 // distribution for complete text of the license and disclaimer of any warranty.
11 //
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
14
15 #include <BOPTools_AlgoTools.ixx>
16
17 #include <Precision.hxx>
18
19 #include <TopoDS.hxx>
20 #include <TopoDS_Vertex.hxx>
21 #include <TopoDS_Edge.hxx>
22
23 #include <gp_Pnt.hxx>
24
25 #include <Geom_Curve.hxx>
26 #include <IntTools_Curve.hxx>
27 #include <BRepBuilderAPI_MakeEdge.hxx>
28 #include <BRepAdaptor_Curve.hxx>
29 #include <GeomAbs_CurveType.hxx>
30
31 #include <BRep_Tool.hxx>
32 #include <BRep_Builder.hxx>
33 #include <TopoDS_Iterator.hxx>
34
35 static
36   void TreatCompound(const TopoDS_Shape& theC1, 
37                      BOPCol_ListOfShape& theLSX);
38
39 //=======================================================================
40 // function: UpdateVertex
41 // purpose: 
42 //=======================================================================
43   void BOPTools_AlgoTools::UpdateVertex (const TopoDS_Vertex& aVF,
44                                      const TopoDS_Vertex& aNewVertex)
45 {
46   Standard_Real aTolVF, aTolNewVertex, aDist, aDTol=1.e-12, aNewTol;
47   //
48   gp_Pnt aPVF=BRep_Tool::Pnt(aVF);
49   gp_Pnt aPNewVertex=BRep_Tool::Pnt(aNewVertex);
50   aTolVF=BRep_Tool::Tolerance(aVF);
51   aTolNewVertex=BRep_Tool::Tolerance(aNewVertex);
52
53   aDist=aPVF.Distance(aPNewVertex);
54   aNewTol=aDist+aTolNewVertex;
55
56   if (aNewTol>aTolVF) {
57     BRep_Builder BB;
58     BB.UpdateVertex (aVF, aNewTol+aDTol);
59   }
60 }
61
62 //=======================================================================
63 // function: UpdateVertex
64 // purpose: 
65 //=======================================================================
66   void BOPTools_AlgoTools::UpdateVertex (const TopoDS_Edge& aE,
67                                      const Standard_Real  aT,
68                                      const TopoDS_Vertex& aV)
69 {
70   Standard_Real aTolV, aDist, aDTol=1.e-12, aFirst, aLast;
71   gp_Pnt  aPc; 
72
73   gp_Pnt aPv=BRep_Tool::Pnt(aV);
74   aTolV=BRep_Tool::Tolerance(aV);
75
76   Handle(Geom_Curve) aC3D=BRep_Tool::Curve(aE, aFirst, aLast);
77   aC3D->D0(aT, aPc);
78   aDist=aPv.Distance(aPc);
79   if (aDist>aTolV) {
80     BRep_Builder BB;
81     BB.UpdateVertex (aV, aDist+aDTol);
82   }
83 }
84 //
85 //=======================================================================
86 // function: UpdateVertex
87 // purpose: 
88 //=======================================================================
89   void BOPTools_AlgoTools::UpdateVertex (const IntTools_Curve& aC,
90                                      const Standard_Real  aT,
91                                      const TopoDS_Vertex& aV)
92 {
93   Standard_Real aTolV, aDist, aDTol=1.e-12;
94   gp_Pnt  aPc; 
95
96   gp_Pnt aPv=BRep_Tool::Pnt(aV);
97   aTolV=BRep_Tool::Tolerance(aV);
98
99   Handle(Geom_Curve) aC3D=aC.Curve();
100   aC3D->D0(aT, aPc);
101   aDist=aPv.Distance(aPc);
102   if (aDist>aTolV) {
103     BRep_Builder BB;
104     BB.UpdateVertex (aV, aDist+aDTol);
105   }
106 }
107 //=======================================================================
108 // function: MakeSectEdge
109 // purpose: 
110 //=======================================================================
111   void BOPTools_AlgoTools::MakeSectEdge(const IntTools_Curve& aIC,
112                                      const TopoDS_Vertex& aV1,
113                                      const Standard_Real  aP1,
114                                      const TopoDS_Vertex& aV2,
115                                      const Standard_Real  aP2,
116                                      TopoDS_Edge& aNewEdge)
117 {
118   Handle(Geom_Curve) aC=aIC.Curve ();
119   
120   BRepBuilderAPI_MakeEdge aMakeEdge(aC, aV1, aV2, aP1, aP2);
121   
122   const TopoDS_Edge& aE=TopoDS::Edge(aMakeEdge.Shape());
123   //
124   // Range must be as it was !
125   BRep_Builder aBB;
126   aBB.Range (aE, aP1, aP2);
127   //
128   aNewEdge=aE;
129   
130 }
131
132 //=======================================================================
133 // function: MakeSplitEdge
134 // purpose: 
135 //=======================================================================
136   void BOPTools_AlgoTools::MakeSplitEdge(const TopoDS_Edge&   aE,
137                                      const TopoDS_Vertex& aV1,
138                                      const Standard_Real  aP1,
139                                      const TopoDS_Vertex& aV2,
140                                      const Standard_Real  aP2,
141                                      TopoDS_Edge& aNewEdge)
142 {
143   Standard_Real f, l, aTol;
144   Handle(Geom_Curve) aC=BRep_Tool::Curve (aE, f, l);
145   aTol=BRep_Tool::Tolerance(aE);
146   //
147   // MakeEdge is used for chechking all input data only 
148   BRepBuilderAPI_MakeEdge aMakeEdge(aC, aV1, aV2, aP1, aP2);
149   //ZZ const TopoDS_Edge& E1=TopoDS::Edge(aMakeEdge.Shape());
150   TopoDS_Edge E=aE;
151   E.EmptyCopy();
152
153   BRep_Builder BB;
154   BB.Add  (E, aV1);
155   BB.Add  (E, aV2);
156   BB.Range(E, aP1, aP2);
157   BB.UpdateEdge(E, aTol);
158   aNewEdge=E;
159 }
160
161 //=======================================================================
162 // function: MakeNewVertex
163 // purpose: 
164 //=======================================================================
165   void BOPTools_AlgoTools::MakeNewVertex(const TopoDS_Vertex& aV1,
166                                      const TopoDS_Vertex& aV2,
167                                      TopoDS_Vertex& aNewVertex)
168 {
169   gp_Pnt aPnt1=BRep_Tool::Pnt(aV1);
170   Standard_Real aTol1=BRep_Tool::Tolerance(aV1);
171         
172   gp_Pnt aPnt2=BRep_Tool::Pnt(aV2);
173   Standard_Real aTol2=BRep_Tool::Tolerance(aV2);
174
175   Standard_Real aMaxTol, aDist;
176         
177   aDist=aPnt1.Distance(aPnt2);
178   aMaxTol=(aTol1>aTol2)? aTol1 : aTol2;
179   aMaxTol=aMaxTol+0.5*aDist;
180         
181   const gp_XYZ& aXYZ1=aPnt1.XYZ();
182   const gp_XYZ& aXYZ2=aPnt2.XYZ();
183   gp_XYZ aNewXYZ=0.5*(aXYZ1+aXYZ2);
184         
185   gp_Pnt aNewPnt(aNewXYZ);
186   BRep_Builder aBB;
187   aBB.MakeVertex (aNewVertex, aNewPnt, aMaxTol);
188 }
189  //=======================================================================
190 // function: MakeNewVertex
191 // purpose: 
192 //=======================================================================
193   void BOPTools_AlgoTools::MakeNewVertex(const gp_Pnt& aP,
194                                      const Standard_Real aTol,
195                                      TopoDS_Vertex& aNewVertex)
196 {
197   BRep_Builder aBB;
198   aBB.MakeVertex (aNewVertex, aP, aTol);
199 }
200
201 //=======================================================================
202 // function: MakeNewVertex
203 // purpose: 
204 //=======================================================================
205   void BOPTools_AlgoTools::MakeNewVertex(const TopoDS_Edge& aE1,
206                                      const Standard_Real aParm1,
207                                      const TopoDS_Edge& aE2,
208                                      const Standard_Real aParm2,
209                                      TopoDS_Vertex& aNewVertex)
210 {
211   Standard_Real aTol1, aTol2, aMaxTol, aDist; 
212   gp_Pnt aPnt1, aPnt2;
213
214   PointOnEdge (aE1, aParm1, aPnt1);
215   PointOnEdge (aE2, aParm2, aPnt2);
216
217   aTol1=BRep_Tool::Tolerance(aE1);
218   aTol2=BRep_Tool::Tolerance(aE2);
219   
220   aDist=aPnt1.Distance(aPnt2);
221   aMaxTol=(aTol1>aTol2)? aTol1 : aTol2;
222   aMaxTol=aMaxTol+0.5*aDist;
223
224   const gp_XYZ& aXYZ1=aPnt1.XYZ();
225   const gp_XYZ& aXYZ2=aPnt2.XYZ();
226   gp_XYZ aNewXYZ=0.5*(aXYZ1+aXYZ2);
227         
228   gp_Pnt aNewPnt(aNewXYZ);
229   BRep_Builder aBB;
230   aBB.MakeVertex (aNewVertex, aNewPnt, aMaxTol);
231 }
232 //=======================================================================
233 // function: MakeNewVertex
234 // purpose: 
235 //=======================================================================
236   void BOPTools_AlgoTools::MakeNewVertex(const TopoDS_Edge& aE1,
237                                      const Standard_Real aParm1,
238                                      const TopoDS_Face& aF1,
239                                      TopoDS_Vertex& aNewVertex)
240 {
241   Standard_Real aTol1, aTol2, aMaxTol, delta=1.e-12; 
242   gp_Pnt aPnt;
243
244   PointOnEdge (aE1, aParm1, aPnt);
245
246   aTol1=BRep_Tool::Tolerance(aE1);
247   aTol2=BRep_Tool::Tolerance(aF1);
248   //
249   //aMaxTol=(aTol1>aTol2)? aTol1 : aTol2;
250   aMaxTol=aTol1+aTol2+delta;
251   //
252   BRep_Builder aBB;
253   aBB.MakeVertex (aNewVertex, aPnt, aMaxTol);
254 }
255
256 //=======================================================================
257 // function: PointOnEdge
258 // purpose: 
259 //=======================================================================
260   void BOPTools_AlgoTools::PointOnEdge(const TopoDS_Edge& aE,
261                                    const Standard_Real aParm,
262                                    gp_Pnt& aPnt)
263 {
264   Standard_Real f, l;
265   Handle(Geom_Curve) C1=BRep_Tool::Curve(aE, f, l);
266   C1->D0(aParm, aPnt);
267 }
268
269 //=======================================================================
270 //function : CorrectRange
271 //purpose  : 
272 //=======================================================================
273   void BOPTools_AlgoTools::CorrectRange(const TopoDS_Edge& aE1,
274                                     const TopoDS_Edge& aE2,
275                                     const IntTools_Range& aSR,
276                                     IntTools_Range& aNewSR)
277 {
278   Standard_Integer i;
279   Standard_Real aRes, aTolE1, aTolE2, aTF, aTL, dT;
280   BRepAdaptor_Curve aBC;
281   GeomAbs_CurveType aCT;
282   gp_Pnt aP;
283   gp_Vec aDer;
284   //
285   aNewSR=aSR;
286   //
287   aBC.Initialize(aE1);
288   aCT=aBC.GetType();
289   if (aCT==GeomAbs_Line) {
290     return;
291   }
292   //
293   dT=Precision::PConfusion();
294   aTF=aSR.First();
295   aTL=aSR.Last();
296   //
297   aTolE1=BRep_Tool::Tolerance(aE1);
298   aTolE2=BRep_Tool::Tolerance(aE2);
299   //
300   for(i=0; i<2; ++i) {
301     aRes = 2.*(aTolE1 + aTolE2);
302     //
303     if (aCT==GeomAbs_BezierCurve ||
304         aCT==GeomAbs_BSplineCurve||
305         aCT==GeomAbs_OtherCurve) {
306       
307       if(!i){
308         aBC.D1 (aTF, aP, aDer);
309       }
310       else {
311         aBC.D1 (aTL, aP, aDer);
312       }
313       //
314       Standard_Real aMgn = aDer.Magnitude();
315       
316       if(aMgn  > 1.e-12) {
317         aRes = aRes/aMgn ;
318       }
319       else {
320         aRes = aBC.Resolution(aRes);
321       }
322     } // if (aCT==GeomAbs_BezierCurve||...
323     else {
324       aRes = aBC.Resolution(aRes);
325     }
326     //
327     if(!i) {
328       aNewSR.SetFirst (aTF+aRes);
329     }
330     else {
331       aNewSR.SetLast (aTL-aRes);
332     }
333     //
334     if ((aNewSR.Last()-aNewSR.First()) < dT) {
335       aNewSR=aSR;
336     }
337     //aNewSR=((aNewSR.Last()-aNewSR.First()) < dT) ? aSR : aNewSR;
338   }
339 }
340                                     
341 //=======================================================================
342 //function : CorrectRange
343 //purpose  : 
344 //=======================================================================
345   void BOPTools_AlgoTools::CorrectRange(const TopoDS_Edge& aE,
346                                     const TopoDS_Face& aF,
347                                     const IntTools_Range& aSR,
348                                     IntTools_Range& aNewSR)
349 {
350   Standard_Integer i;
351   Standard_Real aRes, aTolF, aTF, aTL, dT;
352   BRepAdaptor_Curve aBC;
353   GeomAbs_CurveType aCT;
354   gp_Pnt aP;
355   gp_Vec aDer;
356   //
357   aNewSR=aSR;
358   //
359   dT=Precision::PConfusion();
360   aTF=aSR.First();
361   aTL=aSR.Last();
362   //
363   aBC.Initialize(aE);
364   aCT=aBC.GetType();
365   //
366   aTolF=BRep_Tool::Tolerance(aF);
367   //
368   for(i=0; i<2; ++i) {
369     aRes =aTolF;
370
371     if (aCT==GeomAbs_BezierCurve ||
372         aCT==GeomAbs_BSplineCurve||
373         aCT==GeomAbs_OtherCurve) {
374       
375       if(!i){
376         aBC.D1 (aTF, aP, aDer);
377       }
378       else {
379         aBC.D1 (aTL, aP, aDer);
380       }
381       //
382       Standard_Real aMgn = aDer.Magnitude();
383       
384       if(aMgn  > 1.e-12) {
385         aRes = aRes/aMgn ;
386       }
387       else {
388         aRes = aBC.Resolution(aRes);
389       }
390     } // if (aCT==GeomAbs_BezierCurve||...
391     else {
392       aRes = aBC.Resolution(aRes);
393     }
394     //
395     if(!i) {
396       aNewSR.SetFirst (aTF+aRes);
397     }
398     else {
399       aNewSR.SetLast (aTL-aRes);
400     }
401     //
402     if ((aNewSR.Last()-aNewSR.First()) < dT) {
403       aNewSR=aSR;
404     }
405   }
406 }
407 //=======================================================================
408 //function : Dimension
409 //purpose  : 
410 //=======================================================================
411   Standard_Integer BOPTools_AlgoTools::Dimension(const TopoDS_Shape& theS)
412 {
413   Standard_Integer i, iRet, iRx0 = 0, iRx = 0;
414   TopAbs_ShapeEnum aTS;
415   BOPCol_ListOfShape aLS;
416   BOPCol_ListIteratorOfListOfShape aIt;
417   //
418   aTS=theS.ShapeType();
419   if (aTS!=TopAbs_COMPOUND) {
420     switch (aTS) {
421       case TopAbs_EDGE:
422       case TopAbs_WIRE:
423         iRet=1;
424         break;
425       case TopAbs_FACE:
426       case TopAbs_SHELL:
427         iRet=2;
428         break;
429       case TopAbs_SOLID:
430       case TopAbs_COMPSOLID:
431         iRet=3;
432         break;
433       default:
434         iRet=0;
435     }
436     return iRet;
437   }
438   //
439   iRet=-1;
440   TreatCompound(theS, aLS);
441   if(aLS.IsEmpty()) {
442     iRet = -2; //empty compound
443     return iRet;
444   }
445   aIt.Initialize(aLS);
446   for (i=0; aIt.More(); aIt.Next()) {
447     const TopoDS_Shape& aSx=aIt.Value(); 
448     iRx=Dimension(aSx);
449     if (!i) {
450       iRx0=iRx;
451       i=1;
452       continue;
453     }
454     if (iRx!=iRx0) {
455       return iRet;// -1
456     }
457   }
458   return iRx;
459 }
460
461 //=======================================================================
462 //function : TreatCompound
463 //purpose  : 
464 //=======================================================================
465   void TreatCompound(const TopoDS_Shape& theC1, 
466                      BOPCol_ListOfShape& theLSX)
467 {
468   Standard_Integer aNbC1;
469   TopAbs_ShapeEnum aType;
470   BOPCol_ListOfShape aLC, aLC1;
471   BOPCol_ListIteratorOfListOfShape aIt, aIt1;
472   TopoDS_Iterator aItC;
473   //
474   aLC.Append (theC1);
475   for(;;) {
476     aLC1.Clear();
477     aIt.Initialize(aLC);
478     for (; aIt.More(); aIt.Next()) {
479       const TopoDS_Shape& aC=aIt.Value(); //C is compound
480       //
481       aItC.Initialize(aC);
482       for (; aItC.More(); aItC.Next()) {
483         const TopoDS_Shape& aS=aItC.Value();
484         aType=aS.ShapeType();
485         if (aType==TopAbs_COMPOUND) {
486           aLC1.Append(aS);
487         }
488         else {
489           theLSX.Append(aS);
490         }
491       }
492     }
493     //
494     aNbC1=aLC1.Extent();
495     if (!aNbC1) {
496       break;
497     }
498     //
499     aLC.Clear();
500     aIt.Initialize(aLC1);
501     for (; aIt.More(); aIt.Next()) {
502       const TopoDS_Shape& aSC=aIt.Value();
503       aLC.Append(aSC);
504     }
505   }// while(1)
506 }