1dfc9264394863e09c13897d916ddafc91e15052
[occt.git] / src / BRepClass3d / BRepClass3d_SClassifier.cxx
1 // Created on: 1996-07-15
2 // Created by: Laurent BUCHARD
3 // Copyright (c) 1996-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 //  Modified by skv - Thu Sep  4 11:22:05 2003 OCC578
18
19 #include <BRep_Tool.hxx>
20 #include <BRepClass3d_Intersector3d.hxx>
21 #include <BRepClass3d_SClassifier.hxx>
22 #include <BRepClass3d_SolidExplorer.hxx>
23 #include <BRepTopAdaptor_FClass2d.hxx>
24 #include <ElCLib.hxx>
25 #include <Geom_Surface.hxx>
26 #include <gp_Lin.hxx>
27 #include <gp_Pnt.hxx>
28 #include <gp_Vec.hxx>
29 #include <IntCurvesFace_Intersector.hxx>
30 #include <math_BullardGenerator.hxx>
31 #include <Standard_DomainError.hxx>
32 #include <TopoDS.hxx>
33 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
34 #include <TopTools_MapOfShape.hxx>
35 #include <TopExp.hxx>
36 #include <BRepAdaptor_Surface.hxx>
37 #include <Extrema_ExtPS.hxx>
38
39 #include <vector>
40
41 // modified by NIZHNY-MKK  Mon Jun 21 15:13:40 2004
42 static
43   Standard_Boolean FaceNormal (const TopoDS_Face& aF,
44                                const Standard_Real U,
45                                const Standard_Real V,
46                                gp_Dir& aDN);
47
48 static 
49   Standard_Real GetAddToParam(const gp_Lin& L,const Standard_Real P,const Bnd_Box& B);
50
51 //gets transition of line <L> passing through/near the edge <e> of faces <f1>, <f2>. <param> is
52 // a parameter on the edge where the minimum distance between <l> and <e> was found
53 static Standard_Integer GetTransi(const TopoDS_Face& f1, const TopoDS_Face& f2, const TopoDS_Edge e,
54                      Standard_Real param, const gp_Lin& L, IntCurveSurface_TransitionOnCurve& trans);
55
56 static Standard_Boolean GetNormalOnFaceBound(const TopoDS_Edge& E, const TopoDS_Face& F, Standard_Real param, gp_Dir& OutDir);
57
58 static void Trans(Standard_Real parmin, IntCurveSurface_TransitionOnCurve& tran, int& state);
59
60 //=======================================================================
61 //function : BRepClass3d_SClassifier
62 //purpose  : 
63 //=======================================================================
64 BRepClass3d_SClassifier::BRepClass3d_SClassifier() 
65
66 }
67
68
69 //=======================================================================
70 //function : BRepClass3d_SClassifier
71 //purpose  : 
72 //=======================================================================
73 BRepClass3d_SClassifier::BRepClass3d_SClassifier(BRepClass3d_SolidExplorer& S,
74                                                  const gp_Pnt&  P,
75                                                  const Standard_Real Tol) { 
76   if(S.Reject(P)) { 
77     myState=3; //-- in ds solid case without face 
78   }
79   else { 
80     Perform(S,P,Tol);
81   }
82 }
83
84
85 //=======================================================================
86 //function : PerformInfinitePoint
87 //purpose  : 
88 //=======================================================================
89 void BRepClass3d_SClassifier::PerformInfinitePoint(BRepClass3d_SolidExplorer& aSE,
90                                                    const Standard_Real /*Tol*/) {
91
92   //Take a normal to the first extracted face in its random inner point
93   //and intersect this reversed normal with the faces of the solid.
94   //If the min.par.-intersection point is
95   // a) inner point of a face
96   // b) transition is not TANGENT
97   //    (the line does not touch the face but pierces it)
98   //then set <myState> to IN or OUT according to transition
99   //else take the next random point inside the min.par.-intersected face
100   //and continue
101   
102   if(aSE.Reject(gp_Pnt(0,0,0))) { 
103     myState=3; //-- in ds solid case without face 
104     return;
105   }
106   //
107   //------------------------------------------------------------
108   // 1
109   Standard_Boolean bFound;
110   Standard_Real aParam, aU = 0., aV = 0.;
111   gp_Pnt aPoint;
112   gp_Dir aDN;
113
114   math_BullardGenerator aRandomGenerator;
115   myFace.Nullify();
116   myState=2;
117
118   // Collect faces in sequence to iterate
119   std::vector<TopoDS_Face> aFaces;
120   for (aSE.InitShell(); aSE.MoreShell(); aSE.NextShell())
121   {
122     for (aSE.InitFace(); aSE.MoreFace(); aSE.NextFace())
123     {
124       aFaces.push_back (aSE.CurrentFace());
125     }
126   }
127
128   // iteratively try up to 10 probing points from each face
129   const Standard_Integer NB_MAX_POINTS_PER_FACE = 10;
130   for (Standard_Integer itry = 0; itry < NB_MAX_POINTS_PER_FACE; itry++)
131   {
132     for (std::vector<TopoDS_Face>::iterator iFace = aFaces.begin(); iFace != aFaces.end(); ++iFace)
133     {
134       TopoDS_Face aF = *iFace;
135
136       TopAbs_State aState = TopAbs_OUT;
137       IntCurveSurface_TransitionOnCurve aTransition = IntCurveSurface_Tangent;
138
139       aParam = 0.1 + 0.8 * aRandomGenerator.NextReal(); // random number in range [0.1, 0.9]
140       bFound = aSE.FindAPointInTheFace(aF, aPoint, aU, aV, aParam);
141       if (!bFound || !FaceNormal(aF, aU, aV, aDN))
142         continue;
143
144       gp_Lin aLin(aPoint, -aDN);
145       Standard_Real parmin = RealLast();
146       for (aSE.InitShell();aSE.MoreShell();aSE.NextShell()) { 
147         if (aSE.RejectShell(aLin) == Standard_False) { 
148           for (aSE.InitFace();aSE.MoreFace(); aSE.NextFace()) {
149             if (aSE.RejectFace(aLin) == Standard_False) { 
150               TopoDS_Shape aLocalShape = aSE.CurrentFace();
151               TopoDS_Face CurFace = TopoDS::Face(aLocalShape);
152               IntCurvesFace_Intersector& Intersector3d = aSE.Intersector(CurFace);
153               Intersector3d.Perform(aLin,-RealLast(),parmin); 
154
155               if(Intersector3d.IsDone()) {
156                 if(Intersector3d.NbPnt()) { 
157                   Standard_Integer imin = 1;
158                   for (Standard_Integer i = 2; i <= Intersector3d.NbPnt(); i++)
159                     if (Intersector3d.WParameter(i) < Intersector3d.WParameter(imin))
160                       imin = i;
161                   parmin = Intersector3d.WParameter(imin);
162                   aState = Intersector3d.State(imin);
163                   aTransition = Intersector3d.Transition(imin);
164                 }
165               }
166             }
167           }
168         }
169         else
170           myState = 1;
171       } //end of loop on the whole solid
172         
173       if (aState == TopAbs_IN)
174       {
175         if (aTransition == IntCurveSurface_Out) { 
176           //-- The line is going from inside the solid to outside 
177           //-- the solid.
178           myState = 3; //-- IN --
179           return;
180         }
181         else if (aTransition == IntCurveSurface_In) { 
182           myState = 4; //-- OUT --
183           return;
184         }
185       }
186     } // iteration by faces
187   } // iteration by points
188 }
189
190 //=======================================================================
191 //function : Perform
192 //purpose  : 
193 //=======================================================================
194 void BRepClass3d_SClassifier::Perform(BRepClass3d_SolidExplorer& SolidExplorer,
195                                       const gp_Pnt&  P,
196                                       const Standard_Real Tol)
197
198   if(SolidExplorer.Reject(P))
199   {
200     // Solid without faces => the whole space. Always in.
201     myState = 3; // IN
202     return;
203   }
204
205   const BRepClass3d_BndBoxTree & aTree = SolidExplorer.GetTree();
206   const TopTools_IndexedMapOfShape & aMapEV = SolidExplorer.GetMapEV();
207
208   // Vertices/Edges vs Point.
209   BRepClass3d_BndBoxTreeSelectorPoint aSelectorPoint(aMapEV);
210   aSelectorPoint.SetCurrentPoint(P);
211
212   Standard_Integer SelsVE = 0;
213   SelsVE = aTree.Select(aSelectorPoint); 
214
215   if (SelsVE > 0)
216   {
217     // The point P lays inside the tolerance area of vertices/edges => return ON state.
218     myState = 2; // ON.
219     return;
220   }
221
222   TopTools_IndexedDataMapOfShapeListOfShape mapEF;
223   TopExp::MapShapesAndAncestors(SolidExplorer.GetShape(), TopAbs_EDGE, TopAbs_FACE, mapEF);
224   
225   BRepClass3d_BndBoxTreeSelectorLine aSelectorLine(aMapEV);
226
227   myFace.Nullify();
228   myState = 0;
229
230   gp_Lin L;
231   Standard_Real Par;
232
233   // We compute the intersection between the line built in the Solid Explorer and the shape.
234   //-- --------------------------------------------------------------------------------
235   // Calculate intersection with the face closest to the direction of bounding boxes 
236   // by priority so that to have the smallest possible parmin.
237   // Optimization to produce as much as possible rejections with other faces.
238   Standard_Integer iFlag;
239
240   // If found line passes through a bound of any face, it means that the line
241   // is not found properly and it is necessary to repeat whole procedure.
242   // That's why the main loop while is added.
243   Standard_Boolean isFaultyLine = Standard_True;
244   Standard_Integer anIndFace    = 0;
245   Standard_Real    parmin = 0.0;
246   while (isFaultyLine)
247   {
248     if (anIndFace == 0)
249       iFlag = SolidExplorer.Segment(P,L,Par);
250     else
251       iFlag = SolidExplorer.OtherSegment(P,L,Par);
252
253     Standard_Integer aCurInd = SolidExplorer.GetFaceSegmentIndex();
254
255     if (aCurInd > anIndFace)
256       anIndFace = aCurInd;
257     else
258     {
259       myState = 1; // Faulty.
260       return;
261     }
262
263     if (iFlag==1)
264     {
265       // IsOnFace iFlag==1 i.e face is Infinite
266       myState = 2; // ON.
267       return;
268     }
269     if (iFlag == 2) 
270     {
271       myState = 4; // OUT.
272       return;
273     }
274
275     // Check if the point is ON surface but OUT of the face.
276     // Just skip this face because it is bad for classification.
277     if (iFlag == 3)
278       continue;
279
280     isFaultyLine = Standard_False;
281     parmin = RealLast();
282
283     Standard_Real NearFaultPar = RealLast(); // Parameter on line.
284     aSelectorLine.ClearResults();
285     aSelectorLine.SetCurrentLine(L, Par);
286     Standard_Integer SelsEVL = 0;
287     SelsEVL = aTree.Select(aSelectorLine); //SelsEE > 0 => Line/Edges & Line/Vertex intersection
288      
289     if (SelsEVL > 0 )
290     {    
291       // Line and edges / vertices interference.
292       Standard_Integer VLInterNb = aSelectorLine.GetNbVertParam();
293       TopoDS_Vertex NearIntVert;
294       TopTools_MapOfShape LVInts;
295       for (Standard_Integer i = 1; i <= VLInterNb; i++)
296       {
297         // Line and vertex.
298         Standard_Real LP = 0;
299         TopoDS_Vertex V;
300         aSelectorLine.GetVertParam(i, V, LP);
301
302         LVInts.Add(V);
303         if (Abs(LP) < Abs(NearFaultPar))
304           NearFaultPar = LP;
305       }
306
307       Standard_Real param = 0.0;
308       TopoDS_Edge EE;
309       Standard_Real Lpar = RealLast();
310       for (Standard_Integer i = 1; i <= aSelectorLine.GetNbEdgeParam(); i++)
311       {
312         // Line and edge.
313         aSelectorLine.GetEdgeParam(i, EE, param, Lpar);
314         const TopTools_ListOfShape& ffs = mapEF.FindFromKey(EE); //ffs size == 2
315         if (ffs.Extent() != 2)
316           continue;
317         TopoDS_Face f1 = TopoDS::Face(ffs.First());
318         TopoDS_Face f2 = TopoDS::Face(ffs.Last());
319         TopoDS_Vertex V1, V2;
320         TopExp::Vertices(EE, V1, V2);
321         if (LVInts.Contains(V1) || LVInts.Contains(V2))
322         {
323           continue;
324         }
325
326         IntCurveSurface_TransitionOnCurve tran = IntCurveSurface_Tangent;
327         Standard_Integer Tst = GetTransi(f1, f2, EE, param, L, tran);
328         if (Tst == 1 && Abs(Lpar) < Abs(parmin))
329         {
330           parmin = Lpar;
331           Trans(parmin, tran, myState);
332         }
333         else if (Abs(Lpar) < Abs(NearFaultPar))
334           NearFaultPar = Lpar;
335       }
336     }
337
338     for(SolidExplorer.InitShell();
339         SolidExplorer.MoreShell() && !isFaultyLine;
340         SolidExplorer.NextShell())
341     {
342         if(SolidExplorer.RejectShell(L) == Standard_False)
343         {
344           for (SolidExplorer.InitFace();
345             SolidExplorer.MoreFace() && !isFaultyLine;
346             SolidExplorer.NextFace())
347           {
348             if (SolidExplorer.RejectFace(L) == Standard_False)
349             {
350               TopoDS_Shape aLocalShape = SolidExplorer.CurrentFace();
351               TopoDS_Face f = TopoDS::Face(aLocalShape);
352               IntCurvesFace_Intersector& Intersector3d = SolidExplorer.Intersector(f);
353
354               // Prolong segment, since there are cases when
355               // the intersector does not find intersection points with the original
356               // segment due to rough triangulation of a parameterized surface.
357               Standard_Real addW = Max(10 * Tol, 0.01*Par);
358               Standard_Real AddW = addW;
359
360               Bnd_Box aBoxF = Intersector3d.Bounding();
361
362               // The box must be finite in order to correctly prolong the segment to its bounds.
363               if (!aBoxF.IsVoid() && !aBoxF.IsWhole())
364               {
365                 Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
366                 aBoxF.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
367
368                 Standard_Real boxaddW = GetAddToParam(L, Par, aBoxF);
369                 addW = Max(addW, boxaddW);
370               }
371
372               Standard_Real minW = -AddW;
373               Standard_Real maxW = Min(Par * 10, Par + addW);
374               Intersector3d.Perform(L, minW, maxW);
375               if (Intersector3d.IsDone())
376               {
377                 if (Intersector3d.NbPnt() == 0)
378                 {
379                   if (Intersector3d.IsParallel())
380                   {
381                     //Check distance between surface and point
382                     BRepAdaptor_Surface aBAS(f, Standard_False);
383                     Extrema_ExtPS aProj(P, aBAS, Precision::PConfusion(), Precision::PConfusion());
384                     if (aProj.IsDone() && aProj.NbExt() > 0)
385                     {
386                       Standard_Integer i, indmin = 0;
387                       Standard_Real d = RealLast();
388                       for (i = 1; i <= aProj.NbExt(); ++i)
389                       {
390                         if (aProj.SquareDistance(i) < d)
391                         {
392                           d = aProj.SquareDistance(i);
393                           indmin = i;
394                         }
395                       }
396                       if (indmin > 0)
397                       {
398                         if (d <= Tol * Tol)
399                         {
400                           const Extrema_POnSurf& aPonS = aProj.Point(indmin);
401                           Standard_Real anU, anV;
402                           aPonS.Parameter(anU, anV);
403                           gp_Pnt2d aP2d(anU, anV);
404                           TopAbs_State aSt = Intersector3d.ClassifyUVPoint(aP2d);
405                           if (aSt == TopAbs_IN || aSt == TopAbs_ON)
406                           {
407                             myState = 2;
408                             myFace = f;
409                             parmin = 0.;
410                             break;
411                           }
412                         }
413                       }
414                     }
415                   }
416                 }
417                 for (Standard_Integer i = 1; i <= Intersector3d.NbPnt(); i++)
418                 {
419                   if (Abs(Intersector3d.WParameter(i)) < Abs(parmin) - Precision::PConfusion())
420                   {
421                     parmin = Intersector3d.WParameter(i);
422                     TopAbs_State aState = Intersector3d.State(i);
423                     if (Abs(parmin) <= Tol)
424                     {
425                       myState = 2;
426                       myFace = f;
427                       break;
428                     }
429                     //  Treatment of case TopAbs_ON separately.
430                     else if (aState == TopAbs_IN)
431                     {
432                       //-- The intersection point between the line and a face F 
433                       // -- of the solid is in the face F 
434
435                       IntCurveSurface_TransitionOnCurve tran = Intersector3d.Transition(i);
436                       if (tran == IntCurveSurface_Tangent)
437                       {
438 #ifdef OCCT_DEBUG
439                         std::cout<<"*Problem ds BRepClass3d_SClassifier.cxx"<<std::endl;
440 #endif
441                         continue; // ignore this point
442                       }
443
444                       Trans(parmin, tran, myState);
445                       myFace = f;
446                     }
447                     // If the state is TopAbs_ON, it is necessary to chose
448                     // another line and to repeat the whole procedure.
449                     else if (aState == TopAbs_ON)
450                     {
451                       isFaultyLine = Standard_True;
452                       break;
453                     }
454                   }
455                   else
456                   {
457                     //-- No point has been found by the Intersector3d.
458                     //-- Or a Point has been found with a greater parameter.
459                   }
460                 } //-- loop by intersection points
461                 if (myState == 2)
462                 {
463                   break;
464                 }
465               } //-- Face has not been rejected
466               else
467                 myState = 1;
468             }
469           }//-- Exploration of the faces
470           if (myState == 2)
471           {
472             break;
473           }
474         } //-- Shell has not been rejected
475         else
476           myState = 1;
477     } //-- Exploration of the shells
478
479     if (NearFaultPar != RealLast() &&
480         Abs(parmin) >= Abs(NearFaultPar) - Precision::PConfusion())
481     {
482       isFaultyLine = Standard_True;
483     }
484   }
485
486 #ifdef OCCT_DEBUG
487   //#################################################
488   SolidExplorer.DumpSegment(P,L,parmin,State());
489   //#################################################
490 #endif
491 }
492
493
494 TopAbs_State BRepClass3d_SClassifier::State() const
495 {
496   if(myState == 2)
497     return(TopAbs_ON);
498   else if(myState == 3)
499     return(TopAbs_IN);
500   else if(myState == 4)
501     return(TopAbs_OUT);
502
503   // return OUT state when there is an error during execution.
504   return(TopAbs_OUT);
505 }
506
507 TopoDS_Face BRepClass3d_SClassifier::Face() const {  
508   return(myFace);
509 }
510
511 Standard_Boolean BRepClass3d_SClassifier::Rejected() const { 
512   return(myState==1); 
513 }
514
515   
516 Standard_Boolean BRepClass3d_SClassifier::IsOnAFace() const { 
517   return(myState==2);
518 }
519
520
521 void BRepClass3d_SClassifier::ForceIn() {
522   myState=3;
523 }
524
525 void BRepClass3d_SClassifier::ForceOut() { 
526   myState=4;
527 }
528
529 Standard_Real GetAddToParam(const gp_Lin&       L,
530                             const Standard_Real P,
531                             const Bnd_Box&      B)
532 {
533   Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
534   B.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
535   Standard_Real x[2] = {aXmin,aXmax}, y[2] = {aYmin,aYmax}, z[2] = {aZmin,aZmax};
536   Standard_Integer i = 0, j = 0, k = 0;
537   Standard_Real Par = P;
538   for(i = 0 ; i < 2; i++) {
539     for(j = 0; j < 2; j++) {
540       for(k = 0; k < 2; k++) {
541         Standard_Real X = fabs(x[i]-L.Location().X());
542         Standard_Real Y = fabs(y[j]-L.Location().Y());
543         Standard_Real Z = fabs(z[k]-L.Location().Z());
544         if(X < 1.e+20 && Y < 1.e+20 && Z < 1.e+20) {
545           gp_Pnt aP(x[i],y[j],z[k]);
546           Standard_Real par = ElCLib::Parameter(L,aP);
547           if(par > Par)
548             Par = par;
549         }
550         else
551           return 1.e+20;
552       }
553     }
554   }
555   return Par - P;
556 }
557 //=======================================================================
558 //function : FaceNormal
559 //purpose  : 
560 //=======================================================================
561 Standard_Boolean FaceNormal (const TopoDS_Face& aF,
562                              const Standard_Real U,
563                              const Standard_Real V,
564                              gp_Dir& aDN)
565 {
566   gp_Pnt aPnt ;
567   gp_Vec aD1U, aD1V, aN;
568   Handle(Geom_Surface) aS;
569
570   aS=BRep_Tool::Surface(aF);
571   aS->D1 (U, V, aPnt, aD1U, aD1V);
572   aN=aD1U.Crossed(aD1V);
573   if (aN.Magnitude() <= gp::Resolution())
574     return Standard_False;
575   
576   aN.Normalize();  
577   aDN.SetXYZ(aN.XYZ());
578   if (aF.Orientation() == TopAbs_REVERSED){
579     aDN.Reverse();
580   }
581   return Standard_True;
582 }
583
584 //=======================================================================
585 //function : GetNormalOnFaceBound
586 //purpose  : 
587 //=======================================================================
588 static Standard_Boolean GetNormalOnFaceBound(const TopoDS_Edge& E,
589                                              const TopoDS_Face& F,
590                                              const Standard_Real param,
591                                              gp_Dir& OutDir)
592
593   Standard_Real f = 0, l = 0;
594
595   gp_Pnt2d P2d;
596   Handle(Geom2d_Curve) c2d = BRep_Tool::CurveOnSurface(E, F, f, l);
597   if (c2d.IsNull())
598     return Standard_False;
599   if (param < f || param > l)
600     return Standard_False;
601   c2d->D0(param, P2d);
602   if (!FaceNormal(F, P2d.X(), P2d.Y(), OutDir))
603     return Standard_False;
604   return Standard_True;
605 }
606
607 //=======================================================================
608 //function : GetTransi
609 //purpose  : 
610 //=======================================================================
611 static Standard_Integer GetTransi(const TopoDS_Face& f1,
612                                   const TopoDS_Face& f2,
613                                   const TopoDS_Edge e,
614                                   const Standard_Real param,
615                                   const gp_Lin& L,
616                                   IntCurveSurface_TransitionOnCurve& trans)
617 {
618   //return statuses:
619   //1 => OK
620   //0 => skip
621   //-1 => probably a faulty line
622   gp_Dir nf1, nf2;
623   if (!GetNormalOnFaceBound(e, f1, param, nf1))
624     return -1;
625   if (!GetNormalOnFaceBound(e, f2, param, nf2))
626     return -1;
627
628   const gp_Dir& LDir = L.Direction();
629
630   if(Abs(LDir.Dot(nf1)) < Precision::Angular() || Abs(LDir.Dot(nf2)) < Precision::Angular())
631   {
632     //line is orthogonal to normal(s)
633     //trans = IntCurveSurface_Tangent;
634     return -1;
635   }
636
637   if (nf1.IsParallel(nf2, Precision::Angular()))
638   {
639     Standard_Real angD = nf1.Dot(LDir);
640     if (Abs(angD) < Precision::Angular())
641       return -1;
642     else if (angD > 0)
643       trans = IntCurveSurface_Out;
644     else //angD < -Precision::Angular())
645       trans = IntCurveSurface_In;
646     return 1;
647   }
648
649   gp_Vec N = nf1^nf2;
650   gp_Dir ProjL = N.XYZ() ^ LDir.XYZ() ^ N.XYZ(); //proj LDir on the plane defined by nf1/nf2 directions
651
652   Standard_Real fAD = nf1.Dot(ProjL); 
653   Standard_Real sAD = nf2.Dot(ProjL);  
654
655   if (fAD < -Precision::Angular() && sAD < -Precision::Angular())
656     trans = IntCurveSurface_In;
657   else if (fAD > Precision::Angular() && sAD > Precision::Angular())
658     trans = IntCurveSurface_Out;
659   else
660     return 0;
661   return 1;
662 }
663
664 //=======================================================================
665 //function : Trans
666 //purpose  : 
667 //=======================================================================
668 static void Trans(const Standard_Real parmin, 
669                   IntCurveSurface_TransitionOnCurve& tran,
670                   int& state)
671 {
672   // if parmin is negative we should reverse transition
673   if (parmin < 0)
674     tran = (tran == IntCurveSurface_Out ? IntCurveSurface_In : IntCurveSurface_Out);
675
676   if(tran == IntCurveSurface_Out)
677     //-- The line is going from inside the solid to outside 
678     //-- the solid.
679     state = 3; // IN
680   else
681     state = 4; // OUT
682 }