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