0027117: BRepClass3d_SolidClassifier doesn't take into account vertex/edge/face toler...
[occt.git] / src / BRepClass3d / BRepClass3d_SolidExplorer.cxx
1 // Created on: 1994-03-10
2 // Created by: Laurent BUCHARD
3 // Copyright (c) 1994-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17 // Modifed:     Porting NT 7-5-97 DPF (stdio.h)
18 //              Apr 16 2002 eap, classification against infinite solid (occ299)
19
20
21 //  Modified by skv - Thu Sep  4 12:29:30 2003 OCC578
22
23 //-- Process the case of a hole!!
24 #define REJECTION 1
25
26 //-- To printf on NT
27
28 #include <Bnd_Box.hxx>
29 #include <BRep_Tool.hxx>
30 #include <BRepAdaptor_Curve2d.hxx>
31 #include <BRepAdaptor_HSurface.hxx>
32 #include <BRepAdaptor_Surface.hxx>
33 #include <BRepBndLib.hxx>
34 #include <BRepClass3d_DataMapIteratorOfMapOfInter.hxx>
35 #include <BRepClass3d_SolidExplorer.hxx>
36 #include <BRepClass_Edge.hxx>
37 #include <BRepClass_FaceClassifier.hxx>
38 #include <BRepClass_FacePassiveClassifier.hxx>
39 #include <BRepTools.hxx>
40 #include <BRepTopAdaptor_FClass2d.hxx>
41 #include <ElCLib.hxx>
42 #include <Extrema_ExtPS.hxx>
43 #include <Geom2d_Curve.hxx>
44 #include <GeomAbs_Shape.hxx>
45 #include <gp.hxx>
46 #include <gp_Lin.hxx>
47 #include <gp_Pnt.hxx>
48 #include <gp_Vec.hxx>
49 #include <gp_Vec2d.hxx>
50 #include <IntCurvesFace_Intersector.hxx>
51 #include <Precision.hxx>
52 #include <TopAbs_Orientation.hxx>
53 #include <TopExp_Explorer.hxx>
54 #include <TopoDS.hxx>
55 #include <TopoDS_Face.hxx>
56 #include <TopoDS_Shape.hxx>
57 #include <TopoDS_Shell.hxx>
58 #include <TopExp.hxx>
59
60 #include <stdio.h>
61 //OCC454(apo)->
62 //<-OCC454(apo)
63 //=======================================================================
64 //function : FindAPointInTheFace
65 //purpose  : Compute a point P in the face  F. Param is a Real in
66 //           ]0,1[ and   is  used to  initialise  the algorithm. For
67 //           different values , different points are returned.
68 //=======================================================================
69 Standard_Boolean BRepClass3d_SolidExplorer::FindAPointInTheFace
70 (const TopoDS_Face& _face,
71  gp_Pnt& APoint_,
72  Standard_Real& param_)
73 {
74   Standard_Real u,v;
75   Standard_Boolean r = FindAPointInTheFace(_face,APoint_,u,v,param_);
76   return r;
77 }
78
79 //=======================================================================
80 //function : FindAPointInTheFace
81 //purpose  : 
82 //=======================================================================
83
84 Standard_Boolean BRepClass3d_SolidExplorer::FindAPointInTheFace
85 (const TopoDS_Face& _face,
86  gp_Pnt& APoint_,
87  Standard_Real& u_, Standard_Real& v_,
88  Standard_Real& param_)
89 {
90   gp_Vec aVecD1U, aVecD1V;
91   return FindAPointInTheFace (_face, APoint_, u_, v_, param_, aVecD1U, aVecD1V);
92 }
93
94 //=======================================================================
95 //function : FindAPointInTheFace
96 //purpose  : 
97 //=======================================================================
98
99 Standard_Boolean BRepClass3d_SolidExplorer::FindAPointInTheFace
100 (const TopoDS_Face& _face,
101  gp_Pnt& APoint_,
102  Standard_Real& u_, Standard_Real& v_,
103  Standard_Real& param_,
104  gp_Vec& theVecD1U,
105  gp_Vec& theVecD1V)
106 {
107   TopoDS_Face face = _face;
108   face.Orientation (TopAbs_FORWARD);
109
110   TopExp_Explorer faceexplorer;
111   BRepAdaptor_Curve2d c;
112   gp_Vec2d T;
113   gp_Pnt2d P;
114
115   for (faceexplorer.Init(face,TopAbs_EDGE); 
116        faceexplorer.More(); 
117        faceexplorer.Next())
118   {
119     TopoDS_Edge Edge = TopoDS::Edge (faceexplorer.Current());
120     c.Initialize (Edge, face);
121     c.D1((c.LastParameter() - c.FirstParameter()) * param_ + c.FirstParameter(),P,T);
122
123     Standard_Real x = T.X();
124     Standard_Real y = T.Y();
125     if (Edge.Orientation() == TopAbs_FORWARD)
126     {
127       T.SetCoord (-y,  x);
128     }
129     else
130     {
131       T.SetCoord ( y, -x);
132     }
133     Standard_Real ParamInit = RealLast();
134     Standard_Real TolInit   = 0.00001;
135     Standard_Boolean APointExist = Standard_False;
136
137     BRepClass_FacePassiveClassifier FClassifier;
138
139     T.Normalize();
140     P.SetCoord (P.X() + TolInit * T.X(), P.Y() + TolInit * T.Y());
141     FClassifier.Reset (gp_Lin2d (P, T), ParamInit, RealEpsilon()); //-- Length and Tolerance #######
142
143     TopExp_Explorer otherfaceexplorer;
144     Standard_Integer aNbEdges = 0;
145     for (otherfaceexplorer.Init (face, TopAbs_EDGE);
146          otherfaceexplorer.More(); 
147          otherfaceexplorer.Next(), ++aNbEdges)
148     {
149       TopoDS_Edge OtherEdge = TopoDS::Edge (otherfaceexplorer.Current());
150       if (OtherEdge.Orientation() != TopAbs_EXTERNAL && OtherEdge != Edge)
151       {
152         BRepClass_Edge AEdge (OtherEdge, face);
153         FClassifier.Compare (AEdge, OtherEdge.Orientation());
154         if (FClassifier.ClosestIntersection())
155         {
156           if(ParamInit > FClassifier.Parameter())
157           {
158             ParamInit = FClassifier.Parameter();
159             APointExist = Standard_True;
160           }
161         }
162       }
163     }
164
165     if (aNbEdges == 1)
166     {
167       BRepClass_Edge AEdge (Edge, face);
168       FClassifier.Compare (AEdge, Edge.Orientation());
169       if (FClassifier.ClosestIntersection())
170       {
171         if (ParamInit > FClassifier.Parameter())
172         {
173           ParamInit = FClassifier.Parameter();
174           APointExist = Standard_True;
175         }
176       }
177     }
178
179     while (APointExist)
180     { 
181       ParamInit *= 0.41234;
182       u_ = P.X() + ParamInit* T.X();
183       v_ = P.Y() + ParamInit* T.Y();
184
185       //Additional check
186       BRepTopAdaptor_FClass2d Classifier(face, Precision::Confusion());
187       gp_Pnt2d aPnt2d(u_, v_);
188       TopAbs_State StateOfResultingPoint = Classifier.Perform(aPnt2d);
189       if (StateOfResultingPoint != TopAbs_IN)
190         return Standard_False;
191       
192       BRepAdaptor_Surface s;
193       s.Initialize (face, Standard_False);
194       s.D1 (u_, v_, APoint_, theVecD1U, theVecD1V);
195
196       if(theVecD1U.CrossMagnitude(theVecD1V) > gp::Resolution())
197         return Standard_True;
198
199       if(ParamInit < Precision::PConfusion())
200         return Standard_False;
201     }
202   }
203   return Standard_False;
204 }
205
206 //=======================================================================
207 //function : PointInTheFace
208 //purpose  : 
209 //=======================================================================
210
211 Standard_Boolean BRepClass3d_SolidExplorer::PointInTheFace
212 (const TopoDS_Face& Face,
213  gp_Pnt& APoint_,
214  Standard_Real& u_, Standard_Real& v_,
215  Standard_Real& param_,
216  Standard_Integer& IndexPoint,
217  const Handle(BRepAdaptor_HSurface)& surf,
218  const Standard_Real U1,
219  const Standard_Real V1,
220  const Standard_Real U2,
221  const Standard_Real V2) const
222 {
223   gp_Vec aVecD1U, aVecD1V;
224   return PointInTheFace (Face, APoint_, u_, v_, param_, IndexPoint, surf,
225                          U1, V1, U2, V2, aVecD1U, aVecD1V);
226 }
227
228 //=======================================================================
229 //function : PointInTheFace
230 //purpose  : 
231 //=======================================================================
232
233 Standard_Boolean BRepClass3d_SolidExplorer::PointInTheFace
234 (const TopoDS_Face& Face,
235  gp_Pnt& APoint_,
236  Standard_Real& u_, Standard_Real& v_,
237  Standard_Real& param_,
238  Standard_Integer& IndexPoint,
239  const Handle(BRepAdaptor_HSurface)& surf,
240  const Standard_Real U1,
241  const Standard_Real V1,
242  const Standard_Real U2,
243  const Standard_Real V2,
244  gp_Vec& theVecD1U,
245  gp_Vec& theVecD1V) const
246 {
247   Standard_Real u,du = (U2-U1)/6.0;
248   Standard_Real v,dv = (V2-V1)/6.0;
249   if(du<1e-12) du=1e-12;
250   if(dv<1e-12) dv=1e-12;
251   Standard_Boolean IsNotUper = !surf->IsUPeriodic(), IsNotVper = !surf->IsVPeriodic();
252   Standard_Integer NbPntCalc=0;
253   if(myMapOfInter.IsBound(Face)) { 
254     void *ptr = (void*)(myMapOfInter.Find(Face));
255     Standard_Boolean IsInside = Standard_True;
256     if(IsNotUper)
257     {
258       IsInside = (u_ >= U1) && (u_ <= U2);
259     }
260     if(IsNotVper)
261     {
262       IsInside &= (v_ >= V1) && (v_ <= V2);
263     }
264     if(ptr) { 
265       const IntCurvesFace_Intersector& TheIntersector = (*((IntCurvesFace_Intersector *)ptr));
266       // Check if the point is already in the face
267       if(IsInside && (TheIntersector.ClassifyUVPoint(gp_Pnt2d(u_,v_))==TopAbs_IN)) {
268         gp_Pnt aPnt;
269         surf->D1(u_, v_, aPnt, theVecD1U, theVecD1V);
270         if (aPnt.SquareDistance(APoint_) < Precision::Confusion() * Precision::Confusion())
271           return Standard_True;
272       }
273
274       //-- Take 4 points in each Quarter of surface
275       //-- -> Index : 1 -> 16
276       //-- 
277       //--
278       //--  Then take a matrix of points on a tight grid
279       //--
280       for(u=du+(U1+U2)*0.5; u<U2; u+=du) {          //--  0  X    u increases
281         for(v=dv+(V1+V2)*0.5; v<V2; v+=dv) {        //--  0  0    v increases
282           if(++NbPntCalc>=IndexPoint) { 
283             if(TheIntersector.ClassifyUVPoint(gp_Pnt2d(u,v))==TopAbs_IN) { 
284               u_=u; v_=v;
285               surf->D1 (u, v, APoint_, theVecD1U, theVecD1V);
286               IndexPoint = NbPntCalc;
287               return(Standard_True);
288             }
289           }
290         }
291       }
292           
293       for(u=-du+(U1+U2)*0.5; u>U1; u-=du) {         //--  0  0    u decreases
294         for(v=-dv+(V1+V2)*0.5; v>V1; v-=dv) {       //--  X  0    v decreases
295           if(++NbPntCalc>=IndexPoint) {
296             if(TheIntersector.ClassifyUVPoint(gp_Pnt2d(u,v))==TopAbs_IN) { 
297               u_=u; v_=v;
298               surf->D1 (u, v, APoint_, theVecD1U, theVecD1V);
299               IndexPoint = NbPntCalc;
300               return(Standard_True);
301             }
302           }
303         }
304       }
305       for(u=-du+(U1+U2)*0.5; u>U1; u-=du) {         //--  X  0    u decreases
306         for(v=dv+(V1+V2)*0.5; v<V2; v+=dv) {        //--  0  0    v increases
307           if(++NbPntCalc>=IndexPoint) { 
308             if(TheIntersector.ClassifyUVPoint(gp_Pnt2d(u,v))==TopAbs_IN) { 
309               u_=u; v_=v;
310               surf->D1 (u, v, APoint_, theVecD1U, theVecD1V);
311               IndexPoint = NbPntCalc;
312               return(Standard_True);
313             }
314           }
315         }
316       }
317       for(u=du+(U1+U2)*0.5; u<U2; u+=du) {         //--  0  0     u increases
318         for(v=-dv+(V1+V2)*0.5; v>V1; v-=dv) {      //--  0  X     v decreases
319           if(++NbPntCalc>=IndexPoint) {
320             if(TheIntersector.ClassifyUVPoint(gp_Pnt2d(u,v))==TopAbs_IN) { 
321               u_=u; v_=v;
322               surf->D1 (u, v, APoint_, theVecD1U, theVecD1V);
323               IndexPoint = NbPntCalc;
324               return(Standard_True);
325             }
326           }
327         }
328       }
329       //-- the remainder
330       du = (U2-U1)/37.0;
331       dv = (V2-V1)/37.0;
332       if(du<1e-12) du=1e-12;
333       if(dv<1e-12) dv=1e-12;
334       
335       for(u=du+U1; u<U2; u+=du) { 
336         for(v=dv+V1; v<V2; v+=dv) {
337           if(++NbPntCalc>=IndexPoint) {
338             if(TheIntersector.ClassifyUVPoint(gp_Pnt2d(u,v))==TopAbs_IN) { 
339               u_=u; v_=v;
340               surf->D1 (u, v, APoint_, theVecD1U, theVecD1V);
341               IndexPoint = NbPntCalc;
342               return(Standard_True);
343             }
344           }
345         }
346       }
347       u=(U1+U2)*0.5;
348       v=(V1+V2)*0.5;
349       if(++NbPntCalc>=IndexPoint) {
350         if(TheIntersector.ClassifyUVPoint(gp_Pnt2d(u,v))==TopAbs_IN) { 
351           u_=u; v_=v;
352           surf->D1 (u, v, APoint_, theVecD1U, theVecD1V);
353           IndexPoint = NbPntCalc;
354           return(Standard_True);
355         }
356       }
357     }
358     IndexPoint = NbPntCalc;
359   }
360   else { 
361     //printf("BRepClass3d_SolidExplorer Face not found ds the map \n");
362   }
363
364   return BRepClass3d_SolidExplorer
365     ::FindAPointInTheFace (Face,APoint_, u_, v_, param_, theVecD1U, theVecD1V);
366 }
367
368 //=======================================================================
369 //function : LimitInfiniteUV
370 //purpose  : Limit infinite parameters
371 //=======================================================================
372 static void LimitInfiniteUV (Standard_Real& U1,
373                              Standard_Real& V1,
374                              Standard_Real& U2,
375                              Standard_Real& V2)
376 {
377   Standard_Boolean
378     infU1 = Precision::IsNegativeInfinite(U1),
379     infV1 = Precision::IsNegativeInfinite(V1),
380     infU2 = Precision::IsPositiveInfinite(U2),
381     infV2 = Precision::IsPositiveInfinite(V2);
382
383   if (infU1) U1 = -1e10;
384   if (infV1) V1 = -1e10;
385   if (infU2) U2 =  1e10;
386   if (infV2) V2 =  1e10;
387 }
388 //=======================================================================
389 //function : IsInfiniteUV
390 //purpose  : 
391 //=======================================================================
392 static Standard_Integer IsInfiniteUV (Standard_Real& U1, 
393                                       Standard_Real& V1,
394                                       Standard_Real& U2, 
395                                       Standard_Real& V2) 
396 {
397   Standard_Integer aVal = 0;
398
399   if (Precision::IsInfinite(U1))
400     aVal |= 1;
401
402   if (Precision::IsInfinite(V1))
403     aVal |= 2;
404
405   if (Precision::IsInfinite(U2))
406     aVal |= 4;
407
408   if (Precision::IsInfinite(V2))
409     aVal |= 8;
410
411   return aVal;
412 }
413 //<-OCC454
414 //  Modified by skv - Tue Sep 16 13:50:39 2003 OCC578 End
415 //=======================================================================
416 //function : OtherSegment
417 //purpose  : Returns  in <L>, <Par>  a segment having at least
418 //           one  intersection  with  the  shape  boundary  to
419 //           compute  intersections. 
420 //           The First Call to this method returns a line which
421 //           point to a point of the first face of the shape.
422 //           The Second Call provide a line to the second face
423 //           and so on. 
424 //=======================================================================
425 Standard_Integer BRepClass3d_SolidExplorer::OtherSegment(const gp_Pnt& P, 
426                                                          gp_Lin& L, 
427                                                          Standard_Real& _Par) 
428 {
429   const Standard_Real TolU = Precision::PConfusion();
430   const Standard_Real TolV = TolU;
431
432   TopoDS_Face         face;
433   TopExp_Explorer     faceexplorer;
434   gp_Pnt APoint;
435   gp_Vec aVecD1U, aVecD1V;
436   Standard_Real maxscal=0;
437   Standard_Boolean ptfound=Standard_False;
438   Standard_Real Par;
439   Standard_Real _u,_v;
440   Standard_Integer IndexPoint=0;
441   Standard_Integer NbPointsOK=0;
442   Standard_Integer NbFacesInSolid=0;
443   Standard_Boolean aRestr = Standard_True;
444   Standard_Boolean aTestInvert = Standard_False;
445
446   for(;;) { 
447     myFirstFace++; 
448     faceexplorer.Init(myShape,TopAbs_FACE);
449     // look for point on face starting from myFirstFace
450 //  Modified by skv - Thu Sep  4 14:31:12 2003 OCC578 Begin
451 //     while (faceexplorer.More()) {
452     NbFacesInSolid = 0;
453     for (; faceexplorer.More(); faceexplorer.Next()) {
454 //  Modified by skv - Thu Sep  4 14:31:12 2003 OCC578 End
455       NbFacesInSolid++;
456       if (myFirstFace > NbFacesInSolid) continue;
457       face = TopoDS::Face(faceexplorer.Current());
458
459       Handle(BRepAdaptor_HSurface) surf = new BRepAdaptor_HSurface();
460       if(aTestInvert)
461       {
462         BRepTopAdaptor_FClass2d aClass(face, Precision::Confusion());
463         if(aClass.PerformInfinitePoint() == TopAbs_IN)
464         {
465           aRestr = Standard_False;
466           if(myMapOfInter.IsBound(face))
467           {
468             myMapOfInter.UnBind(face);
469             void *ptr = (void *)(new IntCurvesFace_Intersector(face, Precision::Confusion(),
470                                                                aRestr, Standard_False));
471             myMapOfInter.Bind(face,ptr);
472           }
473         }
474         else
475         {
476           aRestr = Standard_True;
477         }
478       }
479       surf->ChangeSurface().Initialize(face, aRestr);
480       Standard_Real U1,V1,U2,V2;
481       U1 = surf->FirstUParameter();
482       V1 = surf->FirstVParameter();
483       U2 = surf->LastUParameter();
484       V2 = surf->LastVParameter();
485       face.Orientation(TopAbs_FORWARD);
486       //
487       //avoid process faces from uncorrected shells
488       const Standard_Real eps = Precision::PConfusion();
489       Standard_Real epsU = Max(eps * Max(Abs(U2), Abs(U1)), eps);
490       Standard_Real epsV = Max(eps * Max(Abs(V2), Abs(V1)), eps);
491       if( Abs (U2 - U1) < epsU || Abs(V2 - V1) < epsV) {
492         return 2;
493       }
494       //
495       Standard_Real svmyparam=myParamOnEdge;
496       //
497       // Check if the point is on the face or the face is infinite.
498       Standard_Integer anInfFlag = IsInfiniteUV(U1,V1,U2,V2);
499       // default values
500       _u = (U1 + U2) * 0.5;
501       _v = (V1 + V2) * 0.5;
502
503       GeomAdaptor_Surface GA(BRep_Tool::Surface(face));
504       Extrema_ExtPS Ext(P, GA, TolU, TolV);
505       //
506       if (Ext.IsDone() && Ext.NbExt() > 0) {
507         Standard_Integer i, iNear,  iEnd;
508         Standard_Real  aUx, aVx, Dist2, Dist2Min;
509         Extrema_POnSurf aPx;
510         //
511         iNear = 1;
512         Dist2Min = Ext.SquareDistance(1);
513         iEnd = Ext.NbExt();
514         for (i = 2; i <= iEnd; i++) {
515           aPx=Ext.Point(i);
516           aPx.Parameter(aUx, aVx);
517           if (aUx>=U1 && aUx<=U2 && aVx>=V1 && aVx<=V2) {
518             Dist2 = Ext.SquareDistance(i);
519             if (Dist2 < Dist2Min) {
520               Dist2Min = Dist2; 
521               iNear = i;
522             }
523           }
524         }
525         //
526         Standard_Real aDist2Tresh=1.e-24;
527         //
528         if (Dist2Min<aDist2Tresh) {
529           if (anInfFlag) {
530             return 1;
531           } 
532           else {
533             BRepClass_FaceClassifier classifier2d;
534             Standard_Real            aU;
535             Standard_Real            aV;
536
537             (Ext.Point(iNear)).Parameter(aU, aV);
538
539             gp_Pnt2d aPuv(aU, aV);
540
541             classifier2d.Perform(face,aPuv,Precision::PConfusion());
542
543             TopAbs_State aState = classifier2d.State();
544
545             if (aState == TopAbs_IN || aState == TopAbs_ON) {
546               return 1;
547             }
548             else {
549               return 3; // skv - the point is on surface but outside face.
550             }
551           }
552         }
553         if (anInfFlag) {
554           APoint = (Ext.Point(iNear)).Value();
555           gp_Vec V(P,APoint);
556           _Par = V.Magnitude(); 
557           L = gp_Lin(P,V);
558           ptfound=Standard_True;
559           return 0;
560         }
561
562         // set the parameters found by extrema
563         aPx = Ext.Point(iNear);
564         aPx.Parameter(_u, _v);
565         APoint = aPx.Value();
566       }
567       //The point is not ON the face or surface. The face is restricted.
568       // find point in a face not too far from a projection of P on face
569       do {
570         if (PointInTheFace (face, APoint, _u, _v, myParamOnEdge, ++IndexPoint, surf,
571                             U1, V1, U2, V2,
572                             aVecD1U, aVecD1V))
573         {
574           ++NbPointsOK;
575           gp_Vec V (P, APoint);
576           Par = V.Magnitude();
577           if (Par > gp::Resolution() &&
578               aVecD1U.Magnitude() > gp::Resolution() &&
579               aVecD1V.Magnitude() > gp::Resolution())
580           {
581             gp_Vec Norm = aVecD1U.Crossed (aVecD1V);
582             Standard_Real tt = Norm.Magnitude();
583             tt = Abs (Norm.Dot (V)) / (tt * Par);
584             if (tt > maxscal)
585             {
586               maxscal = tt;
587               L = gp_Lin (P, V);
588               _Par = Par;
589               ptfound = Standard_True;
590               if (maxscal>0.2)
591               {
592                 myParamOnEdge=svmyparam;
593                 return 0;
594               }
595             }
596           }
597         }
598       }
599       while(IndexPoint<200 && NbPointsOK<16);
600
601       myParamOnEdge=svmyparam;
602       if(maxscal>0.2) {                  
603         return 0;
604       }
605
606
607       //  Modified by skv - Thu Sep  4 14:32:14 2003 OCC578 Begin
608       // Next is done in the main for(..) loop.
609       //       faceexplorer.Next();
610       //  Modified by skv - Thu Sep  4 14:32:14 2003 OCC578 End
611       IndexPoint = 0;
612
613       Standard_Boolean encoreuneface = faceexplorer.More();
614       if(ptfound==Standard_False && encoreuneface==Standard_False) { 
615         if(myParamOnEdge < 0.0001) { 
616           //-- This case takes place when the point is on the solid
617           //-- and this solid is reduced to a face 
618           gp_Pnt PBidon(P.X()+1.0,P.Y(),P.Z());
619           gp_Vec V(P,PBidon);
620           Par= 1.0;
621           _Par=Par;
622           L  = gp_Lin(P,V);
623           return 0;
624         }
625       }
626     } //-- Exploration of the faces   
627
628     if(NbFacesInSolid==0) { 
629       _Par=0.0;
630       myReject=Standard_True;
631 #ifdef OCCT_DEBUG
632       cout<<"\nWARNING : BRepClass3d_SolidExplorer.cxx  (Solid without face)"<<endl;
633 #endif  
634       return 0;
635     }
636
637     if(ptfound) {
638       return 0;
639     }
640     myFirstFace = 0;
641     if(myParamOnEdge==0.512345)  myParamOnEdge = 0.4;
642     else if(myParamOnEdge==0.4)  myParamOnEdge = 0.6; 
643     else if(myParamOnEdge==0.6)  myParamOnEdge = 0.3; 
644     else if(myParamOnEdge==0.3)  myParamOnEdge = 0.7; 
645     else if(myParamOnEdge==0.7)  myParamOnEdge = 0.2; 
646     else if(myParamOnEdge==0.2)  myParamOnEdge = 0.8; 
647     else if(myParamOnEdge==0.8)  myParamOnEdge = 0.1; 
648     else if(myParamOnEdge==0.1)  myParamOnEdge = 0.9;
649     //
650     else {
651       myParamOnEdge*=0.5;  
652       if(myParamOnEdge < 0.0001) { 
653         gp_Pnt PBidon(P.X()+1.0,P.Y(),P.Z());
654         gp_Vec V(P,PBidon);
655         Par= 1.0;
656         _Par=Par;
657         L  = gp_Lin(P,V);
658         return 0;
659       }
660     }
661     aTestInvert = Standard_True;
662   } //-- for(;;) { ...  } 
663 }
664
665 //  Modified by skv - Thu Sep  4 12:30:14 2003 OCC578 Begin
666 //=======================================================================
667 //function : GetFaceSegmentIndex
668 //purpose  : Returns the index of face for which last segment is calculated.
669 //=======================================================================
670
671 Standard_Integer BRepClass3d_SolidExplorer::GetFaceSegmentIndex() const
672 {
673   return myFirstFace;
674 }
675 //  Modified by skv - Thu Sep  4 12:30:14 2003 OCC578 End
676
677 //=======================================================================
678 //function : PointInTheFace
679 //purpose  : 
680 //=======================================================================
681
682 Standard_Boolean BRepClass3d_SolidExplorer::PointInTheFace
683 (const TopoDS_Face& _face,
684  gp_Pnt& APoint_,
685  Standard_Real& u_, Standard_Real& v_,
686  Standard_Real& param_,
687  Standard_Integer& IndexPoint) const  
688 {   
689   TopoDS_Face Face = _face;
690   Face.Orientation(TopAbs_FORWARD);
691   Handle(BRepAdaptor_HSurface) surf = new BRepAdaptor_HSurface();
692   surf->ChangeSurface().Initialize(Face);
693   Standard_Real U1,V1,U2,V2;//,u,v;
694   U1 = surf->FirstUParameter();
695   V1 = surf->FirstVParameter();
696   U2 = surf->LastUParameter();
697   V2 = surf->LastVParameter();
698   LimitInfiniteUV (U1,V1,U2,V2);
699   return(PointInTheFace(Face,APoint_,u_,v_,param_,IndexPoint,surf,U1,V1,U2,V2));
700 }
701
702 //=======================================================================
703 //function : FindAPointInTheFace
704 //purpose  : 
705 //=======================================================================
706
707 Standard_Boolean BRepClass3d_SolidExplorer::FindAPointInTheFace
708 (const TopoDS_Face& _face,
709  gp_Pnt& APoint_,
710  Standard_Real& u_,Standard_Real& v_) 
711 {
712   Standard_Real param = 0.1;
713   Standard_Boolean r = FindAPointInTheFace(_face,APoint_,u_,v_,param);
714   return r;
715 }
716
717 //=======================================================================
718 //function : FindAPointInTheFace
719 //purpose  : 
720 //=======================================================================
721
722 Standard_Boolean BRepClass3d_SolidExplorer::FindAPointInTheFace
723 (const TopoDS_Face& _face,
724  gp_Pnt& APoint_) 
725 { Standard_Real u,v;
726   Standard_Boolean r = FindAPointInTheFace(_face,APoint_,u,v);
727   return r;
728 }
729
730 //=======================================================================
731 //function : FindAPointInTheFace
732 //purpose  : 
733 //=======================================================================
734
735 Standard_Boolean BRepClass3d_SolidExplorer::FindAPointInTheFace
736 (const TopoDS_Face& _face,
737  Standard_Real& u_,Standard_Real& v_) 
738 { gp_Pnt APoint;
739   Standard_Boolean r = FindAPointInTheFace(_face,APoint,u_,v_);
740   return r;
741 }
742
743 //=======================================================================
744 //function : BRepClass3d_SolidExplorer
745 //purpose  : 
746 //=======================================================================
747
748 BRepClass3d_SolidExplorer::BRepClass3d_SolidExplorer() 
749 {
750 }
751 #include <Standard_ConstructionError.hxx>
752
753 //=======================================================================
754 //function : BRepClass3d_SolidExplorer
755 //purpose  : Raise if called.
756 //=======================================================================
757
758 //BRepClass3d_SolidExplorer::BRepClass3d_SolidExplorer(const BRepClass3d_SolidExplorer& Oth) 
759 BRepClass3d_SolidExplorer::BRepClass3d_SolidExplorer(const BRepClass3d_SolidExplorer& ) 
760 {
761   Standard_ConstructionError::Raise("Magic constructor not allowed");
762 }
763
764 //=======================================================================
765 //function : BRepClass3d_SolidExplorer
766 //purpose  : 
767 //=======================================================================
768
769 BRepClass3d_SolidExplorer::BRepClass3d_SolidExplorer(const TopoDS_Shape& S)
770 {
771   InitShape(S);
772 }
773
774 //=======================================================================
775 //function : ~BRepClass3d_SolidExplorer
776 //purpose  :
777 //=======================================================================
778
779 BRepClass3d_SolidExplorer::~BRepClass3d_SolidExplorer()
780 {
781  Destroy() ;
782 }
783
784 //=======================================================================
785 //function : Destroy
786 //purpose  : C++: alias ~
787 //=======================================================================
788
789 void BRepClass3d_SolidExplorer::Destroy() { 
790   BRepClass3d_DataMapIteratorOfMapOfInter iter(myMapOfInter);
791   for(;iter.More();iter.Next()) { 
792     void *ptr=iter.Value();
793     if(ptr) { 
794       delete (IntCurvesFace_Intersector *)ptr;
795       myMapOfInter.ChangeFind(iter.Key()) = NULL;
796     }
797   }
798   myMapOfInter.Clear();
799 }
800
801 //=======================================================================
802 //function : InitShape
803 //purpose  : 
804 //=======================================================================
805
806 void BRepClass3d_SolidExplorer::InitShape(const TopoDS_Shape& S)
807 {
808   myMapEV.Clear();
809   myTree.Clear();
810
811   myShape = S;
812   myFirstFace = 0;
813   myParamOnEdge = 0.512345;
814   //-- Exploring of the Map and removal of allocated objects
815   
816   
817   BRepClass3d_DataMapIteratorOfMapOfInter iter(myMapOfInter);
818   for(;iter.More();iter.Next()) { 
819     void *ptr=iter.Value();
820     if(ptr) { 
821       delete (IntCurvesFace_Intersector *)ptr;
822       myMapOfInter.ChangeFind(iter.Key()) = NULL;
823     }
824   }
825   
826   myMapOfInter.Clear();
827   
828   myReject = Standard_True; //-- case of infinite solid (without any face)
829
830   TopExp_Explorer Expl;
831   for(Expl.Init(S,TopAbs_FACE);
832       Expl.More();
833       Expl.Next()) { 
834     const TopoDS_Face Face = TopoDS::Face(Expl.Current());
835     void *ptr = (void *)(new IntCurvesFace_Intersector(Face,Precision::Confusion(),Standard_True, Standard_False));
836     myMapOfInter.Bind(Face,ptr);
837     myReject=Standard_False;  //-- at least one face in the solid 
838   }
839   
840 #ifdef OCCT_DEBUG
841   if(myReject) { 
842     cout<<"\nWARNING : BRepClass3d_SolidExplorer.cxx  (Solid without face)"<<endl;
843   }
844 #endif
845
846 #if REJECTION
847   BRepBndLib::Add(myShape,myBox);
848 #endif
849
850   // Fill mapEV with vertices and edges from shape.
851   TopExp::MapShapes(myShape, TopAbs_EDGE, myMapEV);
852   TopExp::MapShapes(myShape, TopAbs_VERTEX, myMapEV);  
853
854   NCollection_UBTreeFiller <Standard_Integer, Bnd_Box> aTreeFiller (myTree);
855
856   for (Standard_Integer i = 1; i <= myMapEV.Extent(); i++)
857   {
858     Bnd_Box B;
859     const TopoDS_Shape& Sh = myMapEV(i);
860     TopAbs_Orientation ori = Sh.Orientation();
861     if (ori == TopAbs_EXTERNAL || ori == TopAbs_INTERNAL)
862       continue;
863     if (Sh.ShapeType() == TopAbs_EDGE && BRep_Tool::Degenerated(TopoDS::Edge(Sh)))
864       continue;
865     BRepBndLib::Add(Sh,B);
866     aTreeFiller.Add(i, B);
867   }
868   aTreeFiller.Fill();
869 }
870
871 //=======================================================================
872 //function : Reject
873 //purpose  : Should return True if P outside of bounding vol. of the shape
874 //=======================================================================
875
876 //Standard_Boolean  BRepClass3d_SolidExplorer::Reject(const gp_Pnt& P) const 
877 Standard_Boolean  BRepClass3d_SolidExplorer::Reject(const gp_Pnt& ) const 
878 {
879   return(myReject);  // case of solid without face 
880 }
881
882 //=======================================================================
883 //function : InitShell
884 //purpose  : Starts an exploration of the shells.
885 //=======================================================================
886
887 void BRepClass3d_SolidExplorer::InitShell()  
888 {
889   myShellExplorer.Init(myShape,TopAbs_SHELL);
890 }
891
892 //=======================================================================
893 //function : MoreShell
894 //purpose  : Returns True if there is a current shell. 
895 //=======================================================================
896
897 Standard_Boolean BRepClass3d_SolidExplorer::MoreShell() const 
898
899   return(myShellExplorer.More());
900 }
901
902 //=======================================================================
903 //function : NextShell
904 //purpose  : Sets the explorer to the next shell.
905 //=======================================================================
906
907 void BRepClass3d_SolidExplorer::NextShell() 
908
909   myShellExplorer.Next();
910 }
911
912 //=======================================================================
913 //function : CurrentShell
914 //purpose  : Returns the current shell.
915 //=======================================================================
916
917 TopoDS_Shell BRepClass3d_SolidExplorer::CurrentShell() const 
918
919   return(TopoDS::Shell(myShellExplorer.Current()));
920 }
921
922 //=======================================================================
923 //function : RejectShell
924 //purpose  : Returns True if the Shell is rejected.
925 //=======================================================================
926
927 Standard_Boolean BRepClass3d_SolidExplorer::RejectShell(const gp_Lin& ) const
928
929   return(Standard_False); 
930 }
931
932 //=======================================================================
933 //function : InitFace
934 //purpose  : Starts an exploration of the faces of the current shell.
935 //=======================================================================
936
937 void BRepClass3d_SolidExplorer::InitFace()  
938 {
939   myFaceExplorer.Init(TopoDS::Shell(myShellExplorer.Current()),TopAbs_FACE);
940 }
941
942 //=======================================================================
943 //function : MoreFace
944 //purpose  : Returns True if current face in current shell. 
945 //=======================================================================
946
947 Standard_Boolean BRepClass3d_SolidExplorer::MoreFace() const 
948
949   return(myFaceExplorer.More());
950 }
951
952 //=======================================================================
953 //function : NextFace
954 //purpose  : Sets the explorer to the next Face of the current shell.
955 //=======================================================================
956
957 void BRepClass3d_SolidExplorer::NextFace() 
958
959   myFaceExplorer.Next();
960 }
961
962 //=======================================================================
963 //function : CurrentFace
964 //purpose  : Returns the current face.
965 //=======================================================================
966
967 TopoDS_Face BRepClass3d_SolidExplorer::CurrentFace() const 
968
969   return(TopoDS::Face(myFaceExplorer.Current()));
970 }
971
972 //=======================================================================
973 //function : RejectFace
974 //purpose  : returns True if the face is rejected.
975 //=======================================================================
976
977 Standard_Boolean BRepClass3d_SolidExplorer::RejectFace(const gp_Lin& ) const 
978
979   return(Standard_False); 
980 }
981
982 #ifdef OCCT_DEBUG
983 #include <TopAbs_State.hxx>
984 #endif
985
986 //=======================================================================
987 //function : Segment
988 //purpose  : Returns  in <L>, <Par>  a segment having at least
989 //           one  intersection  with  the  shape  boundary  to
990 //           compute  intersections. 
991 //=======================================================================
992 Standard_Integer  BRepClass3d_SolidExplorer::Segment(const gp_Pnt& P, 
993                                                      gp_Lin& L, 
994                                                      Standard_Real& Par)  
995 {
996   Standard_Integer bRetFlag;
997   myFirstFace = 0;
998   bRetFlag=OtherSegment(P,L,Par);
999   return bRetFlag;
1000 }
1001
1002 //=======================================================================
1003 //function : Intersector
1004 //purpose  : 
1005 //=======================================================================
1006
1007 IntCurvesFace_Intersector&  BRepClass3d_SolidExplorer::Intersector(const TopoDS_Face& F) const  { 
1008   void *ptr = (void*)(myMapOfInter.Find(F));
1009   IntCurvesFace_Intersector& curr = (*((IntCurvesFace_Intersector *)ptr));
1010   return curr;
1011 }
1012
1013 //=======================================================================
1014 //function : Box
1015 //purpose  : 
1016 //=======================================================================
1017
1018 const Bnd_Box& BRepClass3d_SolidExplorer::Box() const { 
1019   return(myBox);
1020 }
1021
1022 //=======================================================================
1023 //function : DumpSegment
1024 //purpose  : 
1025 //=======================================================================
1026
1027 void BRepClass3d_SolidExplorer::DumpSegment(const gp_Pnt&,
1028                                             const gp_Lin&,
1029                                             const Standard_Real,
1030                                             const TopAbs_State) const
1031 {
1032 #ifdef OCCT_DEBUG
1033  
1034 #endif
1035 }
1036
1037 const TopoDS_Shape& BRepClass3d_SolidExplorer::GetShape() const 
1038
1039   return(myShape);
1040 }