9ed2175c49a3f617db602e83f245435448cd99d3
[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 under
7 // the terms of the GNU Lesser General Public License 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
16 #include <BOPTools_AlgoTools.hxx>
17 #include <BRep_Builder.hxx>
18 #include <BRep_Tool.hxx>
19 #include <BRepAdaptor_Curve.hxx>
20 #include <BRepBuilderAPI_MakeEdge.hxx>
21 #include <Geom_Curve.hxx>
22 #include <GeomAbs_CurveType.hxx>
23 #include <gp_Pnt.hxx>
24 #include <IntTools_Context.hxx>
25 #include <IntTools_Curve.hxx>
26 #include <IntTools_Range.hxx>
27 #include <Precision.hxx>
28 #include <TopoDS.hxx>
29 #include <TopoDS_Edge.hxx>
30 #include <TopoDS_Face.hxx>
31 #include <TopoDS_Iterator.hxx>
32 #include <TopoDS_Shape.hxx>
33 #include <TopoDS_Shell.hxx>
34 #include <TopoDS_Solid.hxx>
35 #include <TopoDS_Vertex.hxx>
36
37 static
38   void TreatCompound(const TopoDS_Shape& theC1, 
39                      TopTools_ListOfShape& theLSX);
40
41 //=======================================================================
42 // function: UpdateVertex
43 // purpose: 
44 //=======================================================================
45 void BOPTools_AlgoTools::UpdateVertex
46   (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   GeomAdaptor_Curve aCA( BRep_Tool::Curve(aE, aFirst, aLast) );
80   aCA.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   GeomAdaptor_Curve aCA( aC.Curve() );
103   aCA.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: CopyEdge
137 // purpose: 
138 //=======================================================================
139 TopoDS_Edge BOPTools_AlgoTools::CopyEdge(const TopoDS_Edge& theEdge)
140 {
141   TopoDS_Edge aNewEdge = TopoDS::Edge(theEdge.Oriented(TopAbs_FORWARD));
142   aNewEdge.EmptyCopy();
143   for (TopoDS_Iterator it(theEdge, Standard_False); it.More(); it.Next())
144     BRep_Builder().Add(aNewEdge, it.Value());
145   aNewEdge.Orientation(theEdge.Orientation());
146   return aNewEdge;
147 }
148
149 //=======================================================================
150 // function: MakeSplitEdge
151 // purpose: 
152 //=======================================================================
153 void BOPTools_AlgoTools::MakeSplitEdge(const TopoDS_Edge&   aE,
154                                        const TopoDS_Vertex& aV1,
155                                        const Standard_Real  aP1,
156                                        const TopoDS_Vertex& aV2,
157                                        const Standard_Real  aP2,
158                                        TopoDS_Edge& aNewEdge)
159 {
160   TopoDS_Edge E = TopoDS::Edge(aE.Oriented(TopAbs_FORWARD));
161   E.EmptyCopy();
162   //
163   BRep_Builder BB;
164   if (!aV1.IsNull()) {
165     if (aP1 < aP2) {
166       BB.Add (E, TopoDS::Vertex(aV1.Oriented(TopAbs_FORWARD)));
167     }
168     else {
169       BB.Add (E, TopoDS::Vertex(aV1.Oriented(TopAbs_REVERSED)));
170     }
171   }
172   if (!aV2.IsNull()) {
173     if (aP1 < aP2) {
174       BB.Add (E, TopoDS::Vertex(aV2.Oriented(TopAbs_REVERSED)));
175     }
176     else {
177       BB.Add (E, TopoDS::Vertex(aV2.Oriented(TopAbs_FORWARD)));
178     }
179   }
180   
181   if (aP1 < aP2) {
182     BB.Range(E, aP1, aP2);
183   }
184   else {
185     BB.Range(E, aP2, aP1);
186   }
187   
188   aNewEdge=E;
189   aNewEdge.Orientation(aE.Orientation());
190 }
191
192 //=======================================================================
193 // function: MakeNewVertex
194 // purpose: 
195 //=======================================================================
196 void BOPTools_AlgoTools::MakeNewVertex(const TopoDS_Vertex& aV1,
197                                        const TopoDS_Vertex& aV2,
198                                        TopoDS_Vertex& aNewVertex)
199 {
200   gp_Pnt aPnt1=BRep_Tool::Pnt(aV1);
201   Standard_Real aTol1=BRep_Tool::Tolerance(aV1);
202         
203   gp_Pnt aPnt2=BRep_Tool::Pnt(aV2);
204   Standard_Real aTol2=BRep_Tool::Tolerance(aV2);
205
206   Standard_Real aMaxTol, aDist;
207         
208   aDist=aPnt1.Distance(aPnt2);
209   aMaxTol=(aTol1>aTol2)? aTol1 : aTol2;
210   aMaxTol=aMaxTol+0.5*aDist;
211         
212   const gp_XYZ& aXYZ1=aPnt1.XYZ();
213   const gp_XYZ& aXYZ2=aPnt2.XYZ();
214   gp_XYZ aNewXYZ=0.5*(aXYZ1+aXYZ2);
215         
216   gp_Pnt aNewPnt(aNewXYZ);
217   BRep_Builder aBB;
218   aBB.MakeVertex (aNewVertex, aNewPnt, aMaxTol);
219 }
220  //=======================================================================
221 // function: MakeNewVertex
222 // purpose: 
223 //=======================================================================
224 void BOPTools_AlgoTools::MakeNewVertex(const gp_Pnt& aP,
225                                        const Standard_Real aTol,
226                                        TopoDS_Vertex& aNewVertex)
227 {
228   BRep_Builder aBB;
229   aBB.MakeVertex (aNewVertex, aP, aTol);
230 }
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_Edge& aE2,
239                                        const Standard_Real aParm2,
240                                        TopoDS_Vertex& aNewVertex)
241 {
242   Standard_Real aTol1, aTol2, aMaxTol, aDist; 
243   gp_Pnt aPnt1, aPnt2;
244
245   PointOnEdge (aE1, aParm1, aPnt1);
246   PointOnEdge (aE2, aParm2, aPnt2);
247
248   aTol1=BRep_Tool::Tolerance(aE1);
249   aTol2=BRep_Tool::Tolerance(aE2);
250   
251   aDist=aPnt1.Distance(aPnt2);
252   aMaxTol=(aTol1>aTol2)? aTol1 : aTol2;
253   aMaxTol=aMaxTol+0.5*aDist;
254
255   const gp_XYZ& aXYZ1=aPnt1.XYZ();
256   const gp_XYZ& aXYZ2=aPnt2.XYZ();
257   gp_XYZ aNewXYZ=0.5*(aXYZ1+aXYZ2);
258         
259   gp_Pnt aNewPnt(aNewXYZ);
260   BRep_Builder aBB;
261   aBB.MakeVertex (aNewVertex, aNewPnt, aMaxTol);
262 }
263 //=======================================================================
264 // function: MakeNewVertex
265 // purpose: 
266 //=======================================================================
267 void BOPTools_AlgoTools::MakeNewVertex(const TopoDS_Edge& aE1,
268                                        const Standard_Real aParm1,
269                                        const TopoDS_Face& aF1,
270                                        TopoDS_Vertex& aNewVertex)
271 {
272   Standard_Real aTol1, aTol2, aMaxTol, delta=1.e-12; 
273   gp_Pnt aPnt;
274
275   PointOnEdge (aE1, aParm1, aPnt);
276
277   aTol1=BRep_Tool::Tolerance(aE1);
278   aTol2=BRep_Tool::Tolerance(aF1);
279   //
280   //aMaxTol=(aTol1>aTol2)? aTol1 : aTol2;
281   aMaxTol=aTol1+aTol2+delta;
282   //
283   BRep_Builder aBB;
284   aBB.MakeVertex (aNewVertex, aPnt, aMaxTol);
285 }
286
287 //=======================================================================
288 // function: PointOnEdge
289 // purpose: 
290 //=======================================================================
291 void BOPTools_AlgoTools::PointOnEdge(const TopoDS_Edge& aE,
292                                      const Standard_Real aParm,
293                                      gp_Pnt& aPnt)
294 {
295   Standard_Real f, l;
296   Handle(Geom_Curve) C1=BRep_Tool::Curve(aE, f, l);
297   C1->D0(aParm, aPnt);
298 }
299
300 //=======================================================================
301 //function : CorrectRange
302 //purpose  : 
303 //=======================================================================
304 void BOPTools_AlgoTools::CorrectRange(const TopoDS_Edge& aE1,
305                                       const TopoDS_Edge& aE2,
306                                       const IntTools_Range& aSR,
307                                       IntTools_Range& aNewSR)
308 {
309   Standard_Integer i;
310   Standard_Real aRes, aTolE1, aTolE2, aTF, aTL, dT;
311   BRepAdaptor_Curve aBC;
312   GeomAbs_CurveType aCT;
313   gp_Pnt aP;
314   gp_Vec aDer;
315   //
316   aNewSR=aSR;
317   //
318   aBC.Initialize(aE1);
319   aCT=aBC.GetType();
320   if (aCT==GeomAbs_Line) {
321     return;
322   }
323   //
324   dT=Precision::PConfusion();
325   aTF=aSR.First();
326   aTL=aSR.Last();
327   //
328   aTolE1=BRep_Tool::Tolerance(aE1);
329   aTolE2=BRep_Tool::Tolerance(aE2);
330   //
331   for(i=0; i<2; ++i) {
332     aRes = 2.*(aTolE1 + aTolE2);
333     //
334     if (aCT==GeomAbs_BezierCurve ||
335         aCT==GeomAbs_BSplineCurve||
336         aCT==GeomAbs_OffsetCurve ||
337         aCT==GeomAbs_OtherCurve) {
338       
339       if(!i){
340         aBC.D1 (aTF, aP, aDer);
341       }
342       else {
343         aBC.D1 (aTL, aP, aDer);
344       }
345       //
346       Standard_Real aMgn = aDer.Magnitude();
347       
348       if(aMgn  > 1.e-12) {
349         aRes = aRes/aMgn ;
350       }
351       else {
352         aRes = aBC.Resolution(aRes);
353       }
354     } // if (aCT==GeomAbs_BezierCurve||...
355     else {
356       aRes = aBC.Resolution(aRes);
357     }
358     //
359     if(!i) {
360       aNewSR.SetFirst (aTF+aRes);
361     }
362     else {
363       aNewSR.SetLast (aTL-aRes);
364     }
365     //
366     if ((aNewSR.Last()-aNewSR.First()) < dT) {
367       aNewSR=aSR;
368     }
369     //aNewSR=((aNewSR.Last()-aNewSR.First()) < dT) ? aSR : aNewSR;
370   }
371 }
372                                     
373 //=======================================================================
374 //function : CorrectRange
375 //purpose  : 
376 //=======================================================================
377 void BOPTools_AlgoTools::CorrectRange(const TopoDS_Edge& aE,
378                                       const TopoDS_Face& aF,
379                                       const IntTools_Range& aSR,
380                                       IntTools_Range& aNewSR)
381 {
382   Standard_Integer i;
383   Standard_Real aRes, aTolF, aTF, aTL, dT;
384   BRepAdaptor_Curve aBC;
385   GeomAbs_CurveType aCT;
386   gp_Pnt aP;
387   gp_Vec aDer;
388   //
389   aNewSR=aSR;
390   //
391   dT=Precision::PConfusion();
392   aTF=aSR.First();
393   aTL=aSR.Last();
394   //
395   aBC.Initialize(aE);
396   aCT=aBC.GetType();
397   //
398   aTolF=BRep_Tool::Tolerance(aF);
399   //
400   for(i=0; i<2; ++i) {
401     aRes =aTolF;
402
403     if (aCT==GeomAbs_BezierCurve ||
404         aCT==GeomAbs_BSplineCurve||
405         aCT==GeomAbs_OffsetCurve ||
406         aCT==GeomAbs_OtherCurve) {
407       
408       if(!i){
409         aBC.D1 (aTF, aP, aDer);
410       }
411       else {
412         aBC.D1 (aTL, aP, aDer);
413       }
414       //
415       Standard_Real aMgn = aDer.Magnitude();
416       
417       if(aMgn  > 1.e-12) {
418         aRes = aRes/aMgn ;
419       }
420       else {
421         aRes = aBC.Resolution(aRes);
422       }
423     } // if (aCT==GeomAbs_BezierCurve||...
424     else {
425       aRes = aBC.Resolution(aRes);
426     }
427     //
428     if(!i) {
429       aNewSR.SetFirst (aTF+aRes);
430     }
431     else {
432       aNewSR.SetLast (aTL-aRes);
433     }
434     //
435     if ((aNewSR.Last()-aNewSR.First()) < dT) {
436       aNewSR=aSR;
437     }
438   }
439 }
440 //=======================================================================
441 //function : Dimension
442 //purpose  : 
443 //=======================================================================
444 Standard_Integer BOPTools_AlgoTools::Dimension(const TopoDS_Shape& theS)
445 {
446   Standard_Integer i, iRet, iRx0 = 0, iRx = 0;
447   TopAbs_ShapeEnum aTS;
448   TopTools_ListOfShape aLS;
449   TopTools_ListIteratorOfListOfShape aIt;
450   //
451   aTS=theS.ShapeType();
452   if (aTS!=TopAbs_COMPOUND) {
453     switch (aTS) {
454       case TopAbs_EDGE:
455       case TopAbs_WIRE:
456         iRet=1;
457         break;
458       case TopAbs_FACE:
459       case TopAbs_SHELL:
460         iRet=2;
461         break;
462       case TopAbs_SOLID:
463       case TopAbs_COMPSOLID:
464         iRet=3;
465         break;
466       default:
467         iRet=0;
468     }
469     return iRet;
470   }
471   //
472   iRet=-1;
473   TreatCompound(theS, aLS);
474   if(aLS.IsEmpty()) {
475     iRet = -2; //empty compound
476     return iRet;
477   }
478   aIt.Initialize(aLS);
479   for (i=0; aIt.More(); aIt.Next()) {
480     const TopoDS_Shape& aSx=aIt.Value(); 
481     iRx=Dimension(aSx);
482     if (!i) {
483       iRx0=iRx;
484       i=1;
485       continue;
486     }
487     if (iRx!=iRx0) {
488       return iRet;// -1
489     }
490   }
491   return iRx;
492 }
493
494 //=======================================================================
495 //function : TreatCompound
496 //purpose  : 
497 //=======================================================================
498 void TreatCompound(const TopoDS_Shape& theC1, 
499                    TopTools_ListOfShape& theLSX)
500 {
501   Standard_Integer aNbC1;
502   TopAbs_ShapeEnum aType;
503   TopTools_ListOfShape aLC, aLC1;
504   TopTools_ListIteratorOfListOfShape aIt, aIt1;
505   TopoDS_Iterator aItC;
506   //
507   aLC.Append (theC1);
508   for(;;) {
509     aLC1.Clear();
510     aIt.Initialize(aLC);
511     for (; aIt.More(); aIt.Next()) {
512       const TopoDS_Shape& aC=aIt.Value(); //C is compound
513       //
514       aItC.Initialize(aC);
515       for (; aItC.More(); aItC.Next()) {
516         const TopoDS_Shape& aS=aItC.Value();
517         aType=aS.ShapeType();
518         if (aType==TopAbs_COMPOUND) {
519           aLC1.Append(aS);
520         }
521         else {
522           theLSX.Append(aS);
523         }
524       }
525     }
526     //
527     aNbC1=aLC1.Extent();
528     if (!aNbC1) {
529       break;
530     }
531     //
532     aLC.Clear();
533     aIt.Initialize(aLC1);
534     for (; aIt.More(); aIt.Next()) {
535       const TopoDS_Shape& aSC=aIt.Value();
536       aLC.Append(aSC);
537     }
538   }// while(1)
539 }