0026206: BRepClass_FaceClassifier returns TopAbs_OUT for internal point
[occt.git] / src / BRepClass / BRepClass_FaceExplorer.cxx
1 // Created on: 1992-11-19
2 // Created by: Remi LEQUETTE
3 // Copyright (c) 1992-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 Jul 13 17:42:58 2006 OCC12627
18 //  Total rewriting of the method Segment; add the method OtherSegment.
19
20 #include <BRepClass_FaceExplorer.ixx>
21 #include <Precision.hxx>
22 #include <Geom2d_Curve.hxx>
23 #include <TopoDS.hxx>
24 #include <BRep_Tool.hxx>
25
26 static const Standard_Real Probing_Start = 0.123;
27 static const Standard_Real Probing_End = 0.7;
28 static const Standard_Real Probing_Step = 0.2111;
29
30 //=======================================================================
31 //function : BRepClass_FaceExplorer
32 //purpose  : 
33 //=======================================================================
34
35 BRepClass_FaceExplorer::BRepClass_FaceExplorer(const TopoDS_Face& F) :
36        myFace(F),
37        myCurEdgeInd(1),
38        myCurEdgePar(Probing_Start)
39 {
40   myFace.Orientation(TopAbs_FORWARD);
41 }
42
43 //=======================================================================
44 //function : Reject
45 //purpose  : 
46 //=======================================================================
47
48 Standard_Boolean  BRepClass_FaceExplorer::Reject(const gp_Pnt2d&)const 
49 {
50   return Standard_False;
51 }
52
53 //=======================================================================
54 //function : Segment
55 //purpose  : 
56 //=======================================================================
57
58 Standard_Boolean BRepClass_FaceExplorer::Segment(const gp_Pnt2d& P, 
59                                                  gp_Lin2d& L,
60                                                  Standard_Real& Par)
61 {
62   myCurEdgeInd = 1;
63   myCurEdgePar = Probing_Start;
64
65   return OtherSegment(P, L, Par);
66 }
67
68 //=======================================================================
69 //function : OtherSegment
70 //purpose  : 
71 //=======================================================================
72
73 Standard_Boolean BRepClass_FaceExplorer::OtherSegment(const gp_Pnt2d& P, 
74                                                       gp_Lin2d& L,
75                                                       Standard_Real& Par)
76 {
77   TopExp_Explorer      anExpF(myFace,TopAbs_EDGE);
78   Standard_Integer     i;
79   Standard_Real        aFPar;
80   Standard_Real        aLPar;
81   Handle(Geom2d_Curve) aC2d;
82   Standard_Real        aTolParConf2 = Precision::PConfusion() * Precision::PConfusion();
83   gp_Pnt2d             aPOnC;
84   Standard_Real        aParamIn;
85
86   for (i = 1; anExpF.More(); anExpF.Next(), i++) {
87     if (i != myCurEdgeInd)
88       continue;
89
90     const TopoDS_Shape       &aLocalShape   = anExpF.Current();
91     const TopAbs_Orientation  anOrientation = aLocalShape.Orientation();
92
93     if (anOrientation == TopAbs_FORWARD || anOrientation == TopAbs_REVERSED) {
94       const TopoDS_Edge &anEdge = TopoDS::Edge(aLocalShape);
95
96       aC2d = BRep_Tool::CurveOnSurface(anEdge, myFace, aFPar, aLPar);
97
98       if (!aC2d.IsNull()) {
99         // Treatment of infinite cases.
100         if (Precision::IsNegativeInfinite(aFPar)) {
101           if (Precision::IsPositiveInfinite(aLPar)) {
102             aFPar = -1.;
103             aLPar =  1.;
104           } else {
105             aFPar = aLPar - 1.;
106           }
107         } else if (Precision::IsPositiveInfinite(aLPar))
108           aLPar = aFPar + 1.;
109
110         for (; myCurEdgePar < Probing_End ;myCurEdgePar += Probing_Step) {
111           aParamIn = myCurEdgePar*aFPar + (1. - myCurEdgePar)*aLPar;
112
113           gp_Vec2d aTanVec;
114           aC2d->D1(aParamIn, aPOnC, aTanVec);
115           Par = aPOnC.SquareDistance(P);
116
117           if (Par > aTolParConf2) {
118             gp_Vec2d aLinVec(P, aPOnC);
119             gp_Dir2d aLinDir(aLinVec);
120
121             Standard_Real aTanMod = aTanVec.SquareMagnitude();
122             if (aTanMod < aTolParConf2)
123               continue;
124             aTanVec /= Sqrt(aTanMod);
125             Standard_Real aSinA = aTanVec.Crossed(aLinDir.XY());
126             const Standard_Real SmallAngle = 0.001;
127             if (Abs(aSinA) < SmallAngle)
128             {
129               // The line from the input point P to the current point on edge
130               // is tangent to the edge curve. This condition is bad for classification.
131               // Therefore try to go to another point in the hope that there will be 
132               // no tangent. If there tangent is preserved then leave the last point in 
133               // order to get this edge chanse to participate in classification.
134               if (myCurEdgePar + Probing_Step < Probing_End)
135                 continue;
136             }
137
138             L = gp_Lin2d(P, aLinDir);
139
140             // Check if ends of a curve lie on a line.
141             aC2d->D0(aFPar, aPOnC);
142
143             if (L.SquareDistance(aPOnC) > aTolParConf2) {
144               aC2d->D0(aLPar, aPOnC);
145
146               if (L.SquareDistance(aPOnC) > aTolParConf2) {
147                 myCurEdgePar += Probing_Step;
148
149                 if (myCurEdgePar >= Probing_End) {
150                   myCurEdgeInd++;
151                   myCurEdgePar = Probing_Start;
152                 }
153
154                 Par = Sqrt(Par);
155                 return Standard_True;
156               }
157             }
158           }
159         }
160       } // if (!aC2d.IsNull()) {
161     } // if (anOrientation == TopAbs_FORWARD ...
162
163     // This curve is not valid for line construction. Go to another edge.
164     myCurEdgeInd++;
165     myCurEdgePar = Probing_Start;
166   }
167
168   // nothing found, return an horizontal line
169   Par = RealLast();
170   L   = gp_Lin2d(P,gp_Dir2d(1,0));
171
172   return Standard_False;
173 }
174
175 //=======================================================================
176 //function : InitWires
177 //purpose  : 
178 //=======================================================================
179
180 void  BRepClass_FaceExplorer::InitWires()
181 {
182   myWExplorer.Init(myFace,TopAbs_WIRE);
183 }
184
185 //=======================================================================
186 //function : RejectWire NYI
187 //purpose  : 
188 //=======================================================================
189
190 Standard_Boolean  BRepClass_FaceExplorer::RejectWire
191   (const gp_Lin2d& , 
192    const Standard_Real)const 
193 {
194   return Standard_False;
195 }
196
197 //=======================================================================
198 //function : InitEdges
199 //purpose  : 
200 //=======================================================================
201
202 void  BRepClass_FaceExplorer::InitEdges()
203 {
204   myEExplorer.Init(myWExplorer.Current(),TopAbs_EDGE);
205 }
206
207 //=======================================================================
208 //function : RejectEdge NYI
209 //purpose  : 
210 //=======================================================================
211
212 Standard_Boolean  BRepClass_FaceExplorer::RejectEdge
213   (const gp_Lin2d& , 
214    const Standard_Real )const 
215 {
216   return Standard_False;
217 }
218
219
220 //=======================================================================
221 //function : CurrentEdge
222 //purpose  : 
223 //=======================================================================
224
225 void  BRepClass_FaceExplorer::CurrentEdge(BRepClass_Edge& E, 
226                                           TopAbs_Orientation& Or) const 
227 {
228   E.Edge() = TopoDS::Edge(myEExplorer.Current());
229   E.Face() = myFace;
230   Or = E.Edge().Orientation();
231 }
232