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