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