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
6 // This file is part of Open CASCADE Technology software library.
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.
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
17 // Modified by skv - Thu Sep 4 11:22:05 2003 OCC578
19 #include <BRepClass3d_SClassifier.ixx>
24 #include <BRepClass3d_Intersector3d.hxx>
27 #include <IntCurvesFace_Intersector.hxx>
28 // modified by NIZHNY-MKK Mon Jun 21 15:13:40 2004
29 #include <Precision.hxx>
31 #include <Geom_Surface.hxx>
32 #include <BRep_Tool.hxx>
33 #include <math_RealRandom.hxx>
34 #include <BRepTopAdaptor_FClass2d.hxx>
37 Standard_Boolean FaceNormal (const TopoDS_Face& aF,
38 const Standard_Real U,
39 const Standard_Real V,
43 Standard_Real GetAddToParam(const gp_Lin& L,const Standard_Real P,const Bnd_Box& B);
47 //=======================================================================
48 //function : BRepClass3d_SClassifier
50 //=======================================================================
51 BRepClass3d_SClassifier::BRepClass3d_SClassifier()
56 //=======================================================================
57 //function : BRepClass3d_SClassifier
59 //=======================================================================
60 BRepClass3d_SClassifier::BRepClass3d_SClassifier(BRepClass3d_SolidExplorer& S,
62 const Standard_Real Tol) {
64 myState=3; //-- in ds solid case without face
72 //=======================================================================
73 //function : PerformInfinitePoint
75 //=======================================================================
76 void BRepClass3d_SClassifier::PerformInfinitePoint(BRepClass3d_SolidExplorer& aSE,
77 const Standard_Real /*Tol*/) {
79 //Take a normal to the first extracted face in its random inner point
80 //and intersect this reversed normal with the faces of the solid.
81 //If the min.par.-intersection point is
82 // a) inner point of a face
83 // b) transition is not TANGENT
84 // (the line does not touch the face but pierces it)
85 //then set <myState> to IN or OUT according to transition
86 //else take the next random point inside the min.par.-intersected face
89 if(aSE.Reject(gp_Pnt(0,0,0))) {
90 myState=3; //-- in ds solid case without face
94 //------------------------------------------------------------
96 Standard_Boolean bFound;
97 Standard_Real aParam, aU = 0., aV = 0.;
101 math_RealRandom RandomGenerator(0.1, 0.9);
111 TopoDS_Face aF = aSE.CurrentFace();
112 TopAbs_State aState = TopAbs_OUT;
113 IntCurveSurface_TransitionOnCurve aTransition = IntCurveSurface_Tangent;
114 TopoDS_Face MinFace = aF;
117 aParam = RandomGenerator.Next();
118 bFound = aSE.FindAPointInTheFace(aF, aPoint, aU, aV, aParam);
122 if (!FaceNormal(aF, aU, aV, aDN))
124 gp_Lin aLin(aPoint, -aDN);
125 Standard_Real parmin = RealLast();
126 for (aSE.InitShell();aSE.MoreShell();aSE.NextShell()) {
127 if (aSE.RejectShell(aLin) == Standard_False) {
128 for (aSE.InitFace();aSE.MoreFace(); aSE.NextFace()) {
129 if (aSE.RejectFace(aLin) == Standard_False) {
130 TopoDS_Shape aLocalShape = aSE.CurrentFace();
131 TopoDS_Face CurFace = TopoDS::Face(aLocalShape);
132 IntCurvesFace_Intersector& Intersector3d = aSE.Intersector(CurFace);
133 Intersector3d.Perform(aLin,-RealLast(),parmin);
135 if(Intersector3d.IsDone()) {
136 if(Intersector3d.NbPnt()) {
137 Standard_Integer imin = 1;
138 for (Standard_Integer i = 2; i <= Intersector3d.NbPnt(); i++)
139 if (Intersector3d.WParameter(i) < Intersector3d.WParameter(imin))
141 parmin = Intersector3d.WParameter(imin);
142 aState = Intersector3d.State(imin);
143 aTransition = Intersector3d.Transition(imin);
152 } //end of loop on the whole solid
154 if (aState == TopAbs_IN)
156 if (aTransition == IntCurveSurface_Out) {
157 //-- The line is going from inside the solid to outside
159 myState = 3; //-- IN --
162 else if (aTransition == IntCurveSurface_In) {
163 myState = 4; //-- OUT --
169 } //if (aSE.MoreFace())
170 } //if (aSE.MoreShell())
173 //=======================================================================
176 //=======================================================================
177 void BRepClass3d_SClassifier::Perform(BRepClass3d_SolidExplorer& SolidExplorer,
179 const Standard_Real Tol)
183 if(SolidExplorer.Reject(P)) {
184 myState=3; //-- in ds solid case without face
191 if(SolidExplorer.Reject(P) == Standard_False) {
194 //-- We compute the intersection betwwen the line builded in the Solid Explorer
197 //-- --------------------------------------------------------------------------------
198 //-- Calculate intersection with the face closest to the direction of bounding boxes
199 //-- by priority so that to have the smallest possible parmin.
200 //-- optimization to produce as much as possible rejections with other faces.
201 Standard_Integer iFlag;
204 // Modified by skv - Thu Sep 4 11:22:05 2003 OCC578 Begin
205 // If found line passes through a bound of any face, it means that the line
206 // is not found properly and it is necessary to repeat whole procedure.
207 // That's why the main loop while is added.
208 Standard_Boolean isFaultyLine = Standard_True;
209 Standard_Integer anIndFace = 0;
210 Standard_Real parmin = 0.;
212 while (isFaultyLine) {
213 if (anIndFace == 0) {
214 iFlag = SolidExplorer.Segment(P,L,Par);
216 iFlag = SolidExplorer.OtherSegment(P,L,Par);
219 Standard_Integer aCurInd = SolidExplorer.GetFaceSegmentIndex();
221 if (aCurInd > anIndFace) {
228 // Modified by skv - Thu Sep 4 11:22:10 2003 OCC578 End
232 // iFlag==1 i.e face is Infinite
237 //SolidExplorer.Segment(P,L,Par);
239 //process results from uncorrected shells
241 //if(Par > 1.e+100 && L.Direction().IsParallel(gp_Dir(0.,0.,1.),1.e-8)) {
246 //-- BRepClass3d_Intersector3d Intersector3d;
248 // Modified by skv - Thu Sep 4 13:48:27 2003 OCC578 Begin
249 // Check if the point is ON surface but OUT of the face.
250 // Just skip this face because it is bad for classification.
254 isFaultyLine = Standard_False;
255 // Standard_Real parmin = RealLast();
257 // for(SolidExplorer.InitShell();
258 // SolidExplorer.MoreShell();
259 // SolidExplorer.NextShell()) {
262 for(SolidExplorer.InitShell();
263 SolidExplorer.MoreShell() && !isFaultyLine;
264 SolidExplorer.NextShell()) {
265 // Modified by skv - Thu Sep 4 13:48:27 2003 OCC578 End
267 if(SolidExplorer.RejectShell(L) == Standard_False) {
269 // Modified by skv - Thu Sep 4 13:48:27 2003 OCC578 Begin
270 // for(SolidExplorer.InitFace();
271 // SolidExplorer.MoreFace();
272 // SolidExplorer.NextFace()) {
273 for(SolidExplorer.InitFace();
274 SolidExplorer.MoreFace() && !isFaultyLine;
275 SolidExplorer.NextFace()) {
276 // Modified by skv - Thu Sep 4 13:48:27 2003 OCC578 End
278 if(SolidExplorer.RejectFace(L) == Standard_False) {
280 //-- Intersector3d.Perform(L,Par,Tol,SolidExplorer.CurrentFace());
281 TopoDS_Shape aLocalShape = SolidExplorer.CurrentFace();
282 TopoDS_Face f = TopoDS::Face(aLocalShape);
283 // TopoDS_Face f = TopoDS::Face(SolidExplorer.CurrentFace());
284 IntCurvesFace_Intersector& Intersector3d = SolidExplorer.Intersector(f);
286 // MSV Oct 25, 2001: prolong segment, since there are cases when
287 // the intersector does not find intersection points with the original
288 // segment due to rough triangulation of a parametrized surface
289 Standard_Real addW = Max(10*Tol, 0.01*Par);
290 Standard_Real AddW = addW;
292 Bnd_Box aBoxF = Intersector3d.Bounding();
294 // MSV 23.09.2004: the box must be finite in order to
295 // correctly prolong the segment to its bounds
296 if (!aBoxF.IsVoid() && !aBoxF.IsWhole()) {
297 Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
298 aBoxF.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
300 Standard_Real boxaddW = GetAddToParam(L,Par,aBoxF);
301 addW = Max(addW,boxaddW);
304 Standard_Real minW = -AddW;//-addW;
305 Standard_Real maxW = Min(Par*10,Par+addW);//Par+addW;
306 //cout << "range [" << minW << "," << maxW << "]" << endl << endl;
307 Intersector3d.Perform(L,minW,maxW);
308 //Intersector3d.Perform(L,-Tol,Par+10.0*Tol);
309 if(Intersector3d.IsDone()) {
311 for (i=1; i <= Intersector3d.NbPnt(); i++) {
312 if(Abs(Intersector3d.WParameter(i)) < Abs(parmin)) {
314 parmin = Intersector3d.WParameter(i);
315 // Modified by skv - Thu Sep 4 12:46:32 2003 OCC578 Begin
316 TopAbs_State aState = Intersector3d.State(i);
317 // Modified by skv - Thu Sep 4 12:46:33 2003 OCC578 End
318 if(Abs(parmin)<=Tol) {
322 // Modified by skv - Thu Sep 4 12:46:32 2003 OCC578 Begin
323 // Treatment of case TopAbs_ON separately.
325 else if(aState==TopAbs_IN) {
326 // Modified by skv - Thu Sep 4 12:46:32 2003 OCC578 End
328 //-- The intersection point between the line and a face F
329 // -- of the solid is in the face F
331 IntCurveSurface_TransitionOnCurve tran = Intersector3d.Transition(i);
332 if (tran == IntCurveSurface_Tangent) {
334 cout<<"*Problem ds BRepClass3d_SClassifier.cxx"<<endl;
336 continue; // ignore this point
338 // if parmin is negative we should reverse transition
340 tran = (tran == IntCurveSurface_Out
341 ? IntCurveSurface_In : IntCurveSurface_Out);
342 if(tran == IntCurveSurface_Out) {
343 //-- The line is going from inside the solid to outside
345 myState = 3; //-- IN --
347 else /* if(tran == IntCurveSurface_In) */ {
348 myState = 4; //-- OUT --
352 // Modified by skv - Thu Sep 4 12:48:50 2003 OCC578 Begin
353 // If the state is TopAbs_ON, it is necessary to chose
354 // another line and to repeat the whole procedure.
355 else if(aState==TopAbs_ON) {
356 isFaultyLine = Standard_True;
360 // Modified by skv - Thu Sep 4 12:48:50 2003 OCC578 End
363 //-- No point has been found by the Intersector3d.
364 //-- Or a Point has been found with a greater parameter.
366 } //-- loop by intersection points
367 } //-- Face has not been rejected
372 } //-- Exploration of the faces
373 } //-- Shell has not been rejected
377 } //-- Exploration of the shells
379 // Modified by skv - Thu Sep 4 11:42:03 2003 OCC578 Begin
380 // The end of main loop.
382 // Modified by skv - Thu Sep 4 11:42:03 2003 OCC578 End
385 //#################################################
386 SolidExplorer.DumpSegment(P,L,parmin,State());
387 //#################################################
390 } //-- Solid has not been rejected
397 TopAbs_State BRepClass3d_SClassifier::State() const {
398 if(myState==2) return(TopAbs_ON);
399 if(myState==4) return(TopAbs_OUT); //--
400 else if(myState==3) return(TopAbs_IN); //--
404 TopoDS_Face BRepClass3d_SClassifier::Face() const {
408 Standard_Boolean BRepClass3d_SClassifier::Rejected() const {
413 Standard_Boolean BRepClass3d_SClassifier::IsOnAFace() const {
418 void BRepClass3d_SClassifier::ForceIn() {
422 void BRepClass3d_SClassifier::ForceOut() {
426 Standard_Real GetAddToParam(const gp_Lin& L,
427 const Standard_Real P,
430 Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
431 B.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
432 Standard_Real x[2] = {aXmin,aXmax}, y[2] = {aYmin,aYmax}, z[2] = {aZmin,aZmax};
433 Standard_Integer i = 0, j = 0, k = 0;
434 Standard_Real Par = P;
435 for(i = 0 ; i < 2; i++) {
436 for(j = 0; j < 2; j++) {
437 for(k = 0; k < 2; k++) {
438 Standard_Real X = fabs(x[i]-L.Location().X());
439 Standard_Real Y = fabs(y[j]-L.Location().Y());
440 Standard_Real Z = fabs(z[k]-L.Location().Z());
441 if(X < 1.e+20 && Y < 1.e+20 && Z < 1.e+20) {
442 gp_Pnt aP(x[i],y[j],z[k]);
443 Standard_Real par = ElCLib::Parameter(L,aP);
454 //=======================================================================
455 //function : FaceNormal
457 //=======================================================================
458 Standard_Boolean FaceNormal (const TopoDS_Face& aF,
459 const Standard_Real U,
460 const Standard_Real V,
464 gp_Vec aD1U, aD1V, aN;
465 Handle(Geom_Surface) aS;
467 aS=BRep_Tool::Surface(aF);
468 aS->D1 (U, V, aPnt, aD1U, aD1V);
469 aN=aD1U.Crossed(aD1V);
470 if (aN.Magnitude() <= gp::Resolution())
471 return Standard_False;
474 aDN.SetXYZ(aN.XYZ());
475 if (aF.Orientation() == TopAbs_REVERSED){
478 return Standard_True;