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