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