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