// Created on: 1996-07-15 // Created by: Laurent BUCHARD // Copyright (c) 1996-1999 Matra Datavision // Copyright (c) 1999-2014 OPEN CASCADE SAS // // This file is part of Open CASCADE Technology software library. // // This library is free software; you can redistribute it and/or modify it under // the terms of the GNU Lesser General Public License version 2.1 as published // by the Free Software Foundation, with special exception defined in the file // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT // distribution for complete text of the license and disclaimer of any warranty. // // Alternatively, this file may be used under the terms of Open CASCADE // commercial license or contractual agreement. // Modified by skv - Thu Sep 4 11:22:05 2003 OCC578 #include #include #include #include #include #include #include // modified by NIZHNY-MKK Mon Jun 21 15:13:40 2004 #include #include #include #include #include #include static Standard_Boolean FaceNormal (const TopoDS_Face& aF, const Standard_Real U, const Standard_Real V, gp_Dir& aDN); static Standard_Real GetAddToParam(const gp_Lin& L,const Standard_Real P,const Bnd_Box& B); //======================================================================= //function : BRepClass3d_SClassifier //purpose : //======================================================================= BRepClass3d_SClassifier::BRepClass3d_SClassifier() { } //======================================================================= //function : BRepClass3d_SClassifier //purpose : //======================================================================= BRepClass3d_SClassifier::BRepClass3d_SClassifier(BRepClass3d_SolidExplorer& S, const gp_Pnt& P, const Standard_Real Tol) { if(S.Reject(P)) { myState=3; //-- in ds solid case without face } else { Perform(S,P,Tol); } } //======================================================================= //function : PerformInfinitePoint //purpose : //======================================================================= void BRepClass3d_SClassifier::PerformInfinitePoint(BRepClass3d_SolidExplorer& aSE, const Standard_Real /*Tol*/) { //Take a normal to the first extracted face in its random inner point //and intersect this reversed normal with the faces of the solid. //If the min.par.-intersection point is // a) inner point of a face // b) transition is not TANGENT // (the line does not touch the face but pierces it) //then set to IN or OUT according to transition //else take the next random point inside the min.par.-intersected face //and continue if(aSE.Reject(gp_Pnt(0,0,0))) { myState=3; //-- in ds solid case without face return; } // //------------------------------------------------------------ // 1 Standard_Boolean bFound; Standard_Real aParam, aU = 0., aV = 0.; gp_Pnt aPoint; gp_Dir aDN; math_BullardGenerator aRandomGenerator; myFace.Nullify(); myState=2; aSE.InitShell(); if (aSE.MoreShell()) { aSE.InitFace(); if (aSE.MoreFace()) { TopoDS_Face aF = aSE.CurrentFace(); TopAbs_State aState = TopAbs_OUT; IntCurveSurface_TransitionOnCurve aTransition = IntCurveSurface_Tangent; TopoDS_Face MinFace = aF; for (;;) { aParam = 0.1 + 0.8 * aRandomGenerator.NextReal(); // random number in range [0.1, 0.9] bFound = aSE.FindAPointInTheFace(aF, aPoint, aU, aV, aParam); if (!bFound) return; if (!FaceNormal(aF, aU, aV, aDN)) continue; gp_Lin aLin(aPoint, -aDN); Standard_Real parmin = RealLast(); for (aSE.InitShell();aSE.MoreShell();aSE.NextShell()) { if (aSE.RejectShell(aLin) == Standard_False) { for (aSE.InitFace();aSE.MoreFace(); aSE.NextFace()) { if (aSE.RejectFace(aLin) == Standard_False) { TopoDS_Shape aLocalShape = aSE.CurrentFace(); TopoDS_Face CurFace = TopoDS::Face(aLocalShape); IntCurvesFace_Intersector& Intersector3d = aSE.Intersector(CurFace); Intersector3d.Perform(aLin,-RealLast(),parmin); if(Intersector3d.IsDone()) { if(Intersector3d.NbPnt()) { Standard_Integer imin = 1; for (Standard_Integer i = 2; i <= Intersector3d.NbPnt(); i++) if (Intersector3d.WParameter(i) < Intersector3d.WParameter(imin)) imin = i; parmin = Intersector3d.WParameter(imin); aState = Intersector3d.State(imin); aTransition = Intersector3d.Transition(imin); MinFace = CurFace; } } } } } else myState = 1; } //end of loop on the whole solid if (aState == TopAbs_IN) { if (aTransition == IntCurveSurface_Out) { //-- The line is going from inside the solid to outside //-- the solid. myState = 3; //-- IN -- return; } else if (aTransition == IntCurveSurface_In) { myState = 4; //-- OUT -- return; } } aF = MinFace; } } //if (aSE.MoreFace()) } //if (aSE.MoreShell()) } //======================================================================= //function : Perform //purpose : //======================================================================= void BRepClass3d_SClassifier::Perform(BRepClass3d_SolidExplorer& SolidExplorer, const gp_Pnt& P, const Standard_Real Tol) { if(SolidExplorer.Reject(P)) { myState=3; //-- in ds solid case without face return; } myFace.Nullify(); myState = 0; if(SolidExplorer.Reject(P) == Standard_False) { gp_Lin L; Standard_Real Par; //-- We compute the intersection betwwen the line builded in the Solid Explorer //-- and the shape. //-- -------------------------------------------------------------------------------- //-- Calculate intersection with the face closest to the direction of bounding boxes //-- by priority so that to have the smallest possible parmin. //-- optimization to produce as much as possible rejections with other faces. Standard_Integer iFlag; // // Modified by skv - Thu Sep 4 11:22:05 2003 OCC578 Begin // If found line passes through a bound of any face, it means that the line // is not found properly and it is necessary to repeat whole procedure. // That's why the main loop while is added. Standard_Boolean isFaultyLine = Standard_True; Standard_Integer anIndFace = 0; Standard_Real parmin = 0.; while (isFaultyLine) { if (anIndFace == 0) { iFlag = SolidExplorer.Segment(P,L,Par); } else { iFlag = SolidExplorer.OtherSegment(P,L,Par); } Standard_Integer aCurInd = SolidExplorer.GetFaceSegmentIndex(); if (aCurInd > anIndFace) { anIndFace = aCurInd; } else { myState = 1; return; } // Modified by skv - Thu Sep 4 11:22:10 2003 OCC578 End if (iFlag==1) { // IsOnFace // iFlag==1 i.e face is Infinite myState=2; return; } //SolidExplorer.Segment(P,L,Par); // //process results from uncorrected shells // //if(Par > 1.e+100 && L.Direction().IsParallel(gp_Dir(0.,0.,1.),1.e-8)) { if (iFlag==2) { myState = 4; return; } //-- BRepClass3d_Intersector3d Intersector3d; // Modified by skv - Thu Sep 4 13:48:27 2003 OCC578 Begin // Check if the point is ON surface but OUT of the face. // Just skip this face because it is bad for classification. if (iFlag == 3) continue; isFaultyLine = Standard_False; // Standard_Real parmin = RealLast(); // for(SolidExplorer.InitShell(); // SolidExplorer.MoreShell(); // SolidExplorer.NextShell()) { parmin = RealLast(); for(SolidExplorer.InitShell(); SolidExplorer.MoreShell() && !isFaultyLine; SolidExplorer.NextShell()) { // Modified by skv - Thu Sep 4 13:48:27 2003 OCC578 End if(SolidExplorer.RejectShell(L) == Standard_False) { // Modified by skv - Thu Sep 4 13:48:27 2003 OCC578 Begin // for(SolidExplorer.InitFace(); // SolidExplorer.MoreFace(); // SolidExplorer.NextFace()) { for(SolidExplorer.InitFace(); SolidExplorer.MoreFace() && !isFaultyLine; SolidExplorer.NextFace()) { // Modified by skv - Thu Sep 4 13:48:27 2003 OCC578 End if(SolidExplorer.RejectFace(L) == Standard_False) { //-- Intersector3d.Perform(L,Par,Tol,SolidExplorer.CurrentFace()); TopoDS_Shape aLocalShape = SolidExplorer.CurrentFace(); TopoDS_Face f = TopoDS::Face(aLocalShape); // TopoDS_Face f = TopoDS::Face(SolidExplorer.CurrentFace()); IntCurvesFace_Intersector& Intersector3d = SolidExplorer.Intersector(f); // MSV Oct 25, 2001: prolong segment, since there are cases when // the intersector does not find intersection points with the original // segment due to rough triangulation of a parametrized surface Standard_Real addW = Max(10*Tol, 0.01*Par); Standard_Real AddW = addW; Bnd_Box aBoxF = Intersector3d.Bounding(); // MSV 23.09.2004: the box must be finite in order to // correctly prolong the segment to its bounds if (!aBoxF.IsVoid() && !aBoxF.IsWhole()) { Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax; aBoxF.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax); Standard_Real boxaddW = GetAddToParam(L,Par,aBoxF); addW = Max(addW,boxaddW); } Standard_Real minW = -AddW;//-addW; Standard_Real maxW = Min(Par*10,Par+addW);//Par+addW; //cout << "range [" << minW << "," << maxW << "]" << endl << endl; Intersector3d.Perform(L,minW,maxW); //Intersector3d.Perform(L,-Tol,Par+10.0*Tol); if(Intersector3d.IsDone()) { Standard_Integer i; for (i=1; i <= Intersector3d.NbPnt(); i++) { if(Abs(Intersector3d.WParameter(i)) < Abs(parmin) - Precision::PConfusion()) { parmin = Intersector3d.WParameter(i); // Modified by skv - Thu Sep 4 12:46:32 2003 OCC578 Begin TopAbs_State aState = Intersector3d.State(i); // Modified by skv - Thu Sep 4 12:46:33 2003 OCC578 End if(Abs(parmin)<=Tol) { myState = 2; myFace = f; } // Modified by skv - Thu Sep 4 12:46:32 2003 OCC578 Begin // Treatment of case TopAbs_ON separately. else if(aState==TopAbs_IN) { // Modified by skv - Thu Sep 4 12:46:32 2003 OCC578 End //-- The intersection point between the line and a face F // -- of the solid is in the face F IntCurveSurface_TransitionOnCurve tran = Intersector3d.Transition(i); if (tran == IntCurveSurface_Tangent) { #ifdef OCCT_DEBUG cout<<"*Problem ds BRepClass3d_SClassifier.cxx"< Par) Par = par; } else return 1.e+20; } } } return Par - P; } //======================================================================= //function : FaceNormal //purpose : //======================================================================= Standard_Boolean FaceNormal (const TopoDS_Face& aF, const Standard_Real U, const Standard_Real V, gp_Dir& aDN) { gp_Pnt aPnt ; gp_Vec aD1U, aD1V, aN; Handle(Geom_Surface) aS; aS=BRep_Tool::Surface(aF); aS->D1 (U, V, aPnt, aD1U, aD1V); aN=aD1U.Crossed(aD1V); if (aN.Magnitude() <= gp::Resolution()) return Standard_False; aN.Normalize(); aDN.SetXYZ(aN.XYZ()); if (aF.Orientation() == TopAbs_REVERSED){ aDN.Reverse(); } return Standard_True; }