0023884: Boolean Fuse between two faces fails
[occt.git] / src / IntTools / IntTools_Tools.cxx
1 // Created on: 2000-11-16
2 // Created by: Peter KURNEV
3 // Copyright (c) 2000-2014 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
7 // This library is free software; you can redistribute it and / or modify it
8 // under the terms of the GNU Lesser General Public version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16 #include <IntTools_Tools.ixx>
17
18 #include <Precision.hxx>
19
20 #include <TopExp_Explorer.hxx>
21 #include <TopTools_IndexedDataMapOfShapeShape.hxx>
22
23 #include <TopoDS.hxx>
24 #include <TopoDS_Shape.hxx>
25 #include <TopoDS_Vertex.hxx>
26 #include <TopoDS_Edge.hxx>
27 #include <TopoDS_Face.hxx>
28 #include <TopoDS_Wire.hxx>
29 #include <TopLoc_Location.hxx>
30
31 #include <BRep_Builder.hxx>
32 #include <BRep_Tool.hxx>
33 #include <BRepAdaptor_Surface.hxx>
34 #include <BRepAdaptor_Curve.hxx>
35 #include <BRepAdaptor_Surface.hxx>
36
37 #include <gp_Pnt.hxx>
38 #include <gp_Pnt2d.hxx>
39 #include <gp.hxx>
40 #include <gp_Lin.hxx>
41 #include <gp_Dir.hxx>
42 #include <gp_Ax1.hxx>
43
44 #include <Geom_Curve.hxx>
45 #include <GeomAdaptor_Surface.hxx>
46 #include <Geom_Surface.hxx>
47 #include <GeomAPI_ProjectPointOnSurf.hxx>
48 #include <GeomAPI_ProjectPointOnCurve.hxx>
49 #include <GeomAdaptor_Curve.hxx>
50 #include <GeomAbs_CurveType.hxx>
51 #include <Geom_Line.hxx>
52 #include <Geom2d_Curve.hxx>
53 #include <Geom_BoundedCurve.hxx>
54 #include <Geom_Geometry.hxx>
55 #include <Geom_TrimmedCurve.hxx>
56 #include <Geom2d_TrimmedCurve.hxx>
57
58 #include <IntTools_FClass2d.hxx>
59 #include <IntTools_Curve.hxx>
60 #include <IntTools_SequenceOfCurves.hxx>
61
62 static
63   void ParabolaTolerance(const Handle(Geom_Curve)& ,
64                          const Standard_Real ,
65                          const Standard_Real ,
66                          const Standard_Real ,
67                          Standard_Real& ,
68                          Standard_Real& );
69
70 //=======================================================================
71 //function : HasInternalEdge
72 //purpose  : 
73 //=======================================================================
74   Standard_Boolean IntTools_Tools::HasInternalEdge(const TopoDS_Wire& aW)
75 {
76   Standard_Boolean bFlag=Standard_True;
77
78   TopExp_Explorer anExp(aW, TopAbs_EDGE);
79   for (; anExp.More(); anExp.Next()) {
80     const TopoDS_Edge& aE=TopoDS::Edge(anExp.Current());
81     TopAbs_Orientation anOr=aE.Orientation();
82     if (anOr==TopAbs_INTERNAL) {
83       return bFlag;
84     }
85   }
86   return !bFlag;
87 }
88
89 //=======================================================================
90 //function : IsClosed
91 //purpose  : 
92 //=======================================================================
93   Standard_Boolean IntTools_Tools::IsClosed (const Handle(Geom_Curve)& aC3D)
94 {
95   Standard_Boolean bRet;
96   Standard_Real aF, aL, aDist, aPC;
97   gp_Pnt aP1, aP2;
98   
99   Handle (Geom_BoundedCurve) aGBC=
100       Handle (Geom_BoundedCurve)::DownCast(aC3D);
101   if (aGBC.IsNull()) {
102     return Standard_False;
103   }
104   
105   aF=aC3D->FirstParameter();
106   aL=aC3D-> LastParameter();
107   
108   aC3D->D0(aF, aP1);
109   aC3D->D0(aL, aP2);
110
111   
112   //
113   //modified by NIZNHY-PKV Mon Jul 04 11:58:23 2011f
114   aPC=Precision::Confusion();
115   aPC=aPC*aPC;
116   aDist=aP1.SquareDistance(aP2);
117   bRet=aDist<aPC;
118   return bRet;
119   //
120   //aDist=aP1.Distance(aP2);
121   //return (aDist < Precision::Confusion()); 
122   //modified by NIZNHY-PKV Mon Jul 04 11:59:50 2011t
123 }
124
125 //=======================================================================
126 //function : RejectLines
127 //purpose  : 
128 //=======================================================================
129    void IntTools_Tools::RejectLines(const IntTools_SequenceOfCurves& aSIn,
130                                     IntTools_SequenceOfCurves& aSOut)
131 {
132   Standard_Integer i, j, aNb;
133   Standard_Boolean bFlag;
134   Handle (Geom_Curve) aC3D;
135
136   gp_Dir aD1, aD2;
137
138   aSOut.Clear();
139
140   aNb=aSIn.Length();
141   for (i=1; i<=aNb; i++) {
142     const IntTools_Curve& IC=aSIn(i);
143     aC3D=IC.Curve();
144     //
145     Handle (Geom_TrimmedCurve) aGTC=
146       Handle (Geom_TrimmedCurve)::DownCast(aC3D);
147     
148     if (!aGTC.IsNull()) {
149       aC3D=aGTC->BasisCurve();
150       IntTools_Curve* pIC=(IntTools_Curve*) &IC;
151       pIC->SetCurve(aC3D);
152     }
153     //
154     Handle (Geom_Line) aGLine=
155       Handle (Geom_Line)::DownCast(aC3D);
156     
157     if (aGLine.IsNull()) {
158       aSOut.Clear();
159       for (j=1; j<=aNb; j++) {
160         aSOut.Append(aSIn(j));
161       }
162       return;
163     }
164     //
165     gp_Lin aLin=aGLine->Lin();
166     aD2=aLin.Direction();
167     if (i==1) {
168       aSOut.Append(IC);
169       aD1=aD2;
170       continue;
171     }
172     
173     bFlag=IntTools_Tools::IsDirsCoinside(aD1, aD2);
174     if (!bFlag) {
175       aSOut.Append(IC);
176       return;
177     }
178   }
179 }
180
181 //=======================================================================
182 //function : IsDirsCoinside
183 //purpose  : 
184 //=======================================================================
185   Standard_Boolean IntTools_Tools::IsDirsCoinside  (const gp_Dir& D1, const gp_Dir& D2)
186 {
187   Standard_Boolean bFlag;
188   gp_Pnt P1(D1.X(), D1.Y(), D1.Z());  
189   gp_Pnt P2(D2.X(), D2.Y(), D2.Z());
190   Standard_Real dLim=0.0002, d;
191   d=P1.Distance (P2); 
192   bFlag= (d<dLim || fabs (2.-d)<dLim); 
193   return bFlag;
194 }
195   
196 //=======================================================================
197 //function : IsDirsCoinside
198 //purpose  : 
199 //=======================================================================
200   Standard_Boolean IntTools_Tools::IsDirsCoinside  (const gp_Dir& D1, 
201                                                     const gp_Dir& D2,
202                                                     const Standard_Real dLim)
203 {
204   Standard_Boolean bFlag;
205   Standard_Real d;
206   //
207   gp_Pnt P1(D1.X(), D1.Y(), D1.Z());  
208   gp_Pnt P2(D2.X(), D2.Y(), D2.Z());
209   d=P1.Distance (P2); 
210   bFlag= (d<dLim || fabs (2.-d)<dLim); 
211   return bFlag;
212 }
213 //=======================================================================
214 //function : SplitCurve
215 //purpose  : 
216 //=======================================================================
217   Standard_Integer IntTools_Tools::SplitCurve(const IntTools_Curve& IC,
218                                               IntTools_SequenceOfCurves& aCvs)
219 {
220   Handle (Geom_Curve) aC3D =IC.Curve();
221   if(aC3D.IsNull())
222     return 0;
223   //
224   Handle (Geom2d_Curve) aC2D1=IC.FirstCurve2d();
225   Handle (Geom2d_Curve) aC2D2=IC.SecondCurve2d();
226   Standard_Boolean bIsClosed;
227
228   bIsClosed=IntTools_Tools::IsClosed(aC3D);
229   if (!bIsClosed) {
230     return 0;
231   }
232
233   Standard_Real aF, aL, aMid;
234   
235   //
236   aF=aC3D->FirstParameter();
237   aL=aC3D->LastParameter();
238   aMid=0.5*(aF+aL);
239   GeomAdaptor_Curve aGAC(aC3D);
240   GeomAbs_CurveType aCT=aGAC.GetType();
241   if (aCT==GeomAbs_BSplineCurve ||
242       aCT==GeomAbs_BezierCurve) {
243     //aMid=0.5*aMid;
244     aMid=IntTools_Tools::IntermediatePoint(aF, aL);
245   }
246   //
247   Handle(Geom_Curve) aC3DNewF, aC3DNewL;
248   aC3DNewF =new Geom_TrimmedCurve  (aC3D, aF, aMid);
249   aC3DNewL =new Geom_TrimmedCurve  (aC3D, aMid, aL);
250
251   //
252   Handle (Geom2d_Curve) aC2D1F, aC2D1L, aC2D2F, aC2D2L;
253   //
254   if(!aC2D1.IsNull()) {
255     aC2D1F=new Geom2d_TrimmedCurve (aC2D1, aF, aMid);
256     aC2D1L=new Geom2d_TrimmedCurve (aC2D1, aMid, aL);
257   }
258
259   if(!aC2D2.IsNull()) {
260     aC2D2F=new Geom2d_TrimmedCurve (aC2D2, aF, aMid);
261     aC2D2L=new Geom2d_TrimmedCurve (aC2D2, aMid, aL);
262   }
263   // 
264   
265   IntTools_Curve aIC1(aC3DNewF, aC2D1F, aC2D2F);
266   IntTools_Curve aIC2(aC3DNewL, aC2D1L, aC2D2L);
267   //
268   aCvs.Append(aIC1);
269   //
270   aCvs.Append(aIC2);
271   //
272   return 2;
273 }
274
275 //=======================================================================
276 //function : IntermediatePoint
277 //purpose  : 
278 //=======================================================================
279   Standard_Real IntTools_Tools::IntermediatePoint (const Standard_Real aFirst,
280                                                    const Standard_Real aLast)
281 {
282   //define parameter division number as 10*e^(-M_PI) = 0.43213918
283   const Standard_Real PAR_T = 0.43213918;
284   Standard_Real aParm;
285   aParm=(1.-PAR_T)*aFirst + PAR_T*aLast;
286   return aParm;
287 }
288
289 //=======================================================================
290 //function : IsVertex
291 //purpose  : 
292 //=======================================================================
293   Standard_Boolean IntTools_Tools::IsVertex (const gp_Pnt& aP,
294                                              const Standard_Real aTolPV,
295                                              const TopoDS_Vertex& aV)
296 {
297   Standard_Boolean bRet;
298   Standard_Real aTolV, aD, dTol;
299   gp_Pnt aPv; 
300   
301   aTolV=BRep_Tool::Tolerance(aV);
302   //
303   dTol=Precision::Confusion();
304   aTolV=aTolV+aTolPV+dTol;
305   //
306   aPv=BRep_Tool::Pnt(aV);
307   //
308   //modified by NIZNHY-PKV Mon Jul 04 12:00:37 2011f
309   aD=aPv.SquareDistance(aP);
310   aTolV=aTolV*aTolV;
311   bRet=(aD<=aTolV);
312   return bRet;
313   //
314   //aD=aPv.Distance(aP);
315   //return (aD<=aTolV);
316   //modified by NIZNHY-PKV Mon Jul 04 12:00:40 2011t
317 }
318
319
320 //=======================================================================
321 //function : IsVertex
322 //purpose  : 
323 //=======================================================================
324   Standard_Boolean IntTools_Tools::IsVertex (const IntTools_CommonPrt& aCmnPrt)
325 {
326   Standard_Boolean anIsVertex;
327   Standard_Real aParam;
328
329   const TopoDS_Edge&    aE1=aCmnPrt.Edge1();
330   const IntTools_Range& aR1=aCmnPrt.Range1();
331   aParam=0.5*(aR1.First()+aR1.Last());
332   anIsVertex=IntTools_Tools::IsVertex (aE1, aParam);
333   
334   if (anIsVertex) {
335     return Standard_True;
336   }
337
338   const TopoDS_Edge&    aE2=aCmnPrt.Edge2();
339   const IntTools_SequenceOfRanges& aRs2=aCmnPrt.Ranges2();
340   const IntTools_Range& aR2=aRs2(1);
341   aParam=0.5*(aR2.First()+aR2.Last());
342   anIsVertex=IntTools_Tools::IsVertex (aE2, aParam);
343   if (anIsVertex) {
344     return Standard_True;
345   }
346   return Standard_False;
347 }
348
349 //=======================================================================
350 //function : IsVertex
351 //purpose  : 
352 //=======================================================================
353   Standard_Boolean IntTools_Tools::IsVertex (const TopoDS_Edge& aE,
354                                              const TopoDS_Vertex& aV,
355                                              const Standard_Real t)
356 {
357   Standard_Real aTolV, aTolV2, d2;
358   gp_Pnt aPv, aPt; 
359   
360   BRepAdaptor_Curve aBAC(aE);
361   aBAC.D0(t, aPt);
362
363   aTolV=BRep_Tool::Tolerance(aV);
364   aTolV2=aTolV*aTolV;
365   aPv=BRep_Tool::Pnt(aV);
366   d2=aPv.SquareDistance (aPt);
367   if (d2 < aTolV2) {
368     return Standard_True;
369   }
370   return Standard_False;
371 }
372 //=======================================================================
373 //function : IsVertex
374 //purpose  : 
375 //=======================================================================
376   Standard_Boolean IntTools_Tools::IsVertex (const TopoDS_Edge& aE,
377                                              const Standard_Real t)
378 {
379   Standard_Real aTolV, aTolV2, d2;
380   TopoDS_Vertex aV;
381   gp_Pnt aPv, aPt; 
382   
383   BRepAdaptor_Curve aBAC(aE);
384   aBAC.D0(t, aPt);
385
386   TopExp_Explorer anExp(aE, TopAbs_VERTEX);
387   for (; anExp.More(); anExp.Next()) {
388     aV=TopoDS::Vertex (anExp.Current());
389     aTolV=BRep_Tool::Tolerance(aV);
390     aTolV2=aTolV*aTolV;
391     aTolV2=1.e-12;
392      aPv=BRep_Tool::Pnt(aV);
393      d2=aPv.SquareDistance (aPt);
394      if (d2 < aTolV2) {
395        return Standard_True;
396      }
397   }
398   return Standard_False;
399 }
400
401
402 //=======================================================================
403 //function : ComputeVV
404 //purpose  : 
405 //=======================================================================
406   Standard_Integer IntTools_Tools::ComputeVV(const TopoDS_Vertex& aV1, 
407                                              const TopoDS_Vertex& aV2)
408 {
409   Standard_Real aTolV1, aTolV2, aTolSum, d;
410   gp_Pnt aP1, aP2;
411
412   aTolV1=BRep_Tool::Tolerance(aV1);
413   aTolV2=BRep_Tool::Tolerance(aV2);
414   aTolSum=aTolV1+aTolV2;
415   
416   aP1=BRep_Tool::Pnt(aV1);
417   aP2=BRep_Tool::Pnt(aV2);
418   //modified by NIZNHY-PKV Mon Jul 04 11:55:52 2011f
419   aTolSum=aTolSum*aTolSum;
420   d=aP1.SquareDistance(aP2);
421   //d=aP1.Distance(aP2);
422   //modified by NIZNHY-PKV Mon Jul 04 11:55:53 2011t
423   if (d<aTolSum) {
424     return 0;
425   }
426   return -1;
427 }
428
429 //=======================================================================
430 //function : MakeFaceFromWireAndFace
431 //purpose  : 
432 //=======================================================================
433   void IntTools_Tools::MakeFaceFromWireAndFace(const TopoDS_Wire& aW,
434                                                const TopoDS_Face& aF,
435                                                TopoDS_Face& aFNew)
436 {
437   TopoDS_Face aFF;
438   aFF=aF;
439   aFF.Orientation(TopAbs_FORWARD);
440   aFNew=TopoDS::Face (aFF.EmptyCopied());
441   BRep_Builder BB;
442   BB.Add(aFNew, aW);
443 }
444
445 //=======================================================================
446 //function : ClassifyPointByFace
447 //purpose  : 
448 //=======================================================================
449   TopAbs_State IntTools_Tools::ClassifyPointByFace(const TopoDS_Face& aF,
450                                                    const gp_Pnt2d& aP2d)
451 {
452   Standard_Real aFaceTolerance;
453   TopAbs_State aState;
454   
455   aFaceTolerance=BRep_Tool::Tolerance(aF);
456   IntTools_FClass2d aClass2d(aF, aFaceTolerance);
457   aState=aClass2d.Perform(aP2d);
458   
459   return aState;
460 }
461
462 //=======================================================================
463 //function : IsMiddlePointsEqual
464 //purpose  : 
465 //=======================================================================
466   Standard_Boolean IntTools_Tools::IsMiddlePointsEqual(const TopoDS_Edge& aE1,
467                                                        const TopoDS_Edge& aE2)
468                                                        
469 {
470   Standard_Boolean bRet;
471   Standard_Real f1, l1, m1, f2, l2, m2, aTol1, aTol2, aSumTol, aD2;
472   gp_Pnt aP1, aP2;
473
474   aTol1=BRep_Tool::Tolerance(aE1);
475   Handle(Geom_Curve) C1=BRep_Tool::Curve(aE1, f1, l1);
476   m1=0.5*(f1+l1);
477   C1->D0(m1, aP1);
478
479   aTol2=BRep_Tool::Tolerance(aE2);
480   Handle(Geom_Curve) C2=BRep_Tool::Curve(aE2, f2, l2);
481   m2=0.5*(f2+l2);
482   C2->D0(m2, aP2);
483
484   aSumTol=aTol1+aTol2;
485   //modified by NIZNHY-PKV Mon Jul 04 12:02:20 2011f
486   aSumTol=aSumTol*aSumTol;
487   aD2=aP1.SquareDistance(aP2);
488   bRet=aD2<aSumTol;
489   return bRet;
490   //
491   //if (aP1.Distance(aP2) < aSumTol) {
492   //  return Standard_True;
493   //}
494   //return Standard_False;
495   //modified by NIZNHY-PKV Mon Jul 04 12:02:24 2011t
496 }
497
498 //=======================================================================
499 //function : CurveTolerance
500 //purpose  : 
501 //=======================================================================
502   Standard_Real IntTools_Tools::CurveTolerance(const Handle(Geom_Curve)& aC3D,
503                                                const Standard_Real aTolBase)
504 {
505   Standard_Real aTolReached, aTf, aTl, aTolMin, aTolMax;
506
507   aTolReached=aTolBase;
508   //
509   if (aC3D.IsNull()) {
510     return aTolReached;
511   }
512   //
513   Handle(Geom_TrimmedCurve) aCT3D=Handle(Geom_TrimmedCurve)::DownCast(aC3D);
514   if (aCT3D.IsNull()) {
515     return aTolReached;
516   }
517   //
518   aTolMin=aTolBase;
519   aTolMax=aTolBase;
520   //
521   aTf=aCT3D->FirstParameter();
522   aTl=aCT3D->LastParameter();
523   //
524   GeomAdaptor_Curve aGAC(aCT3D);
525   GeomAbs_CurveType aCType=aGAC.GetType();
526   //
527   if (aCType==GeomAbs_Parabola) {
528     Handle(Geom_Curve) aC3DBase=aCT3D->BasisCurve();
529     ParabolaTolerance(aC3DBase, aTf, aTl, aTolBase, aTolMin, aTolMax);
530     aTolReached=aTolMax;
531   }
532   //
533   return aTolReached;
534 }
535
536 #include <Geom_Parabola.hxx>
537 #include <gp_Parab.hxx>
538 //=======================================================================
539 //function : ParabolaTolerance
540 //purpose  : 
541 //=======================================================================
542 void ParabolaTolerance(const Handle(Geom_Curve)& aC3D,
543                        const Standard_Real aTf,
544                        const Standard_Real aTl,
545                        const Standard_Real aTol,
546                        Standard_Real& aTolMin,
547                        Standard_Real& aTolMax)
548 {
549   
550   aTolMin=aTol;
551   aTolMax=aTol;
552
553   Handle(Geom_Parabola) aGP=Handle(Geom_Parabola)::DownCast(aC3D);
554   if (aGP.IsNull()){
555     return;
556   }
557
558   Standard_Integer aNbPoints;
559   Standard_Real aFocal, aX1, aX2, aTol1, aTol2;
560   gp_Pnt aPf, aPl;
561   gp_Parab aParab=aGP->Parab();
562   gp_Ax1 aXAxis=aParab.XAxis();
563   Handle(Geom_Line) aGAxis=new Geom_Line(aXAxis);
564
565   aFocal=aGP->Focal();
566   if (aFocal==0.) {
567     return;
568   }
569   //
570   // aTol1
571   aTol1=aTol;
572   aX1=0.;
573   aGP->D0(aTf, aPf);
574   GeomAPI_ProjectPointOnCurve aProj1(aPf, aGAxis);
575   aNbPoints=aProj1.NbPoints();
576   if (aNbPoints) {
577     aX1=aProj1.LowerDistanceParameter();
578   }
579   if (aX1>=0.) {
580     aTol1=aTol*sqrt(0.5*aX1/aFocal);
581   }
582   if (aTol1==0.) {
583     aTol1=aTol;
584   }
585   //
586   // aTol2
587   aTol2=aTol;
588   aX2=0.;
589   aGP->D0(aTl, aPl);
590   GeomAPI_ProjectPointOnCurve aProj2(aPl, aGAxis);
591   aNbPoints=aProj2.NbPoints();
592   if (aNbPoints) {
593     aX2=aProj2.LowerDistanceParameter();
594   }
595   
596   if (aX2>=0.) {
597     aTol2=aTol*sqrt(0.5*aX2/aFocal);
598   }
599   if (aTol2==0.) {
600     aTol2=aTol;
601   }
602   //
603   aTolMax=(aTol1>aTol2) ? aTol1 : aTol2;
604   aTolMin=(aTol1<aTol2) ? aTol1 : aTol2;
605 }
606