0026738: Make Boolean operations safely treating arguments when running with fuzzy...
[occt.git] / src / IntTools / IntTools_Context.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 <Bnd_Box.hxx>
17 #include <BRep_Tool.hxx>
18 #include <BRepAdaptor_Surface.hxx>
19 #include <BRepBndLib.hxx>
20 #include <BRepClass3d_SolidClassifier.hxx>
21 #include <Extrema_LocateExtPC.hxx>
22 #include <Geom2d_Curve.hxx>
23 #include <Geom2d_TrimmedCurve.hxx>
24 #include <Geom2dHatch_Hatcher.hxx>
25 #include <Geom2dHatch_Intersector.hxx>
26 #include <Geom_BoundedCurve.hxx>
27 #include <Geom_Curve.hxx>
28 #include <GeomAdaptor_Curve.hxx>
29 #include <GeomAPI_ProjectPointOnCurve.hxx>
30 #include <GeomAPI_ProjectPointOnSurf.hxx>
31 #include <gp_Pnt.hxx>
32 #include <gp_Pnt2d.hxx>
33 #include <IntTools_Context.hxx>
34 #include <IntTools_Curve.hxx>
35 #include <IntTools_FClass2d.hxx>
36 #include <IntTools_SurfaceRangeLocalizeData.hxx>
37 #include <IntTools_Tools.hxx>
38 #include <Precision.hxx>
39 #include <Standard_Type.hxx>
40 #include <TopAbs_State.hxx>
41 #include <TopExp_Explorer.hxx>
42 #include <TopoDS.hxx>
43 #include <TopoDS_Edge.hxx>
44 #include <TopoDS_Face.hxx>
45 #include <TopoDS_Shape.hxx>
46 #include <TopoDS_Solid.hxx>
47 #include <TopoDS_Vertex.hxx>
48
49 IMPLEMENT_STANDARD_RTTIEXT(IntTools_Context,MMgt_TShared)
50
51 // 
52 //=======================================================================
53 //function : 
54 //purpose  : 
55 //=======================================================================
56 IntTools_Context::IntTools_Context()
57 :
58   myAllocator(NCollection_BaseAllocator::CommonBaseAllocator()),
59   myFClass2dMap(100, myAllocator),
60   myProjPSMap(100, myAllocator),
61   myProjPCMap(100, myAllocator),
62   mySClassMap(100, myAllocator),
63   myProjPTMap(100, myAllocator),
64   myHatcherMap(100, myAllocator),
65   myProjSDataMap(100, myAllocator),
66   myBndBoxDataMap(100, myAllocator),
67   myCreateFlag(0),
68   myPOnSTolerance(1.e-12)
69 {
70 }
71 //=======================================================================
72 //function : 
73 //purpose  : 
74 //=======================================================================
75 IntTools_Context::IntTools_Context
76   (const Handle(NCollection_BaseAllocator)& theAllocator)
77 :
78   myAllocator(theAllocator),
79   myFClass2dMap(100, myAllocator),
80   myProjPSMap(100, myAllocator),
81   myProjPCMap(100, myAllocator),
82   mySClassMap(100, myAllocator),
83   myProjPTMap(100, myAllocator),
84   myHatcherMap(100, myAllocator),
85   myProjSDataMap(100, myAllocator),
86   myBndBoxDataMap(100, myAllocator),
87   myCreateFlag(1),
88   myPOnSTolerance(1.e-12)
89 {
90 }
91 //=======================================================================
92 //function : ~
93 //purpose  : 
94 //=======================================================================
95 IntTools_Context::~IntTools_Context()
96 {
97   Standard_Address anAdr;
98   BOPCol_DataMapIteratorOfDataMapOfShapeAddress aIt;
99   BOPCol_DataMapIteratorOfDataMapOfTransientAddress aIt1;
100   //
101   IntTools_FClass2d* pFClass2d;
102   //
103   aIt.Initialize(myFClass2dMap);
104   for (; aIt.More(); aIt.Next()) {
105     anAdr=aIt.Value();
106     pFClass2d=(IntTools_FClass2d*)anAdr;
107     (*pFClass2d).~IntTools_FClass2d();
108     myAllocator->Free(anAdr); 
109   }
110   myFClass2dMap.Clear();
111   //
112   clearCachedPOnSProjectors();
113   //
114   GeomAPI_ProjectPointOnCurve* pProjPC;
115   aIt.Initialize(myProjPCMap);
116   for (; aIt.More(); aIt.Next()) {
117     anAdr=aIt.Value();
118     pProjPC=(GeomAPI_ProjectPointOnCurve*)anAdr;
119     (*pProjPC).~GeomAPI_ProjectPointOnCurve();
120     myAllocator->Free(anAdr); 
121   }
122   myProjPCMap.Clear();
123   //
124   //
125   BRepClass3d_SolidClassifier* pSC;
126   aIt.Initialize(mySClassMap);
127   for (; aIt.More(); aIt.Next()) {
128     anAdr=aIt.Value();
129     pSC=(BRepClass3d_SolidClassifier*)anAdr;
130     (*pSC).~BRepClass3d_SolidClassifier();
131     myAllocator->Free(anAdr); 
132   }
133   mySClassMap.Clear();
134   //
135   GeomAPI_ProjectPointOnCurve* pProjPT;
136   aIt1.Initialize(myProjPTMap);
137   for (; aIt1.More(); aIt1.Next()) {
138     anAdr=aIt1.Value();
139     pProjPT=(GeomAPI_ProjectPointOnCurve*)anAdr;
140     (*pProjPT).~GeomAPI_ProjectPointOnCurve();
141     myAllocator->Free(anAdr); 
142   }
143   myProjPTMap.Clear();
144   //
145   Geom2dHatch_Hatcher* pHatcher;
146   aIt.Initialize(myHatcherMap);
147   for (; aIt.More(); aIt.Next()) {
148     anAdr=aIt.Value();
149     pHatcher=(Geom2dHatch_Hatcher*)anAdr;
150     (*pHatcher).~Geom2dHatch_Hatcher();
151     myAllocator->Free(anAdr);
152   }
153   myHatcherMap.Clear();
154   //
155   IntTools_SurfaceRangeLocalizeData* pSData = NULL;
156   aIt.Initialize(myProjSDataMap);
157   for (; aIt.More(); aIt.Next()) {
158     anAdr=aIt.Value();
159     pSData = (IntTools_SurfaceRangeLocalizeData*)anAdr;
160     (*pSData).~IntTools_SurfaceRangeLocalizeData();
161     myAllocator->Free(anAdr);
162   }
163   myProjSDataMap.Clear();
164   //
165   Bnd_Box* pBox;
166   aIt.Initialize(myBndBoxDataMap);
167   for (; aIt.More(); aIt.Next()) {
168     anAdr=aIt.Value();
169     pBox=(Bnd_Box*)anAdr;
170     (*pBox).~Bnd_Box();
171     myAllocator->Free(anAdr); 
172   }
173   myBndBoxDataMap.Clear();
174 }
175 //=======================================================================
176 //function : BndBox
177 //purpose  : 
178 //=======================================================================
179 Bnd_Box& IntTools_Context::BndBox(const TopoDS_Shape& aS)
180 {
181   Standard_Address anAdr;
182   Bnd_Box* pBox;
183   //
184   if (!myBndBoxDataMap.IsBound(aS)) {
185     //
186     pBox=(Bnd_Box*)myAllocator->Allocate(sizeof(Bnd_Box));
187     new (pBox) Bnd_Box();
188     //
189     Bnd_Box &aBox=*pBox;
190     BRepBndLib::Add(aS, aBox);
191     //
192     anAdr=(Standard_Address)pBox;
193     myBndBoxDataMap.Bind(aS, anAdr);
194   }
195   else {
196     anAdr=myBndBoxDataMap.Find(aS);
197     pBox=(Bnd_Box*)anAdr;
198   }
199   return *pBox;
200 }
201 //=======================================================================
202 //function : IsInfiniteFace
203 //purpose  : 
204 //=======================================================================
205 Standard_Boolean IntTools_Context::IsInfiniteFace
206   (const TopoDS_Face& aFace)
207 {
208   Standard_Boolean bRet;
209   Standard_Integer i;
210   Standard_Real aX[6];
211   //
212   bRet=Standard_False;
213   //
214   if (!BRep_Tool::NaturalRestriction(aFace)) {
215     return bRet; 
216   }
217   //
218   Bnd_Box& aBox=BndBox(aFace);
219   //
220   aBox.Get(aX[0], aX[1], aX[2], aX[3], aX[4], aX[5]);
221   //
222   for (i=0; (i<6) && (!bRet); ++i) {
223     bRet=Precision::IsInfinite(aX[i]);
224   }
225   //
226   return bRet; 
227 }
228 //=======================================================================
229 //function : FClass2d
230 //purpose  : 
231 //=======================================================================
232 IntTools_FClass2d& IntTools_Context::FClass2d(const TopoDS_Face& aF)
233 {
234   Standard_Address anAdr;
235   IntTools_FClass2d* pFClass2d;
236   //
237   if (!myFClass2dMap.IsBound(aF)) {
238     Standard_Real aTolF;
239     TopoDS_Face aFF;
240     //
241     aFF=aF;
242     aFF.Orientation(TopAbs_FORWARD);
243     aTolF=BRep_Tool::Tolerance(aFF);
244     //
245     pFClass2d=(IntTools_FClass2d*)myAllocator->Allocate(sizeof(IntTools_FClass2d));
246     new (pFClass2d) IntTools_FClass2d(aFF, aTolF);
247     //
248     anAdr=(Standard_Address)pFClass2d;
249     myFClass2dMap.Bind(aFF, anAdr);
250   }
251   else {
252     anAdr=myFClass2dMap.Find(aF);
253     pFClass2d=(IntTools_FClass2d*)anAdr;
254   }
255   return *pFClass2d;
256 }
257 //=======================================================================
258 //function : ProjPS
259 //purpose  : 
260 //=======================================================================
261 GeomAPI_ProjectPointOnSurf& IntTools_Context::ProjPS(const TopoDS_Face& aF)
262 {
263   Standard_Address anAdr;
264   GeomAPI_ProjectPointOnSurf* pProjPS;
265  
266   if (!myProjPSMap.IsBound(aF)) {
267     Standard_Real Umin, Usup, Vmin, Vsup;
268     BRepAdaptor_Surface aBAS;
269     //
270     const Handle(Geom_Surface)& aS=BRep_Tool::Surface(aF);
271     aBAS.Initialize (aF, Standard_True);
272     //
273     Umin=aBAS.FirstUParameter();
274     Usup=aBAS.LastUParameter ();
275     Vmin=aBAS.FirstVParameter();
276     Vsup=aBAS.LastVParameter ();
277     //
278     pProjPS=(GeomAPI_ProjectPointOnSurf*)myAllocator->Allocate(sizeof(GeomAPI_ProjectPointOnSurf));
279     new (pProjPS) GeomAPI_ProjectPointOnSurf();
280     pProjPS->Init(aS ,Umin, Usup, Vmin, Vsup, myPOnSTolerance/*, Extrema_ExtAlgo_Tree*/);
281     Extrema_ExtPS& anExtAlgo = const_cast<Extrema_ExtPS&>(pProjPS->Extrema());
282     anExtAlgo.SetFlag(Extrema_ExtFlag_MIN);
283     //
284     anAdr=(Standard_Address)pProjPS;
285     myProjPSMap.Bind(aF, anAdr);
286   }
287   
288   else {
289     anAdr=myProjPSMap.Find(aF);
290     pProjPS=(GeomAPI_ProjectPointOnSurf*)anAdr;
291   }
292   return *pProjPS;
293 }
294 //=======================================================================
295 //function : ProjPC
296 //purpose  : 
297 //=======================================================================
298 GeomAPI_ProjectPointOnCurve& IntTools_Context::ProjPC(const TopoDS_Edge& aE)
299 {
300   Standard_Address anAdr;
301   GeomAPI_ProjectPointOnCurve* pProjPC;
302  
303   if (!myProjPCMap.IsBound(aE)) {
304     Standard_Real f, l;
305     //
306     Handle(Geom_Curve)aC3D=BRep_Tool::Curve (aE, f, l);
307     //
308     pProjPC=(GeomAPI_ProjectPointOnCurve*)myAllocator->Allocate(sizeof(GeomAPI_ProjectPointOnCurve));
309     new (pProjPC) GeomAPI_ProjectPointOnCurve();
310     pProjPC->Init(aC3D, f, l);
311     //
312     anAdr=(Standard_Address)pProjPC;
313     myProjPCMap.Bind(aE, anAdr);
314   }
315   
316   else {
317     anAdr=myProjPCMap.Find(aE);
318     pProjPC=(GeomAPI_ProjectPointOnCurve*)anAdr;
319   }
320   return *pProjPC;
321 }
322
323 //=======================================================================
324 //function : ProjPT
325 //purpose  : 
326 //=======================================================================
327 GeomAPI_ProjectPointOnCurve& IntTools_Context::ProjPT
328   (const Handle(Geom_Curve)& aC3D)
329
330 {
331   Standard_Address anAdr;
332   GeomAPI_ProjectPointOnCurve* pProjPT;
333  
334   if (!myProjPTMap.IsBound(aC3D)) {
335     Standard_Real f, l;
336     f=aC3D->FirstParameter();
337     l=aC3D->LastParameter();
338     //
339     pProjPT=(GeomAPI_ProjectPointOnCurve*)myAllocator->Allocate(sizeof(GeomAPI_ProjectPointOnCurve));
340     new (pProjPT) GeomAPI_ProjectPointOnCurve();
341     pProjPT->Init(aC3D, f, l);
342     //
343     anAdr=(Standard_Address)pProjPT;
344     myProjPTMap.Bind(aC3D, anAdr);
345   }
346   
347   else {
348     anAdr=myProjPTMap.Find(aC3D);
349     pProjPT=(GeomAPI_ProjectPointOnCurve*)anAdr;
350   }
351   return *pProjPT;
352 }
353 //=======================================================================
354 //function : SolidClassifier
355 //purpose  : 
356 //=======================================================================
357 BRepClass3d_SolidClassifier& IntTools_Context::SolidClassifier
358   (const TopoDS_Solid& aSolid)
359 {
360   Standard_Address anAdr;
361   BRepClass3d_SolidClassifier* pSC;
362  
363   if (!mySClassMap.IsBound(aSolid)) {
364     //
365     pSC=(BRepClass3d_SolidClassifier*)myAllocator->Allocate(sizeof(BRepClass3d_SolidClassifier));
366     new (pSC) BRepClass3d_SolidClassifier(aSolid);
367     //
368     anAdr=(Standard_Address)pSC;
369     mySClassMap.Bind(aSolid, anAdr);
370   }
371   
372   else {
373     anAdr=mySClassMap.Find(aSolid);
374     pSC =(BRepClass3d_SolidClassifier*)anAdr;
375   }
376   return *pSC;
377 }
378
379 //=======================================================================
380 //function : Hatcher
381 //purpose  : 
382 //=======================================================================
383 Geom2dHatch_Hatcher& IntTools_Context::Hatcher(const TopoDS_Face& aF)
384 {
385   Standard_Address anAdr;
386   Geom2dHatch_Hatcher* pHatcher;
387   //
388   if (!myHatcherMap.IsBound(aF)) {
389     Standard_Real aTolArcIntr, aTolTangfIntr, aTolHatch2D, aTolHatch3D;
390     Standard_Real aU1, aU2, aEpsT;
391     TopAbs_Orientation aOrE;
392     Handle(Geom_Surface) aS;
393     Handle(Geom2d_Curve) aC2D;
394     Handle(Geom2d_TrimmedCurve) aCT2D;
395     TopoDS_Face aFF;
396     TopExp_Explorer aExp;
397     //
398     aTolHatch2D=1.e-8;
399     aTolHatch3D=1.e-8;
400     aTolArcIntr=1.e-10;
401     aTolTangfIntr=1.e-10;
402     aEpsT=Precision::PConfusion();
403     //
404     Geom2dHatch_Intersector aIntr(aTolArcIntr, aTolTangfIntr);
405     pHatcher=(Geom2dHatch_Hatcher*)
406       myAllocator->Allocate(sizeof(Geom2dHatch_Hatcher));
407     new (pHatcher) Geom2dHatch_Hatcher(aIntr,
408                                        aTolHatch2D, aTolHatch3D,
409                                        Standard_True, Standard_False);
410     //
411     aFF=aF;
412     aFF.Orientation(TopAbs_FORWARD);
413     aS=BRep_Tool::Surface(aFF);
414
415     aExp.Init (aFF, TopAbs_EDGE);
416     for (; aExp.More() ; aExp.Next()) {
417       const TopoDS_Edge& aE=*((TopoDS_Edge*)&aExp.Current());
418       aOrE=aE.Orientation();
419       //
420       aC2D=BRep_Tool::CurveOnSurface (aE, aFF, aU1, aU2);
421       if (aC2D.IsNull() ) {
422         continue;
423       }
424       if (fabs(aU1-aU2) < aEpsT) {
425         continue;
426       }
427       //
428       aCT2D=new Geom2d_TrimmedCurve(aC2D, aU1, aU2);
429       Geom2dAdaptor_Curve aGAC (aCT2D);
430       pHatcher->AddElement(aGAC, aOrE);
431     }// for (; aExp.More() ; aExp.Next()) {
432     //
433     anAdr=(Standard_Address)pHatcher;
434     myHatcherMap.Bind(aFF, anAdr);
435   }//if (!myHatcherMap.IsBound(aF)) {
436   //
437   else {
438     anAdr=myHatcherMap.Find(aF);
439     pHatcher=(Geom2dHatch_Hatcher*)anAdr;
440   }
441
442   return *pHatcher;
443 }
444
445 //=======================================================================
446 //function : SurfaceData
447 //purpose  : 
448 //=======================================================================
449 IntTools_SurfaceRangeLocalizeData& IntTools_Context::SurfaceData
450   (const TopoDS_Face& aF) 
451 {
452   Standard_Address anAdr;
453   IntTools_SurfaceRangeLocalizeData* pSData;
454   //
455   if (!myProjSDataMap.IsBound(aF)) {
456     pSData=(IntTools_SurfaceRangeLocalizeData*)
457       myAllocator->Allocate(sizeof(IntTools_SurfaceRangeLocalizeData));
458     new (pSData) IntTools_SurfaceRangeLocalizeData
459       (3, 
460        3, 
461        10. * Precision::PConfusion(), 
462        10. * Precision::PConfusion());
463     //
464     anAdr=(Standard_Address)pSData;
465     myProjSDataMap.Bind(aF, anAdr);
466   }
467   
468   else {
469     anAdr=myProjSDataMap.Find(aF);
470     pSData=(IntTools_SurfaceRangeLocalizeData*)anAdr;
471   }
472   return *pSData;
473
474 }
475
476 //=======================================================================
477 //function : ComputePE
478 //purpose  : 
479 //=======================================================================
480 Standard_Integer IntTools_Context::ComputePE
481   (const gp_Pnt& aP1,
482    const Standard_Real aTolP1,
483    const TopoDS_Edge& aE2,
484    Standard_Real& aT,
485    Standard_Real& aDist)
486 {
487   if (!BRep_Tool::IsGeometric(aE2)) { 
488     return -2;
489   }
490   Standard_Real aTolE2, aTolSum;
491   Standard_Integer aNbProj;
492   //
493   GeomAPI_ProjectPointOnCurve& aProjector=ProjPC(aE2);
494   aProjector.Perform(aP1);
495
496   aNbProj=aProjector.NbPoints();
497   if (!aNbProj) {
498     return -3;
499   }
500   //
501   aDist=aProjector.LowerDistance();
502   //
503   aTolE2=BRep_Tool::Tolerance(aE2);
504   aTolSum = aTolP1 + aTolE2 + Precision::Confusion();
505   //
506   aT=aProjector.LowerDistanceParameter();
507   if (aDist > aTolSum) {
508     return -4;
509   }
510   return 0;
511 }
512 //=======================================================================
513 //function : ComputeVE
514 //purpose  : 
515 //=======================================================================
516 Standard_Integer IntTools_Context::ComputeVE
517   (const TopoDS_Vertex& theV, 
518    const TopoDS_Edge&   theE,
519    Standard_Real& theT,
520    Standard_Real& theTol,
521    const Standard_Real theFuzz)
522 {
523   if (BRep_Tool::Degenerated(theE)) {
524     return -1;
525   }
526   if (!BRep_Tool::IsGeometric(theE)) { 
527     return -2;
528   }
529   Standard_Real aDist, aTolV, aTolE, aTolSum;
530   Standard_Integer aNbProj;
531   gp_Pnt aP;
532   //
533   aP=BRep_Tool::Pnt(theV);
534   //
535   GeomAPI_ProjectPointOnCurve& aProjector=ProjPC(theE);
536   aProjector.Perform(aP);
537
538   aNbProj=aProjector.NbPoints();
539   if (!aNbProj) {
540     return -3;
541   }
542   //
543   aDist=aProjector.LowerDistance();
544   //
545   aTolV=BRep_Tool::Tolerance(theV);
546   aTolE=BRep_Tool::Tolerance(theE);
547   aTolSum = aTolV + aTolE + Max(theFuzz, Precision::Confusion());
548   //
549   theTol = aDist + aTolE;
550   theT = aProjector.LowerDistanceParameter();
551   if (aDist > aTolSum) {
552     return -4;
553   }
554   return 0;
555 }
556 //=======================================================================
557 //function : ComputeVF
558 //purpose  : 
559 //=======================================================================
560 Standard_Integer IntTools_Context::ComputeVF
561   (const TopoDS_Vertex& theVertex, 
562    const TopoDS_Face&   theFace,
563    Standard_Real& theU,
564    Standard_Real& theV,
565    Standard_Real& theTol,
566    const Standard_Real theFuzz)
567 {
568   Standard_Real aTolV, aTolF, aTolSum, aDist;
569   gp_Pnt aP;
570
571   aP = BRep_Tool::Pnt(theVertex);
572   //
573   // 1. Check if the point is projectable on the surface
574   GeomAPI_ProjectPointOnSurf& aProjector=ProjPS(theFace);
575   aProjector.Perform(aP);
576   //
577   if (!aProjector.IsDone()) { // the point is not  projectable on the surface
578     return -1;
579   }
580   //
581   // 2. Check the distance between the projection point and 
582   //    the original point
583   aDist = aProjector.LowerDistance();
584   //
585   aTolV = BRep_Tool::Tolerance(theVertex);
586   aTolF = BRep_Tool::Tolerance(theFace);
587   //
588   aTolSum = aTolV + aTolF + Max(theFuzz, Precision::Confusion());
589   theTol = aDist + aTolF;
590   aProjector.LowerDistanceParameters(theU, theV);
591   //
592   if (aDist > aTolSum) {
593     // the distance is too large
594     return -2;
595   }
596   //
597   gp_Pnt2d aP2d(theU, theV);
598   Standard_Boolean pri = IsPointInFace (theFace, aP2d);
599   if (!pri) {//  the point lays on the surface but out of the face 
600     return -3;
601   }
602   return 0;
603 }
604 //=======================================================================
605 //function : StatePointFace
606 //purpose  : 
607 //=======================================================================
608 TopAbs_State IntTools_Context::StatePointFace
609   (const TopoDS_Face& aF,
610    const gp_Pnt2d& aP2d)
611 {
612   TopAbs_State aState;
613   IntTools_FClass2d& aClass2d=FClass2d(aF);
614   aState=aClass2d.Perform(aP2d);
615   return aState;
616 }
617 //=======================================================================
618 //function : IsPointInFace
619 //purpose  : 
620 //=======================================================================
621 Standard_Boolean IntTools_Context::IsPointInFace
622   (const TopoDS_Face& aF,
623    const gp_Pnt2d& aP2d)
624 {
625   TopAbs_State aState=StatePointFace(aF, aP2d);
626   if (aState==TopAbs_OUT || aState==TopAbs_ON) {
627     return Standard_False;
628   }
629   return Standard_True;
630 }
631 //=======================================================================
632 //function : IsPointInFace
633 //purpose  : 
634 //=======================================================================
635 Standard_Boolean IntTools_Context::IsPointInFace
636   (const gp_Pnt& aP,
637    const TopoDS_Face& aF,
638    const Standard_Real aTol) 
639 {
640   Standard_Boolean bIn;
641   Standard_Real aDist;
642   //
643   GeomAPI_ProjectPointOnSurf& aProjector=ProjPS(aF);
644   aProjector.Perform(aP);
645   //
646   bIn = aProjector.IsDone();
647   if (bIn) {
648     aDist = aProjector.LowerDistance();
649     if (aDist < aTol) {
650       Standard_Real U, V;
651       //
652       aProjector.LowerDistanceParameters(U, V);
653       gp_Pnt2d aP2D(U, V);
654       bIn = IsPointInFace(aF, aP2D);
655     }
656   }
657   //
658   return bIn;
659 }
660 //=======================================================================
661 //function : IsPointInOnFace
662 //purpose  : 
663 //=======================================================================
664   Standard_Boolean IntTools_Context::IsPointInOnFace(const TopoDS_Face& aF,
665                                                    const gp_Pnt2d& aP2d)
666
667   TopAbs_State aState=StatePointFace(aF, aP2d);
668   if (aState==TopAbs_OUT) {
669     return Standard_False;
670   }
671   return Standard_True;
672 }
673 //=======================================================================
674 //function : IsValidPointForFace
675 //purpose  : 
676 //=======================================================================
677 Standard_Boolean IntTools_Context::IsValidPointForFace
678   (const gp_Pnt& aP,
679    const TopoDS_Face& aF,
680    const Standard_Real aTol) 
681 {
682   Standard_Boolean bFlag;
683   Standard_Real Umin, U, V;
684
685   GeomAPI_ProjectPointOnSurf& aProjector=ProjPS(aF);
686   aProjector.Perform(aP);
687   
688   bFlag=aProjector.IsDone();
689   if (bFlag) {
690     
691     Umin=aProjector.LowerDistance();
692     //if (Umin > 1.e-3) { // it was 
693     if (Umin > aTol) {
694       return !bFlag; 
695     }
696     //
697     aProjector.LowerDistanceParameters(U, V);
698     gp_Pnt2d aP2D(U, V);
699     bFlag=IsPointInOnFace (aF, aP2D);
700   }
701   return bFlag;
702 }
703 //=======================================================================
704 //function : IsValidPointForFaces
705 //purpose  : 
706 //=======================================================================
707 Standard_Boolean IntTools_Context::IsValidPointForFaces 
708   (const gp_Pnt& aP,
709    const TopoDS_Face& aF1,
710    const TopoDS_Face& aF2,
711    const Standard_Real aTol) 
712 {
713   Standard_Boolean bFlag1, bFlag2;
714
715   bFlag1=IsValidPointForFace(aP, aF1, aTol);
716   if (!bFlag1) {
717     return bFlag1;
718   }
719   bFlag2=IsValidPointForFace(aP, aF2, aTol);  
720   return  bFlag2;
721 }
722 //=======================================================================
723 //function : IsValidBlockForFace
724 //purpose  : 
725 //=======================================================================
726 Standard_Boolean IntTools_Context::IsValidBlockForFace 
727   (const Standard_Real aT1,
728    const Standard_Real aT2,
729    const IntTools_Curve& aC, 
730    const TopoDS_Face& aF,
731    const Standard_Real aTol) 
732 {
733   Standard_Boolean bFlag;
734   Standard_Real aTInterm;
735   gp_Pnt aPInterm;
736
737   aTInterm=IntTools_Tools::IntermediatePoint(aT1, aT2);
738
739   Handle(Geom_Curve) aC3D=aC.Curve();
740   // point 3D
741   aC3D->D0(aTInterm, aPInterm);
742   //
743   bFlag=IsValidPointForFace (aPInterm, aF, aTol);
744   return bFlag;
745 }
746 //=======================================================================
747 //function : IsValidBlockForFaces
748 //purpose  : 
749 //=======================================================================
750 Standard_Boolean IntTools_Context::IsValidBlockForFaces 
751   (const Standard_Real aT1,
752    const Standard_Real aT2,
753    const IntTools_Curve& aC, 
754    const TopoDS_Face& aF1,
755    const TopoDS_Face& aF2,
756    const Standard_Real aTol) 
757 {
758   Standard_Boolean bFlag1, bFlag2;
759   //
760   Handle(Geom2d_Curve) aPC1 = aC.FirstCurve2d();
761   Handle(Geom2d_Curve) aPC2 = aC.SecondCurve2d();
762   if( !aPC1.IsNull() && !aPC2.IsNull() ) {
763     Standard_Real aMidPar = IntTools_Tools::IntermediatePoint(aT1, aT2);
764     gp_Pnt2d aPnt2D;
765
766
767     aPC1->D0(aMidPar, aPnt2D);
768     bFlag1 = IsPointInOnFace(aF1, aPnt2D);
769
770     if( !bFlag1 )
771       return bFlag1;
772
773     aPC2->D0(aMidPar, aPnt2D);
774     bFlag2 = IsPointInOnFace(aF2, aPnt2D);
775     return bFlag2;
776   }
777   //
778
779   bFlag1=IsValidBlockForFace (aT1, aT2, aC, aF1, aTol);
780   if (!bFlag1) {
781     return bFlag1;
782   }
783   bFlag2=IsValidBlockForFace (aT1, aT2, aC, aF2, aTol);
784   return bFlag2;
785 }
786 //=======================================================================
787 //function : IsVertexOnLine
788 //purpose  : 
789 //=======================================================================
790 Standard_Boolean IntTools_Context::IsVertexOnLine 
791   (const TopoDS_Vertex& aV,
792    const IntTools_Curve& aC, 
793    const Standard_Real aTolC,
794    Standard_Real& aT)
795 {
796   Standard_Boolean bRet;
797   Standard_Real aTolV;
798   //
799   aTolV=BRep_Tool::Tolerance(aV);
800   bRet=IntTools_Context::IsVertexOnLine(aV, aTolV, aC, aTolC , aT);
801   //
802   return bRet;
803 }
804 //=======================================================================
805 //function : IsVertexOnLine
806 //purpose  : 
807 //=======================================================================
808 Standard_Boolean IntTools_Context::IsVertexOnLine 
809   (const TopoDS_Vertex& aV,
810    const Standard_Real aTolV,
811    const IntTools_Curve& aC, 
812    const Standard_Real aTolC,
813    Standard_Real& aT)
814 {
815   Standard_Real aFirst, aLast, aDist, aTolSum;
816   Standard_Integer aNbProj;
817   gp_Pnt aPv; 
818   
819   aPv=BRep_Tool::Pnt(aV);
820
821   Handle(Geom_Curve) aC3D=aC.Curve();
822   
823   
824   aTolSum=aTolV+aTolC;
825   //
826   GeomAdaptor_Curve aGAC(aC3D);
827   GeomAbs_CurveType aType=aGAC.GetType();
828   if (aType==GeomAbs_BSplineCurve ||
829       aType==GeomAbs_BezierCurve) {
830     aTolSum=2.*aTolSum;
831     if (aTolSum<1.e-5) {
832       aTolSum=1.e-5;
833     }
834   }
835   else {
836     aTolSum=2.*aTolSum;//xft
837     if(aTolSum < 1.e-6)
838       aTolSum = 1.e-6;
839   }
840   //
841   aFirst=aC3D->FirstParameter();
842   aLast =aC3D->LastParameter();
843   //
844   // Checking extermities first
845   // It is necessary to chose the closest bound to the point
846   Standard_Boolean bFirstValid = Standard_False;
847   Standard_Real aFirstDist = Precision::Infinite();
848   //
849   if (!Precision::IsInfinite(aFirst)) {
850     gp_Pnt aPCFirst=aC3D->Value(aFirst);
851     aFirstDist = aPv.Distance(aPCFirst);
852     if (aFirstDist < aTolSum) {
853       bFirstValid = Standard_True;
854       aT=aFirst;
855       //
856       if (aFirstDist > aTolV) {
857         Extrema_LocateExtPC anExt(aPv, aGAC, aFirst, 1.e-10);
858         
859         if(anExt.IsDone()) {
860           Extrema_POnCurv aPOncurve = anExt.Point();
861           aT = aPOncurve.Parameter();
862           
863           if((aT > (aLast + aFirst) * 0.5) ||
864              (aPv.Distance(aPOncurve.Value()) > aTolSum) ||
865              (aPCFirst.Distance(aPOncurve.Value()) < Precision::Confusion()))
866             aT = aFirst;
867         }
868         else
869         {
870           // Local search may fail. Try to use more precise algo.
871           Extrema_ExtPC anExt2(aPv, aGAC, 1.e-10);
872           Standard_Real aMinDist = RealLast();
873           Standard_Integer aMinIdx = -1;
874           if (anExt2.IsDone()) {
875             for (Standard_Integer anIdx = 1; anIdx <= anExt2.NbExt(); anIdx++)
876             {
877               if ( anExt2.IsMin(anIdx) &&
878                    anExt2.SquareDistance(anIdx) < aMinDist )
879               {
880                 aMinDist = anExt2.SquareDistance(anIdx);
881                 aMinIdx = anIdx;
882               }
883             }
884           }
885           if (aMinIdx != -1)
886           {
887             const Extrema_POnCurv& aPOncurve = anExt2.Point(aMinIdx);
888             aT = aPOncurve.Parameter();
889
890             if((aT > (aLast + aFirst) * 0.5) ||
891               (aPv.Distance(aPOncurve.Value()) > aTolSum) ||
892               (aPCFirst.Distance(aPOncurve.Value()) < Precision::Confusion()))
893               aT = aFirst;
894           }
895         }
896
897       }
898     }
899   }
900   //
901   if (!Precision::IsInfinite(aLast)) {
902     gp_Pnt aPCLast=aC3D->Value(aLast);
903     aDist=aPv.Distance(aPCLast);
904     if (bFirstValid && (aFirstDist < aDist)) {
905       return Standard_True;
906     }
907     //
908     if (aDist < aTolSum) {
909       aT=aLast;
910       //
911       if(aDist > aTolV) {
912         Extrema_LocateExtPC anExt(aPv, aGAC, aLast, 1.e-10);
913         
914         if(anExt.IsDone()) {
915           Extrema_POnCurv aPOncurve = anExt.Point();
916           aT = aPOncurve.Parameter();
917           
918           if((aT < (aLast + aFirst) * 0.5) ||
919              (aPv.Distance(aPOncurve.Value()) > aTolSum) ||
920              (aPCLast.Distance(aPOncurve.Value()) < Precision::Confusion()))
921             aT = aLast;
922         }
923         else
924         {
925           // Local search may fail. Try to use more precise algo.
926           Extrema_ExtPC anExt2(aPv, aGAC, 1.e-10);
927           Standard_Real aMinDist = RealLast();
928           Standard_Integer aMinIdx = -1;
929           if (anExt2.IsDone()) {
930             for (Standard_Integer anIdx = 1; anIdx <= anExt2.NbExt(); anIdx++)
931             {
932               if ( anExt2.IsMin(anIdx) &&
933                    anExt2.SquareDistance(anIdx) < aMinDist )
934               {
935                 aMinDist = anExt2.SquareDistance(anIdx);
936                 aMinIdx = anIdx;
937               }
938             }
939           }
940           if (aMinIdx != -1)
941           {
942             const Extrema_POnCurv& aPOncurve = anExt2.Point(aMinIdx);
943             aT = aPOncurve.Parameter();
944
945             if((aT < (aLast + aFirst) * 0.5) ||
946               (aPv.Distance(aPOncurve.Value()) > aTolSum) ||
947               (aPCLast.Distance(aPOncurve.Value()) < Precision::Confusion()))
948               aT = aLast;
949           }
950         }
951       }
952       //
953       return Standard_True;
954     }
955   }
956   else if (bFirstValid) {
957     return Standard_True;
958   }
959   //
960   GeomAPI_ProjectPointOnCurve& aProjector=ProjPT(aC3D);
961   aProjector.Perform(aPv);
962   
963   aNbProj=aProjector.NbPoints();
964   if (!aNbProj) {
965     Handle(Geom_BoundedCurve) aBC=
966       Handle(Geom_BoundedCurve)::DownCast(aC3D);
967     if (!aBC.IsNull()) {
968       gp_Pnt aPStart=aBC->StartPoint();
969       gp_Pnt aPEnd  =aBC->EndPoint();
970       
971       aDist=aPv.Distance(aPStart);
972       if (aDist < aTolSum) {
973         aT=aFirst;
974         return Standard_True;
975       }
976       
977       aDist=aPv.Distance(aPEnd);
978       if (aDist < aTolSum) {
979         aT=aLast;
980         return Standard_True;
981       }
982     }
983     
984     return Standard_False;
985   }
986   
987   aDist=aProjector.LowerDistance();
988   
989   if (aDist > aTolSum) {
990     return Standard_False;
991   }
992
993   aT=aProjector.LowerDistanceParameter();
994
995   return Standard_True; 
996 }
997 //=======================================================================
998 //function : ProjectPointOnEdge
999 //purpose  : 
1000 //=======================================================================
1001 Standard_Boolean IntTools_Context::ProjectPointOnEdge
1002   (const gp_Pnt& aP,
1003    const TopoDS_Edge& anEdge,
1004    Standard_Real& aT)
1005 {
1006   Standard_Integer aNbPoints;
1007
1008   GeomAPI_ProjectPointOnCurve& aProjector=ProjPC(anEdge);
1009   aProjector.Perform(aP);
1010
1011   aNbPoints=aProjector.NbPoints();
1012   if (aNbPoints) {
1013     aT=aProjector.LowerDistanceParameter();
1014     return Standard_True;
1015   }
1016   return Standard_False;
1017 }
1018
1019 //=======================================================================
1020 //function : SetPOnSProjectionTolerance
1021 //purpose  : 
1022 //=======================================================================
1023 void IntTools_Context::SetPOnSProjectionTolerance(const Standard_Real theValue)
1024 {
1025   myPOnSTolerance = theValue;
1026   clearCachedPOnSProjectors();
1027 }
1028
1029 //=======================================================================
1030 //function : clearCachedPOnSProjectors
1031 //purpose  : 
1032 //=======================================================================
1033 void IntTools_Context::clearCachedPOnSProjectors()
1034 {
1035   GeomAPI_ProjectPointOnSurf* pProjPS;
1036   BOPCol_DataMapIteratorOfDataMapOfShapeAddress aIt(myProjPSMap);
1037   for (; aIt.More(); aIt.Next()) {
1038     Standard_Address anAdr=aIt.Value();
1039     pProjPS=(GeomAPI_ProjectPointOnSurf*)anAdr;
1040     (*pProjPS).~GeomAPI_ProjectPointOnSurf();
1041     myAllocator->Free(anAdr); 
1042   }
1043   myProjPSMap.Clear();
1044 }