0026738: Make Boolean operations safely treating arguments when running with fuzzy...
[occt.git] / src / IntTools / IntTools_EdgeFace.cxx
1 // Created on: 2001-02-26
2 // Created by: Peter KURNEV
3 // Copyright (c) 2001-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 under
8 // the terms of the GNU Lesser General Public License 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
17 #include <Bnd_Box.hxx>
18 #include <BndLib_AddSurface.hxx>
19 #include <BRep_Tool.hxx>
20 #include <BRepAdaptor_Surface.hxx>
21 #include <Extrema_ExtCS.hxx>
22 #include <Extrema_POnCurv.hxx>
23 #include <Extrema_POnSurf.hxx>
24 #include <Geom_Curve.hxx>
25 #include <Geom_Surface.hxx>
26 #include <GeomAdaptor_Curve.hxx>
27 #include <GeomAdaptor_HCurve.hxx>
28 #include <GeomAdaptor_HSurface.hxx>
29 #include <GeomAdaptor_Surface.hxx>
30 #include <GeomAPI_ProjectPointOnSurf.hxx>
31 #include <gp_Ax1.hxx>
32 #include <gp_Circ.hxx>
33 #include <gp_Cone.hxx>
34 #include <gp_Cylinder.hxx>
35 #include <gp_Lin.hxx>
36 #include <gp_Pln.hxx>
37 #include <gp_Pnt.hxx>
38 #include <gp_Torus.hxx>
39 #include <IntCurveSurface_HInter.hxx>
40 #include <IntCurveSurface_IntersectionPoint.hxx>
41 #include <IntTools.hxx>
42 #include <IntTools_Array1OfRange.hxx>
43 #include <IntTools_BeanFaceIntersector.hxx>
44 #include <IntTools_CArray1OfInteger.hxx>
45 #include <IntTools_CArray1OfReal.hxx>
46 #include <IntTools_CommonPrt.hxx>
47 #include <IntTools_Context.hxx>
48 #include <IntTools_EdgeFace.hxx>
49 #include <IntTools_Range.hxx>
50 #include <IntTools_Root.hxx>
51 #include <IntTools_Tools.hxx>
52 #include <Precision.hxx>
53 #include <TopoDS_Edge.hxx>
54 #include <TopoDS_Face.hxx>
55
56 #include <algorithm>
57 static
58   Standard_Boolean IsCoplanar (const BRepAdaptor_Curve&  ,
59                                const BRepAdaptor_Surface& );
60 static
61   Standard_Boolean IsRadius (const BRepAdaptor_Curve& aCurve ,
62                              const BRepAdaptor_Surface& aSurface,
63                              const Standard_Real aCriteria);
64 static
65   Standard_Integer AdaptiveDiscret (const Standard_Integer iDiscret,
66                                     const BRepAdaptor_Curve& aCurve ,
67                                     const BRepAdaptor_Surface& aSurface);
68
69 //=======================================================================
70 //function : IntTools_EdgeFace::IntTools_EdgeFace
71 //purpose  : 
72 //=======================================================================
73   IntTools_EdgeFace::IntTools_EdgeFace()
74 {
75   myFuzzyValue = Precision::Confusion();
76   myDiscret = 30;
77   myEpsT   =1e-12;
78   myDeflection=0.01;
79   myIsDone=Standard_False;
80   myErrorStatus=1;
81   myQuickCoincidenceCheck=Standard_False;
82 }
83 //=======================================================================
84 //function : SetContext
85 //purpose  : 
86 //=======================================================================
87 void IntTools_EdgeFace::SetContext(const Handle(IntTools_Context)& theContext) 
88 {
89   myContext = theContext;
90 }
91
92 //=======================================================================
93 //function : Context
94 //purpose  : 
95 //=======================================================================
96 const Handle(IntTools_Context)& IntTools_EdgeFace::Context()const 
97 {
98   return myContext;
99 }
100 //=======================================================================
101 //function : SetEdge
102 //purpose  : 
103 //=======================================================================
104 void IntTools_EdgeFace::SetEdge(const TopoDS_Edge& anEdge)
105 {
106   myEdge=anEdge;
107 }
108 //=======================================================================
109 //function : SetFace
110 //purpose  : 
111 //=======================================================================
112 void IntTools_EdgeFace::SetFace(const TopoDS_Face& aFace)
113 {
114   myFace=aFace;
115 }
116 //=======================================================================
117 //function : Edge
118 //purpose  : 
119 //=======================================================================
120 const TopoDS_Edge& IntTools_EdgeFace::Edge()const 
121 {
122   return myEdge;
123 }
124 //=======================================================================
125 //function : Face
126 //purpose  : 
127 //=======================================================================
128 const TopoDS_Face& IntTools_EdgeFace::Face()const 
129 {
130   return myFace;
131 }
132 //=======================================================================
133 //function : SetFuzzyValue
134 //purpose  : 
135 //=======================================================================
136 void IntTools_EdgeFace::SetFuzzyValue(const Standard_Real theFuzz)
137 {
138   myFuzzyValue = Max(theFuzz, Precision::Confusion());
139 }
140 //=======================================================================
141 //function : SetDiscretize
142 //purpose  : 
143 //=======================================================================
144 void IntTools_EdgeFace::SetDiscretize(const Standard_Integer aDiscret)
145 {
146   myDiscret=aDiscret;
147 }
148 //=======================================================================
149 //function : SetDeflection
150 //purpose  : 
151 //=======================================================================
152 void IntTools_EdgeFace::SetDeflection(const Standard_Real aDefl) 
153 {
154   myDeflection=aDefl;
155
156 //=======================================================================
157 //function : SetEpsilonT
158 //purpose  : 
159 //=======================================================================
160 void IntTools_EdgeFace::SetEpsilonT(const Standard_Real anEpsT) 
161 {
162   myEpsT=anEpsT;
163
164 //=======================================================================
165 //function : SetRange
166 //purpose  : 
167 //=======================================================================
168 void IntTools_EdgeFace::SetRange(const Standard_Real aFirst,
169                                  const Standard_Real aLast) 
170 {
171   myRange.SetFirst (aFirst);
172   myRange.SetLast  (aLast);
173
174
175 //=======================================================================
176 //function : SetRange
177 //purpose  : 
178 //=======================================================================
179 void IntTools_EdgeFace::SetRange(const IntTools_Range& aRange) 
180 {
181   SetRange(aRange.First(), aRange.Last());
182
183 //=======================================================================
184 //function : IsDone
185 //purpose  : 
186 //=======================================================================
187 Standard_Boolean IntTools_EdgeFace::IsDone()const 
188 {
189   return myIsDone;
190
191 //=======================================================================
192 //function : ErrorStatus
193 //purpose  : 
194 //=======================================================================
195 Standard_Integer IntTools_EdgeFace::ErrorStatus()const 
196 {
197   return myErrorStatus;
198 }
199 //=======================================================================
200 //function : CommonParts
201 //purpose  : 
202 //=======================================================================
203 const IntTools_SequenceOfCommonPrts& IntTools_EdgeFace::CommonParts() const 
204 {
205   return mySeqOfCommonPrts;
206 }
207 //=======================================================================
208 //function : Range
209 //purpose  : 
210 //=======================================================================
211 const IntTools_Range&  IntTools_EdgeFace::Range() const
212 {
213   return myRange;
214
215 //=======================================================================
216 //function :  IsCoincident
217 //purpose  : 
218 //=======================================================================
219 Standard_Boolean IntTools_EdgeFace::IsCoincident() 
220 {
221   Standard_Integer i, iCnt;
222   Standard_Real dT, aT, aD, aT1, aT2, aU, aV;
223
224   gp_Pnt aP;
225   TopAbs_State aState;
226   gp_Pnt2d aP2d;
227   //
228   GeomAPI_ProjectPointOnSurf& aProjector=myContext->ProjPS(myFace);
229
230   const Standard_Integer aNbSeg=23;
231   const Standard_Real aTresh=0.5;
232   const Standard_Integer aTreshIdxF = RealToInt((aNbSeg+1)*0.25),
233                          aTreshIdxL = RealToInt((aNbSeg+1)*0.75);
234   const Handle(Geom_Surface) aSurf = BRep_Tool::Surface(myFace);
235
236   aT1=myRange.First();
237   aT2=myRange.Last();
238   dT=(aT2-aT1)/aNbSeg;
239   //
240   Standard_Boolean isClassified = Standard_False;
241   iCnt=0;
242   for(i=0; i <= aNbSeg; ++i) {
243     aT = aT1+i*dT;
244     aP=myC.Value(aT);
245     //
246     aProjector.Perform(aP);
247     if (!aProjector.IsDone()) {
248       continue;
249     }
250     //
251     
252     aD=aProjector.LowerDistance();
253     if (aD>myCriteria) {
254       continue;
255     }
256     //
257
258     ++iCnt; 
259
260     //We classify only three points: in the begin, in the 
261     //end and in the middle of the edge.
262     //However, exact middle point (when i == (aNbSeg + 1)/2)
263     //can be unprojectable. Therefore, it will not be able to
264     //be classified. Therefore, points with indexes in 
265     //[aTreshIdxF, aTreshIdxL] range are made available 
266     //for classification.
267     //isClassified == TRUE if MIDDLE point has been choosen and
268     //classified correctly.
269
270     if(((0 < i) && (i < aTreshIdxF)) || ((aTreshIdxL < i ) && (i < aNbSeg)))
271       continue;
272
273     if(isClassified && (i != aNbSeg))
274       continue;
275
276     aProjector.LowerDistanceParameters(aU, aV);
277     aP2d.SetX(aU);
278     aP2d.SetY(aV);
279
280     IntTools_FClass2d& aClass2d=myContext->FClass2d(myFace);
281     aState = aClass2d.Perform(aP2d);
282     
283     if(aState == TopAbs_OUT)
284       return Standard_False;
285
286     if(i != 0)
287       isClassified = Standard_True;
288   }
289   //
290   const Standard_Real aCoeff=(Standard_Real)iCnt/((Standard_Real)aNbSeg+1);
291   return (aCoeff > aTresh);
292 }
293 //=======================================================================
294 //function : CheckData
295 //purpose  : 
296 //=======================================================================
297 void IntTools_EdgeFace::CheckData()
298 {
299   if (BRep_Tool::Degenerated(myEdge)) {
300     myErrorStatus=2;
301   }
302   if (!BRep_Tool::IsGeometric(myEdge)) { 
303      myErrorStatus=3;
304   }
305 }
306 //=======================================================================
307 //function : Prepare
308 //purpose  : 
309 //=======================================================================
310 void IntTools_EdgeFace::Prepare() 
311 {
312   Standard_Integer pri;
313   Standard_Real aTmin, aTmax;
314   IntTools_CArray1OfReal aPars;
315  
316   //
317   // 1.Prepare Curve's data and Surface's data
318   myC.Initialize(myEdge);
319   GeomAbs_CurveType aCurveType;
320   aCurveType=myC.GetType();
321   //
322   // 2.Prepare myCriteria
323   Standard_Real aFuzz = myFuzzyValue / 2.;
324   Standard_Real aTolF = BRep_Tool::Tolerance(myFace) + aFuzz;
325   Standard_Real aTolE = BRep_Tool::Tolerance(myEdge) + aFuzz;
326   if (aCurveType == GeomAbs_BSplineCurve ||
327       aCurveType == GeomAbs_BezierCurve) {
328     myCriteria = 1.5*aTolE + aTolF;
329   }
330   else {
331     myCriteria = aTolE + aTolF;
332   }
333   // 2.a myTmin, myTmax
334   aTmin=myRange.First();
335   aTmax=myRange.Last();
336   // 2.b myFClass2d
337   myS.Initialize (myFace,Standard_True);
338   myFClass2d.Init(myFace, 1.e-6);
339   //
340   // 2.c Prepare adaptive myDiscret
341   myDiscret=AdaptiveDiscret(myDiscret, myC, myS);
342   //
343   //
344   // 3.Prepare myPars 
345   pri = IntTools::PrepareArgs(myC, aTmax, aTmin, 
346                               myDiscret, myDeflection, aPars);
347   if (pri) {
348     myErrorStatus=6;
349     return;
350   }
351   // 4.
352   //ProjectableRanges
353   Standard_Integer i, iProj, aNb, aNbProj, ind0, ind1;
354   Standard_Real t0, t1, tRoot;
355   
356   //
357   // Table of Projection's function values
358   aNb=aPars.Length();
359   IntTools_CArray1OfInteger anArrProjectability;
360   anArrProjectability.Resize(aNb);
361   
362   for (iProj=0, i=0; i<aNb; i++) {
363     t0=aPars(i);
364     aNbProj=IsProjectable (t0); 
365     
366     anArrProjectability(i)=0;
367     if (aNbProj) {
368       anArrProjectability(i)=1;
369       iProj++;
370     }
371   }
372   //
373   // Checking
374   if (!iProj ) {
375     myErrorStatus=7;
376     return;
377   }
378   
379   //
380   // Projectable Ranges
381   IntTools_Range aRange;
382   
383   ind0=anArrProjectability(0);
384   if (ind0) {
385     t0=aPars(0);
386     aRange.SetFirst(t0);
387   }
388   
389   for(i=1; i<aNb; i++) {
390     ind1=anArrProjectability(i);
391     t0=aPars(i-1);
392     t1=aPars(i);
393
394     if (i==(aNb-1)) {
395       if (ind1 && ind0) {
396  aRange.SetLast(t1);
397  myProjectableRanges.Append(aRange);
398       }
399       if (ind1 && !ind0) {
400  FindProjectableRoot(t0, t1, ind0, ind1, tRoot);
401  aRange.SetFirst(tRoot);
402  aRange.SetLast(t1);
403  myProjectableRanges.Append(aRange);
404       }
405       //
406       if (ind0 && !ind1) {
407  FindProjectableRoot(t0, t1, ind0, ind1, tRoot);
408  aRange.SetLast(tRoot);
409  myProjectableRanges.Append(aRange);
410       }
411       //
412       break;
413     }
414     
415     if (ind0 != ind1) {
416       FindProjectableRoot(t0, t1, ind0, ind1, tRoot);
417       
418       if (ind0 && !ind1) {
419  aRange.SetLast(tRoot);
420  myProjectableRanges.Append(aRange);
421       }
422       else {
423  aRange.SetFirst(tRoot);
424       }
425     } // if (ind0 != ind1)
426     ind0=ind1;
427   } // for(i=1; i<aNb; i++) {
428 }
429
430 //=======================================================================
431 //function : FindProjectableRoot
432 //purpose  : 
433 //=======================================================================
434   void IntTools_EdgeFace::FindProjectableRoot (const Standard_Real tt1,
435                                                const Standard_Real tt2,
436                                                const Standard_Integer ff1,
437                                                const Standard_Integer /*ff2*/,
438                                                Standard_Real& tRoot)
439 {
440   Standard_Real tm, t1, t2, aEpsT;
441   Standard_Integer anIsProj1, anIsProjm;
442   aEpsT = 0.5 * myEpsT;
443
444   // Root is inside [tt1, tt2]
445   t1 = tt1;
446   t2 = tt2;
447   anIsProj1 =  ff1;
448
449   for(;;)
450   {
451     if (fabs(t1 - t2) < aEpsT)
452     {
453       tRoot = (anIsProj1) ? t1 : t2;
454       return;
455     }
456     tm = 0.5 * (t1 + t2);
457     anIsProjm = IsProjectable(tm);
458
459     if (anIsProjm != anIsProj1)
460     {
461       t2 = tm;
462     }
463     else
464     {
465       t1 = tm;
466       anIsProj1 = anIsProjm;
467     }
468   } // for(;;)
469 }
470 //=======================================================================
471 //function : IsProjectable
472 //purpose  : 
473 //=======================================================================
474 Standard_Boolean IntTools_EdgeFace::IsProjectable
475   (const Standard_Real aT) const
476 {
477   Standard_Boolean bFlag; 
478   gp_Pnt aPC;
479   //
480   myC.D0(aT, aPC);
481   bFlag=myContext->IsValidPointForFace(aPC, myFace, myCriteria);
482   //
483   return bFlag;
484 }
485 //=======================================================================
486 //function : DistanceFunction
487 //purpose  : 
488 //=======================================================================
489 Standard_Real IntTools_EdgeFace::DistanceFunction
490   (const Standard_Real t)
491 {
492   Standard_Real aD;
493
494   //
495   gp_Pnt P;
496   myC.D0(t, P);
497   //
498   Standard_Boolean bIsEqDistance;
499
500   bIsEqDistance= IntTools_EdgeFace::IsEqDistance(P, myS, 1.e-7, aD); 
501   if (bIsEqDistance) {
502     aD=aD-myCriteria;
503     return aD; 
504   }
505   
506   //
507   Standard_Boolean bFlag = Standard_False;
508
509   GeomAPI_ProjectPointOnSurf& aLocProj = myContext->ProjPS(myFace);
510   aLocProj.Perform(P);
511   bFlag = aLocProj.IsDone();
512   
513   if(bFlag) {
514     aD = aLocProj.LowerDistance();
515   }
516   //
517   
518   if (!bFlag) {
519     myErrorStatus=11;
520     return 99.;
521   }
522   
523   // 
524   //   aD=aProjector.LowerDistance();
525   // 
526   aD=aD-myCriteria;
527   return aD; 
528 }
529 //
530 //=======================================================================
531 //function : IsEqDistance
532 //purpose  : 
533 //=======================================================================
534 Standard_Boolean IntTools_EdgeFace::IsEqDistance
535   (const gp_Pnt& aP,
536    const BRepAdaptor_Surface& aBAS,
537    const Standard_Real aTol,
538    Standard_Real& aD)
539 {
540   Standard_Boolean bRetFlag=Standard_True;
541
542   GeomAbs_SurfaceType aSurfType=aBAS.GetType();
543
544   if (aSurfType==GeomAbs_Cylinder) {
545     gp_Cylinder aCyl=aBAS.Cylinder();
546     const gp_Ax1& anAx1  =aCyl.Axis();
547     gp_Lin aLinAxis(anAx1);
548     Standard_Real aDC, aRadius=aCyl.Radius();
549     aDC=aLinAxis.Distance(aP);
550     if (aDC < aTol) {
551       aD=aRadius;
552       return bRetFlag; 
553     }
554   }
555
556   if (aSurfType==GeomAbs_Cone) {
557     gp_Cone aCone=aBAS.Cone();
558     const gp_Ax1& anAx1  =aCone.Axis();
559     gp_Lin aLinAxis(anAx1);
560     Standard_Real aDC, aRadius, aDS, aSemiAngle;
561     aDC=aLinAxis.Distance(aP);
562     if (aDC < aTol) {
563       gp_Pnt anApex=aCone.Apex();
564       aSemiAngle=aCone.SemiAngle();
565       aDS=aP.Distance(anApex);
566       
567       aRadius=aDS*tan(aSemiAngle);
568       aD=aRadius;
569       return bRetFlag; 
570     }
571   }
572
573   if (aSurfType==GeomAbs_Torus) {
574     Standard_Real aMajorRadius, aMinorRadius, aDC;
575
576     gp_Torus aTorus=aBAS.Torus();
577     gp_Pnt aPLoc=aTorus.Location();
578     aMajorRadius=aTorus.MajorRadius();
579     
580     aDC=fabs(aPLoc.Distance(aP)-aMajorRadius);
581     if (aDC < aTol) {
582       aMinorRadius=aTorus.MinorRadius();
583       aD=aMinorRadius;
584       return bRetFlag; 
585     }
586   }
587   return !bRetFlag; 
588 }
589 //
590 //=======================================================================
591 //function : MakeType
592 //purpose  : 
593 //=======================================================================
594 Standard_Integer IntTools_EdgeFace::MakeType
595   (IntTools_CommonPrt&  aCommonPrt)
596 {
597   Standard_Real  af1, al1;
598   Standard_Real  df1, tm;
599   Standard_Boolean bAllNullFlag;
600   //
601   bAllNullFlag=aCommonPrt.AllNullFlag();
602   if (bAllNullFlag) {
603     aCommonPrt.SetType(TopAbs_EDGE);
604     return 0;
605   }
606   //
607   aCommonPrt.Range1(af1, al1);
608
609   {
610     gp_Pnt aPF, aPL;
611     myC.D0(af1, aPF);
612     myC.D0(al1, aPL);
613     df1=aPF.Distance(aPL);
614     Standard_Boolean isWholeRange = Standard_False;
615     
616     if((Abs(af1 - myRange.First()) < myC.Resolution(myCriteria)) &&
617        (Abs(al1 - myRange.Last()) < myC.Resolution(myCriteria)))
618       isWholeRange = Standard_True;
619     
620     
621     if ((df1 > myCriteria * 2.) && isWholeRange) {
622       aCommonPrt.SetType(TopAbs_EDGE);
623     }
624     else {
625       if(isWholeRange) {
626         tm = (af1 + al1) * 0.5;
627         
628         if(aPF.Distance(myC.Value(tm)) > myCriteria * 2.) {
629           aCommonPrt.SetType(TopAbs_EDGE);
630           return 0;
631         }
632       }
633       
634       if(!CheckTouch(aCommonPrt, tm)) {
635         tm = (af1 + al1) * 0.5;
636       }
637       aCommonPrt.SetType(TopAbs_VERTEX);
638       aCommonPrt.SetVertexParameter1(tm);
639       aCommonPrt.SetRange1 (af1, al1);
640     }
641   }
642  return 0;
643 }
644
645
646 //=======================================================================
647 //function : CheckTouch 
648 //purpose  : 
649 //=======================================================================
650 Standard_Boolean IntTools_EdgeFace::CheckTouch
651   (const IntTools_CommonPrt& aCP,
652    Standard_Real&            aTx) 
653 {
654   Standard_Real aTF, aTL, Tol, U1f, U1l, V1f, V1l, af, al,aDist2, aMinDist2;
655   Standard_Boolean theflag=Standard_False;
656   Standard_Integer aNbExt, iLower;
657
658   aCP.Range1(aTF, aTL);
659
660   //
661   Standard_Real aCR;
662   aCR=myC.Resolution(myCriteria);
663   if((Abs(aTF - myRange.First()) < aCR) &&
664      (Abs(aTL - myRange.Last())  < aCR)) {
665     return theflag; // EDGE 
666   }
667   //
668
669   Tol = Precision::PConfusion();
670
671   const Handle(Geom_Curve)&  Curve   =BRep_Tool::Curve  (myC.Edge(), af, al);
672   const Handle(Geom_Surface)& Surface=BRep_Tool::Surface(myS.Face());
673   //   Surface->Bounds(U1f,U1l,V1f,V1l);
674   U1f = myS.FirstUParameter();
675   U1l = myS.LastUParameter();
676   V1f = myS.FirstVParameter();
677   V1l = myS.LastVParameter();
678   
679   GeomAdaptor_Curve   TheCurve   (Curve,aTF, aTL);
680   GeomAdaptor_Surface TheSurface (Surface, U1f, U1l, V1f, V1l); 
681      
682   Extrema_ExtCS anExtrema (TheCurve, TheSurface, Tol, Tol);
683
684   aDist2 = 1.e100;
685
686   if(anExtrema.IsDone()) {
687     aMinDist2 = aDist2;
688
689     if(!anExtrema.IsParallel()) {
690       aNbExt=anExtrema.NbExt();
691       
692       if(aNbExt > 0) {
693  iLower=1;
694  for (Standard_Integer i=1; i<=aNbExt; i++) {
695    aDist2=anExtrema.SquareDistance(i);
696    if (aDist2 < aMinDist2) {
697      aMinDist2=aDist2;
698      iLower=i;
699    }
700  }
701  aDist2=anExtrema.SquareDistance(iLower);
702  Extrema_POnCurv aPOnC;
703  Extrema_POnSurf aPOnS;
704  anExtrema.Points(iLower, aPOnC, aPOnS);
705  aTx=aPOnC.Parameter();
706       }
707       else {
708  // modified by NIZHNY-MKK  Thu Jul 21 11:35:32 2005.BEGIN
709  IntCurveSurface_HInter anExactIntersector;
710   
711  Handle(GeomAdaptor_HCurve) aCurve     = new GeomAdaptor_HCurve(TheCurve);
712  Handle(GeomAdaptor_HSurface) aSurface = new GeomAdaptor_HSurface(TheSurface);
713  
714  anExactIntersector.Perform(aCurve, aSurface);
715
716  if(anExactIntersector.IsDone()) {
717    for(Standard_Integer i = 1; i <= anExactIntersector.NbPoints(); i++) {
718      const IntCurveSurface_IntersectionPoint& aPoint = anExactIntersector.Point(i);
719       
720      if((aPoint.W() >= aTF) && (aPoint.W() <= aTL)) {
721        aDist2=0.;
722        aTx = aPoint.W();
723      }
724    }
725  }
726  // modified by NIZHNY-MKK  Thu Jul 21 11:35:40 2005.END
727       }
728     }
729     else {
730       return theflag;
731     }
732   }
733
734   Standard_Real aBoundaryDist;
735
736   aBoundaryDist = DistanceFunction(aTF) + myCriteria;
737   if(aBoundaryDist * aBoundaryDist < aDist2) {
738     aDist2 = aBoundaryDist * aBoundaryDist;
739     aTx = aTF;
740   }
741   
742   aBoundaryDist = DistanceFunction(aTL) + myCriteria;
743   if(aBoundaryDist * aBoundaryDist < aDist2) {
744     aDist2 = aBoundaryDist * aBoundaryDist;
745     aTx = aTL;
746   }
747
748   Standard_Real aParameter = (aTF + aTL) * 0.5;
749   aBoundaryDist = DistanceFunction(aParameter) + myCriteria;
750   if(aBoundaryDist * aBoundaryDist < aDist2) {
751     aDist2 = aBoundaryDist * aBoundaryDist;
752     aTx = aParameter;
753   }
754
755   if(aDist2 > myCriteria * myCriteria) {
756     return theflag;
757   }
758   
759   if (fabs (aTx-aTF) < myEpsT) {
760     return !theflag;
761   }
762
763   if (fabs (aTx-aTL) < myEpsT) {
764     return !theflag;
765   }
766
767   if (aTx>aTF && aTx<aTL) {
768     return !theflag;
769   }
770
771   return theflag;
772 }
773
774 //=======================================================================
775 //function : Perform
776 //purpose  : 
777 //=======================================================================
778 void IntTools_EdgeFace::Perform() 
779 {
780   Standard_Integer i, aNb;
781   IntTools_CommonPrt aCommonPrt;
782   //
783   aCommonPrt.SetEdge1(myEdge);
784   //
785   myErrorStatus=0;
786   CheckData();
787   if (myErrorStatus) {
788     return;
789   }
790   //
791   if (myContext.IsNull()) {
792     myContext=new IntTools_Context;
793   }
794   //
795   myIsDone = Standard_False;
796   myC.Initialize(myEdge);
797   GeomAbs_CurveType aCurveType;
798   aCurveType=myC.GetType();
799   //
800   // Prepare myCriteria
801   Standard_Real aFuzz = myFuzzyValue / 2.;
802   Standard_Real aTolF = BRep_Tool::Tolerance(myFace) + aFuzz;
803   Standard_Real aTolE = BRep_Tool::Tolerance(myEdge) + aFuzz;
804   if (aCurveType == GeomAbs_BSplineCurve ||
805       aCurveType==GeomAbs_BezierCurve) {
806     //--- 5112
807     Standard_Real diff1 = (aTolE/aTolF);
808     Standard_Real diff2 = (aTolF/aTolE);
809     if( diff1 > 100 || diff2 > 100 ) {
810       myCriteria = Max(aTolE,aTolF);
811     }
812     else //--- 5112
813       myCriteria = 1.5*aTolE + aTolF;
814   }
815   else {
816     myCriteria = aTolE + aTolF;
817   }
818   
819   myS.Initialize (myFace,Standard_True);
820   
821   if(myContext.IsNull()) {
822     myFClass2d.Init(myFace, 1.e-6);
823   }
824   //
825   if (myQuickCoincidenceCheck) {
826     if (IsCoincident()) {
827       aCommonPrt.SetType(TopAbs_EDGE);
828       aCommonPrt.SetRange1(myRange.First(), myRange.Last());
829       MakeType (aCommonPrt); 
830       mySeqOfCommonPrts.Append(aCommonPrt);
831       myIsDone=Standard_True;
832       return;
833     }
834   }
835   //
836   IntTools_BeanFaceIntersector anIntersector(myC, myS, aTolE, aTolF);
837   anIntersector.SetBeanParameters(myRange.First(), myRange.Last());
838   //
839   anIntersector.SetContext(myContext);
840   //
841   anIntersector.Perform();
842   
843   if(!anIntersector.IsDone()) {
844     return;
845   }
846   
847   for(Standard_Integer r = 1; r <= anIntersector.Result().Length(); r++) {
848     const IntTools_Range& aRange = anIntersector.Result().Value(r);
849     
850     if(IsProjectable(IntTools_Tools::IntermediatePoint(aRange.First(), aRange.Last()))) {
851       aCommonPrt.SetRange1(aRange.First(), aRange.Last());
852       mySeqOfCommonPrts.Append(aCommonPrt);
853     }
854   }
855
856   aNb = mySeqOfCommonPrts.Length();
857
858   for (i=1; i<=aNb; i++) {
859     IntTools_CommonPrt& aCP=mySeqOfCommonPrts.ChangeValue(i);
860     //
861     Standard_Real aTx1, aTx2;
862     gp_Pnt aPx1, aPx2;
863     //
864     aCP.Range1(aTx1, aTx2);
865     myC.D0(aTx1, aPx1);
866     myC.D0(aTx2, aPx2);
867     aCP.SetBoundingPoints(aPx1, aPx2);
868     //
869     MakeType (aCP); 
870   }
871   {
872     // Line\Cylinder's Common Parts treatement
873     GeomAbs_CurveType   aCType;
874     GeomAbs_SurfaceType aSType;
875     TopAbs_ShapeEnum aType;
876     Standard_Boolean bIsTouch;
877     Standard_Real aTx;
878     
879     aCType=myC.GetType();
880     aSType=myS.GetType();
881     
882     if (aCType==GeomAbs_Line && aSType==GeomAbs_Cylinder) {
883       for (i=1; i<=aNb; i++) {
884         IntTools_CommonPrt& aCP=mySeqOfCommonPrts(i);
885         aType=aCP.Type();
886         if (aType==TopAbs_EDGE) {
887           bIsTouch=CheckTouch (aCP, aTx);
888           if (bIsTouch) {
889             aCP.SetType(TopAbs_VERTEX);
890             aCP.SetVertexParameter1(aTx);
891             //aCP.SetRange1 (aTx, aTx);
892           }
893         }
894         else if (aType==TopAbs_VERTEX) {
895           bIsTouch=CheckTouchVertex (aCP, aTx);
896           if (bIsTouch) {
897             aCP.SetVertexParameter1(aTx);
898             //aCP.SetRange1 (aTx, aTx);
899           }
900         }
901       }
902     }
903     
904     // Circle\Plane's Common Parts treatement
905     
906     if (aCType==GeomAbs_Circle && aSType==GeomAbs_Plane) {
907       Standard_Boolean bIsCoplanar, bIsRadius;
908       bIsCoplanar=IsCoplanar(myC, myS);
909       bIsRadius=IsRadius(myC, myS, myCriteria);
910       if (!bIsCoplanar && !bIsRadius) {
911         for (i=1; i<=aNb; i++) {
912           IntTools_CommonPrt& aCP=mySeqOfCommonPrts(i);
913           aType=aCP.Type();
914           if (aType==TopAbs_EDGE) {
915             bIsTouch=CheckTouch (aCP, aTx);
916             if (bIsTouch) {
917               aCP.SetType(TopAbs_VERTEX);
918               aCP.SetVertexParameter1(aTx);
919               //aCP.SetRange1 (aTx, aTx);
920             }
921           }
922           else if (aType==TopAbs_VERTEX) {
923             bIsTouch=CheckTouchVertex (aCP, aTx);
924             if (bIsTouch) {
925               aCP.SetVertexParameter1(aTx);
926               //aCP.SetRange1 (aTx, aTx);
927             }
928           }
929         }
930       }
931     }
932   }
933   myIsDone=Standard_True;
934 }
935
936 //
937 // myErrorStatus
938 // 1 - the method Perform() is not invoked  
939 // 2,3,4,5 -the method CheckData() fails
940 // 6 - PrepareArgs() problems
941 // 7 - No Projectable ranges
942 // 8,9 - PrepareArgs() problems occured inside  projectable Ranges
943 // 11 - can't fill array  aFunc(i) in PrepareArgsFuncArrays 
944
945
946 //=======================================================================
947 //function : CheckTouch 
948 //purpose  : 
949 //=======================================================================
950 Standard_Boolean IntTools_EdgeFace::CheckTouchVertex 
951   (const IntTools_CommonPrt& aCP,
952    Standard_Real& aTx) 
953 {
954   Standard_Real aTF, aTL, Tol, U1f,U1l,V1f,V1l;
955   Standard_Real aEpsT, af, al,aDist2, aMinDist2, aTm, aDist2New;
956   Standard_Boolean theflag=Standard_False;
957   Standard_Integer aNbExt, i, iLower ;
958   GeomAbs_CurveType aType;
959   //
960   aCP.Range1(aTF, aTL);
961   aType=myC.GetType();
962   //
963   aEpsT=8.e-5;
964   if (aType==GeomAbs_Line) {
965     aEpsT=9.e-5;
966   }
967   //
968   aTm=0.5*(aTF+aTL);
969   aDist2=DistanceFunction(aTm);
970   aDist2 *= aDist2;
971
972   Tol = Precision::PConfusion();
973
974   const Handle(Geom_Curve)&  Curve =BRep_Tool::Curve  (myC.Edge(), af, al);
975   const Handle(Geom_Surface)& Surface=BRep_Tool::Surface(myS.Face());
976
977   Surface->Bounds(U1f,U1l,V1f,V1l);
978   
979   GeomAdaptor_Curve   TheCurve   (Curve,aTF, aTL);
980   GeomAdaptor_Surface TheSurface (Surface, U1f, U1l, V1f, V1l); 
981      
982   Extrema_ExtCS anExtrema (TheCurve, TheSurface, Tol, Tol);
983    
984   if(!anExtrema.IsDone()) {
985     return theflag;
986   }
987   if (anExtrema.IsParallel()) {
988     return theflag;
989   }
990   
991   aNbExt=anExtrema.NbExt() ;
992   if (!aNbExt) {
993      return theflag;
994   }
995
996   iLower=1;
997   aMinDist2=1.e100;
998   for (i=1; i<=aNbExt; ++i) {
999     aDist2=anExtrema.SquareDistance(i);
1000     if (aDist2 < aMinDist2) {
1001       aMinDist2=aDist2;
1002       iLower=i;
1003     }
1004   }
1005
1006   aDist2New=anExtrema.SquareDistance(iLower);
1007   
1008   if (aDist2New > aDist2) {
1009     aTx=aTm;
1010     return !theflag;
1011   }
1012   
1013   if (aDist2New > myCriteria * myCriteria) {
1014     return theflag;
1015   }
1016
1017   Extrema_POnCurv aPOnC;
1018   Extrema_POnSurf aPOnS;
1019   anExtrema.Points(iLower, aPOnC, aPOnS);
1020
1021  
1022   aTx=aPOnC.Parameter();
1023   ///
1024   if (fabs (aTx-aTF) < aEpsT) {
1025     return theflag;
1026   }
1027
1028   if (fabs (aTx-aTL) < aEpsT) {
1029     return theflag;
1030   }
1031
1032   if (aTx>aTF && aTx<aTL) {
1033     return !theflag;
1034   }
1035
1036   return theflag;
1037 }
1038
1039
1040 //=======================================================================
1041 //function :  IsCoplanar
1042 //purpose  : 
1043 //=======================================================================
1044 Standard_Boolean IsCoplanar (const BRepAdaptor_Curve& aCurve ,
1045                              const BRepAdaptor_Surface& aSurface)
1046 {
1047   Standard_Boolean bFlag=Standard_False;
1048
1049   GeomAbs_CurveType   aCType;
1050   GeomAbs_SurfaceType aSType;
1051
1052   aCType=aCurve.GetType();
1053   aSType=aSurface.GetType();
1054     
1055   if (aCType==GeomAbs_Circle && aSType==GeomAbs_Plane) {
1056     gp_Circ aCirc=aCurve.Circle();
1057     const gp_Ax1& anAx1=aCirc.Axis();
1058     const gp_Dir& aDirAx1=anAx1.Direction();
1059     
1060     gp_Pln aPln=aSurface.Plane();
1061     const gp_Ax1& anAx=aPln.Axis();
1062     const gp_Dir& aDirPln=anAx.Direction();
1063
1064     bFlag=IntTools_Tools::IsDirsCoinside(aDirAx1, aDirPln);
1065   }
1066   return bFlag;
1067 }
1068 //=======================================================================
1069 //function :  IsRadius
1070 //purpose  : 
1071 //=======================================================================
1072 Standard_Boolean IsRadius (const BRepAdaptor_Curve& aCurve,
1073                            const BRepAdaptor_Surface& aSurface,
1074                            const Standard_Real aCriteria)
1075 {
1076   Standard_Boolean bFlag=Standard_False;
1077
1078   GeomAbs_CurveType   aCType;
1079   GeomAbs_SurfaceType aSType;
1080
1081   aCType=aCurve.GetType();
1082   aSType=aSurface.GetType();
1083     
1084   if (aCType==GeomAbs_Circle && aSType==GeomAbs_Plane) {
1085     gp_Circ aCirc=aCurve.Circle();
1086     const gp_Pnt aCenter=aCirc.Location();
1087     Standard_Real aR=aCirc.Radius();
1088     gp_Pln aPln=aSurface.Plane();
1089     Standard_Real aD=aPln.Distance(aCenter);
1090     if (fabs (aD-aR) < aCriteria) {
1091       return !bFlag;
1092     }
1093   }
1094   return bFlag;
1095 }
1096 //
1097 //=======================================================================
1098 //function :  AdaptiveDiscret
1099 //purpose  : 
1100 //=======================================================================
1101 Standard_Integer AdaptiveDiscret (const Standard_Integer iDiscret,
1102                                   const BRepAdaptor_Curve& aCurve ,
1103                                   const BRepAdaptor_Surface& aSurface)
1104 {
1105   Standard_Integer iDiscretNew;
1106
1107   iDiscretNew=iDiscret;
1108
1109   GeomAbs_SurfaceType aSType;
1110
1111   aSType=aSurface.GetType();
1112     
1113   if (aSType==GeomAbs_Cylinder) {
1114    Standard_Real aELength, aRadius, dLR;
1115
1116    aELength=IntTools::Length(aCurve.Edge());
1117    
1118    gp_Cylinder aCylinder=aSurface.Cylinder();
1119    aRadius=aCylinder.Radius();
1120    dLR=2*aRadius;
1121
1122    iDiscretNew=(Standard_Integer)(aELength/dLR);
1123    
1124    if (iDiscretNew<iDiscret) {
1125      iDiscretNew=iDiscret;
1126    }
1127      
1128   }
1129   return iDiscretNew;
1130 }
1131
1132 #ifdef _MSC_VER
1133 #pragma warning ( default : 4101 )
1134 #endif