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
9 // under the terms of the GNU Lesser General Public 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>
35 void FaceNormal (const TopoDS_Face& aF,
36 const Standard_Real U,
37 const Standard_Real V,
41 Standard_Real GetAddToParam(const gp_Lin& L,const Standard_Real P,const Bnd_Box& B);
45 //=======================================================================
46 //function : BRepClass3d_SClassifier
48 //=======================================================================
49 BRepClass3d_SClassifier::BRepClass3d_SClassifier()
54 //=======================================================================
55 //function : BRepClass3d_SClassifier
57 //=======================================================================
58 BRepClass3d_SClassifier::BRepClass3d_SClassifier(BRepClass3d_SolidExplorer& S,
60 const Standard_Real Tol) {
62 myState=3; //-- in ds solid case without face
70 //=======================================================================
71 //function : PerformInfinitePoint
73 //=======================================================================
74 void BRepClass3d_SClassifier::PerformInfinitePoint(BRepClass3d_SolidExplorer& aSE,
75 const Standard_Real /*Tol*/) {
76 //-- Idea : Take point A in face1 and point B in face B
77 //-- (if there is only one face, take 2 points in the same face.)
79 //-- Intersect straight line AB with the solid and produce transition of the
80 //-- first point. If the solid has only one face and the straight line AB does not cut it
81 //-- it is not possible to decide.
83 if(aSE.Reject(gp_Pnt(0,0,0))) {
84 myState=3; //-- in ds solid case without face
88 //------------------------------------------------------------
90 Standard_Boolean bFound, bFlag;
91 Standard_Integer nump;
92 Standard_Real aParam, aU1 = 0., aV1 = 0., aU2 = 0., aV2 = 0.;
101 for(aSE.InitShell(); aSE.MoreShell() && nump<2; aSE.NextShell()) {
102 for(aSE.InitFace(); aSE.MoreFace() && nump<2; ) {
103 TopoDS_Face aF = aSE.CurrentFace();
107 bFound=aSE.FindAPointInTheFace(aF, A, aU1, aV1, aParam);
112 if(!aSE.MoreFace()) {
114 bFound=aSE.FindAPointInTheFace(aF, B, aU2, aV2, aParam);
122 bFound=aSE.FindAPointInTheFace(aF, B, aU2, aV2, aParam);
129 }// for(aSE.InitFace(); aSE.MoreFace() && nump<2; ) {
130 }// for(aSE.InitShell(); aSE.MoreShell() && nump<2; aSE.NextShell()) {
132 //------------------------------------------------------------
134 Standard_Integer cpasbon;
135 Standard_Real parmin, aD2, aSP;
136 IntCurveSurface_TransitionOnCurve aTC;
141 bFlag=Standard_False;
143 FaceNormal(aF1, aU1, aV1, aDN1);
144 FaceNormal(aF2, aU2, aV2, aDN2);
151 aD2=A.SquareDistance(B);
152 if(aD2<0.000001 || bFlag) {
153 B.SetCoord(A.X()+1,A.Y()+1,A.Z()+1);
162 case 1 : AB.SetX(-AB.X());break;
163 case 2 : AB.SetY(-AB.Y());break;
164 case 3 : AB.SetZ(-AB.Z());break;
165 case 4 : AB.SetY(-AB.Y());break;
166 case 5 : AB.SetX(-AB.X());break;
168 gp_Lin L(A,gp_Dir(AB));
169 //-- cout<<"\npoint A "<<A.X()<<" "<<A.Y()<<" "<<A.Z()<<endl;
170 //-- cout<<"\npoint B "<<B.X()<<" "<<B.Y()<<" "<<B.Z()<<endl;
171 for(aSE.InitShell();aSE.MoreShell();aSE.NextShell()) {
172 if(aSE.RejectShell(L) == Standard_False) {
173 for(aSE.InitFace();aSE.MoreFace(); aSE.NextFace()) {
174 if(aSE.RejectFace(L) == Standard_False) {
175 TopoDS_Shape aLocalShape = aSE.CurrentFace();
176 TopoDS_Face f = TopoDS::Face(aLocalShape);
177 IntCurvesFace_Intersector& Intersector3d = aSE.Intersector(f);
178 Intersector3d.Perform(L,-RealLast(),parmin);
180 if(Intersector3d.IsDone()) {
181 if(Intersector3d.NbPnt()) {
182 if(Intersector3d.WParameter(1) < parmin) {
183 aState=Intersector3d.State(1);
184 parmin = Intersector3d.WParameter(1);
185 if(aState==TopAbs_IN || aState==TopAbs_ON) {
186 aTC=Intersector3d.Transition(1);
187 //-- The intersection point between the line and a face F
188 // -- of the solid is in the face F
189 if(aTC == IntCurveSurface_Out) {
190 //-- The line is going from inside the solid to outside
192 myState = 3; //-- IN --
194 else if(aTC == IntCurveSurface_In) {
195 myState = 4; //-- OUT --
200 else if(Intersector3d.State(1)==TopAbs_ON) {
201 //-- The intersection point between the line and a face F
202 //-- of the solid is in the face F
203 if(Intersector3d.Transition(1) == IntCurveSurface_Out) {
204 //-- The line is going from inside the solid to outside
206 myState = 3; //-- IN --
208 else if(Intersector3d.Transition(1) == IntCurveSurface_In) {
209 myState = 4; //-- OUT --
218 //-- No point has been found by the Intersector3d.
219 //-- Or a Point has been found with a greater parameter.
224 } //-- Exploration of the faces
225 } //-- Shell has not been rejected
229 } //-- Exploration of the shells
232 while(cpasbon!=0 && cpasbon<5);
234 //=======================================================================
237 //=======================================================================
238 void BRepClass3d_SClassifier::Perform(BRepClass3d_SolidExplorer& SolidExplorer,
240 const Standard_Real Tol)
244 if(SolidExplorer.Reject(P)) {
245 myState=3; //-- in ds solid case without face
252 if(SolidExplorer.Reject(P) == Standard_False) {
255 //-- We compute the intersection betwwen the line builded in the Solid Explorer
258 //-- --------------------------------------------------------------------------------
259 //-- Calculate intersection with the face closest to the direction of bounding boxes
260 //-- by priority so that to have the smallest possible parmin.
261 //-- optimization to produce as much as possible rejections with other faces.
262 Standard_Integer iFlag;
265 // Modified by skv - Thu Sep 4 11:22:05 2003 OCC578 Begin
266 // If found line passes through a bound of any face, it means that the line
267 // is not found properly and it is necessary to repeat whole procedure.
268 // That's why the main loop while is added.
269 Standard_Boolean isFaultyLine = Standard_True;
270 Standard_Integer anIndFace = 0;
271 Standard_Real parmin = 0.;
273 while (isFaultyLine) {
274 if (anIndFace == 0) {
275 iFlag = SolidExplorer.Segment(P,L,Par);
277 iFlag = SolidExplorer.OtherSegment(P,L,Par);
280 Standard_Integer aCurInd = SolidExplorer.GetFaceSegmentIndex();
282 if (aCurInd > anIndFace) {
289 // Modified by skv - Thu Sep 4 11:22:10 2003 OCC578 End
293 // iFlag==1 i.e face is Infinite
298 //SolidExplorer.Segment(P,L,Par);
300 //process results from uncorrected shells
302 //if(Par > 1.e+100 && L.Direction().IsParallel(gp_Dir(0.,0.,1.),1.e-8)) {
307 //-- BRepClass3d_Intersector3d Intersector3d;
309 // Modified by skv - Thu Sep 4 13:48:27 2003 OCC578 Begin
310 // Check if the point is ON surface but OUT of the face.
311 // Just skip this face because it is bad for classification.
315 isFaultyLine = Standard_False;
316 // Standard_Real parmin = RealLast();
318 // for(SolidExplorer.InitShell();
319 // SolidExplorer.MoreShell();
320 // SolidExplorer.NextShell()) {
323 for(SolidExplorer.InitShell();
324 SolidExplorer.MoreShell() && !isFaultyLine;
325 SolidExplorer.NextShell()) {
326 // Modified by skv - Thu Sep 4 13:48:27 2003 OCC578 End
328 if(SolidExplorer.RejectShell(L) == Standard_False) {
330 // Modified by skv - Thu Sep 4 13:48:27 2003 OCC578 Begin
331 // for(SolidExplorer.InitFace();
332 // SolidExplorer.MoreFace();
333 // SolidExplorer.NextFace()) {
334 for(SolidExplorer.InitFace();
335 SolidExplorer.MoreFace() && !isFaultyLine;
336 SolidExplorer.NextFace()) {
337 // Modified by skv - Thu Sep 4 13:48:27 2003 OCC578 End
339 if(SolidExplorer.RejectFace(L) == Standard_False) {
341 //-- Intersector3d.Perform(L,Par,Tol,SolidExplorer.CurrentFace());
342 TopoDS_Shape aLocalShape = SolidExplorer.CurrentFace();
343 TopoDS_Face f = TopoDS::Face(aLocalShape);
344 // TopoDS_Face f = TopoDS::Face(SolidExplorer.CurrentFace());
345 IntCurvesFace_Intersector& Intersector3d = SolidExplorer.Intersector(f);
347 // MSV Oct 25, 2001: prolong segment, since there are cases when
348 // the intersector does not find intersection points with the original
349 // segment due to rough triangulation of a parametrized surface
350 Standard_Real addW = Max(10*Tol, 0.01*Par);
351 Standard_Real AddW = addW;
353 Bnd_Box aBoxF = Intersector3d.Bounding();
355 // MSV 23.09.2004: the box must be finite in order to
356 // correctly prolong the segment to its bounds
357 if (!aBoxF.IsVoid() && !aBoxF.IsWhole()) {
358 Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
359 aBoxF.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
361 Standard_Real boxaddW = GetAddToParam(L,Par,aBoxF);
362 addW = Max(addW,boxaddW);
365 Standard_Real minW = -AddW;//-addW;
366 Standard_Real maxW = Min(Par*10,Par+addW);//Par+addW;
367 //cout << "range [" << minW << "," << maxW << "]" << endl << endl;
368 Intersector3d.Perform(L,minW,maxW);
369 //Intersector3d.Perform(L,-Tol,Par+10.0*Tol);
370 if(Intersector3d.IsDone()) {
372 for (i=1; i <= Intersector3d.NbPnt(); i++) {
373 if(Abs(Intersector3d.WParameter(i)) < Abs(parmin)) {
375 parmin = Intersector3d.WParameter(i);
376 // Modified by skv - Thu Sep 4 12:46:32 2003 OCC578 Begin
377 TopAbs_State aState = Intersector3d.State(i);
378 // Modified by skv - Thu Sep 4 12:46:33 2003 OCC578 End
379 if(Abs(parmin)<=Tol) {
383 // Modified by skv - Thu Sep 4 12:46:32 2003 OCC578 Begin
384 // Treatment of case TopAbs_ON separately.
386 else if(aState==TopAbs_IN) {
387 // Modified by skv - Thu Sep 4 12:46:32 2003 OCC578 End
389 //-- The intersection point between the line and a face F
390 // -- of the solid is in the face F
392 IntCurveSurface_TransitionOnCurve tran = Intersector3d.Transition(i);
393 if (tran == IntCurveSurface_Tangent) {
395 cout<<"*Problem ds BRepClass3d_SClassifier.cxx"<<endl;
397 continue; // ignore this point
399 // if parmin is negative we should reverse transition
401 tran = (tran == IntCurveSurface_Out
402 ? IntCurveSurface_In : IntCurveSurface_Out);
403 if(tran == IntCurveSurface_Out) {
404 //-- The line is going from inside the solid to outside
406 myState = 3; //-- IN --
408 else /* if(tran == IntCurveSurface_In) */ {
409 myState = 4; //-- OUT --
413 // Modified by skv - Thu Sep 4 12:48:50 2003 OCC578 Begin
414 // If the state is TopAbs_ON, it is necessary to chose
415 // another line and to repeat the whole procedure.
416 else if(aState==TopAbs_ON) {
417 isFaultyLine = Standard_True;
421 // Modified by skv - Thu Sep 4 12:48:50 2003 OCC578 End
424 //-- No point has been found by the Intersector3d.
425 //-- Or a Point has been found with a greater parameter.
427 } //-- loop by intersection points
428 } //-- Face has not been rejected
433 } //-- Exploration of the faces
434 } //-- Shell has not been rejected
438 } //-- Exploration of the shells
440 // Modified by skv - Thu Sep 4 11:42:03 2003 OCC578 Begin
441 // The end of main loop.
443 // Modified by skv - Thu Sep 4 11:42:03 2003 OCC578 End
446 //#################################################
447 SolidExplorer.DumpSegment(P,L,parmin,State());
448 //#################################################
451 } //-- Solid has not been rejected
458 TopAbs_State BRepClass3d_SClassifier::State() const {
459 if(myState==2) return(TopAbs_ON);
460 if(myState==4) return(TopAbs_OUT); //--
461 else if(myState==3) return(TopAbs_IN); //--
465 TopoDS_Face BRepClass3d_SClassifier::Face() const {
469 Standard_Boolean BRepClass3d_SClassifier::Rejected() const {
474 Standard_Boolean BRepClass3d_SClassifier::IsOnAFace() const {
479 void BRepClass3d_SClassifier::ForceIn() {
483 void BRepClass3d_SClassifier::ForceOut() {
487 Standard_Real GetAddToParam(const gp_Lin& L,
488 const Standard_Real P,
491 Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
492 B.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
493 Standard_Real x[2] = {aXmin,aXmax}, y[2] = {aYmin,aYmax}, z[2] = {aZmin,aZmax};
494 Standard_Integer i = 0, j = 0, k = 0;
495 Standard_Real Par = P;
496 for(i = 0 ; i < 2; i++) {
497 for(j = 0; j < 2; j++) {
498 for(k = 0; k < 2; k++) {
499 Standard_Real X = fabs(x[i]-L.Location().X());
500 Standard_Real Y = fabs(y[j]-L.Location().Y());
501 Standard_Real Z = fabs(z[k]-L.Location().Z());
502 if(X < 1.e+20 && Y < 1.e+20 && Z < 1.e+20) {
503 gp_Pnt aP(x[i],y[j],z[k]);
504 Standard_Real par = ElCLib::Parameter(L,aP);
515 //=======================================================================
516 //function : FaceNormal
518 //=======================================================================
519 void FaceNormal (const TopoDS_Face& aF,
520 const Standard_Real U,
521 const Standard_Real V,
525 gp_Vec aD1U, aD1V, aN;
526 Handle(Geom_Surface) aS;
528 aS=BRep_Tool::Surface(aF);
529 aS->D1 (U, V, aPnt, aD1U, aD1V);
530 aN=aD1U.Crossed(aD1V);
532 aDN.SetXYZ(aN.XYZ());
533 if (aF.Orientation() == TopAbs_REVERSED){