0031851: Data Exchange, STEP - enable Unicode symbols in STEP export
[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 <BRep_Tool.hxx>
21 #include <BRepClass_Edge.hxx>
22 #include <BRepClass_FaceExplorer.hxx>
23 #include <BRepTools.hxx>
24 #include <Geom2d_Curve.hxx>
25 #include <gp_Lin2d.hxx>
26 #include <gp_Pnt2d.hxx>
27 #include <Precision.hxx>
28 #include <TopoDS.hxx>
29 #include <TopoDS_Face.hxx>
30 #include <Geom2dAPI_ProjectPointOnCurve.hxx>
31
32 static const Standard_Real Probing_Start = 0.123;
33 static const Standard_Real Probing_End = 0.7;
34 static const Standard_Real Probing_Step = 0.2111;
35
36 //=======================================================================
37 //function : BRepClass_FaceExplorer
38 //purpose  : 
39 //=======================================================================
40
41 BRepClass_FaceExplorer::BRepClass_FaceExplorer(const TopoDS_Face& F) :
42        myFace(F),
43        myCurEdgeInd(1),
44        myCurEdgePar(Probing_Start),
45        myUMin (Precision::Infinite()),
46        myUMax (-Precision::Infinite()),
47        myVMin (Precision::Infinite()),
48        myVMax (-Precision::Infinite())
49 {
50   myFace.Orientation(TopAbs_FORWARD);
51 }
52
53 //=======================================================================
54 //function : ComputeFaceBounds
55 //purpose  : 
56 //=======================================================================
57 void BRepClass_FaceExplorer::ComputeFaceBounds()
58 {
59   TopLoc_Location aLocation;
60   const Handle(Geom_Surface)& aSurface = BRep_Tool::Surface (myFace, aLocation);
61   aSurface->Bounds (myUMin, myUMax, myVMin, myVMax);
62   if (Precision::IsInfinite (myUMin) || Precision::IsInfinite (myUMax) ||
63       Precision::IsInfinite (myVMin) || Precision::IsInfinite (myVMax))
64   {
65     BRepTools::UVBounds(myFace, myUMin, myUMax, myVMin, myVMax);
66   }
67 }
68
69 //=======================================================================
70 //function : CheckPoint
71 //purpose  : 
72 //=======================================================================
73
74 Standard_Boolean BRepClass_FaceExplorer::CheckPoint(gp_Pnt2d& thePoint)
75 {
76   if (myUMin > myUMax)
77   {
78     ComputeFaceBounds();
79   }
80
81   if (Precision::IsInfinite(myUMin) || Precision::IsInfinite(myUMax) ||
82       Precision::IsInfinite(myVMin) || Precision::IsInfinite(myVMax))
83   {
84     return Standard_True;
85   }
86
87   gp_Pnt2d aCenterPnt(( myUMin + myUMax ) / 2, ( myVMin + myVMax ) / 2);
88   Standard_Real aDistance = aCenterPnt.Distance(thePoint);
89   if (Precision::IsInfinite(aDistance))
90   {
91     thePoint.SetCoord (myUMin - (myUMax - myUMin ),
92                        myVMin - (myVMax - myVMin ));
93     return Standard_False;
94   }
95   else
96   {
97     Standard_Real anEpsilon = Epsilon(aDistance);
98     if (anEpsilon > Max (myUMax - myUMin, myVMax - myVMin))
99     {
100       gp_Vec2d aLinVec(aCenterPnt, thePoint);
101       gp_Dir2d aLinDir(aLinVec);
102       thePoint = aCenterPnt.XY() + aLinDir.XY() * ( 2. * anEpsilon );
103       return Standard_False;
104     }
105   }
106
107   return Standard_True;
108 }
109
110 //=======================================================================
111 //function : Reject
112 //purpose  : 
113 //=======================================================================
114
115 Standard_Boolean  BRepClass_FaceExplorer::Reject(const gp_Pnt2d&)const 
116 {
117   return Standard_False;
118 }
119
120 //=======================================================================
121 //function : Segment
122 //purpose  : 
123 //=======================================================================
124
125 Standard_Boolean BRepClass_FaceExplorer::Segment(const gp_Pnt2d& P, 
126                                                  gp_Lin2d& L,
127                                                  Standard_Real& Par)
128 {
129   myCurEdgeInd = 1;
130   myCurEdgePar = Probing_Start;
131
132   return OtherSegment(P, L, Par);
133 }
134
135 //=======================================================================
136 //function : OtherSegment
137 //purpose  : 
138 //=======================================================================
139
140 Standard_Boolean BRepClass_FaceExplorer::OtherSegment(const gp_Pnt2d& P, 
141                                                       gp_Lin2d& L,
142                                                       Standard_Real& Par)
143 {
144   TopExp_Explorer      anExpF(myFace, TopAbs_EDGE);
145   Standard_Integer     i;
146   Standard_Real        aFPar;
147   Standard_Real        aLPar;
148   Handle(Geom2d_Curve) aC2d;
149   Standard_Real        aTolParConf2 = Precision::PConfusion() * Precision::PConfusion();
150   gp_Pnt2d             aPOnC;
151   Standard_Real        aParamIn;
152
153   for (i = 1; anExpF.More(); anExpF.Next(), i++) {
154     if (i != myCurEdgeInd)
155       continue;
156
157     const TopoDS_Shape       &aLocalShape = anExpF.Current();
158     const TopAbs_Orientation  anOrientation = aLocalShape.Orientation();
159
160     if (anOrientation == TopAbs_FORWARD || anOrientation == TopAbs_REVERSED) {
161       const TopoDS_Edge &anEdge = TopoDS::Edge(aLocalShape);
162
163       aC2d = BRep_Tool::CurveOnSurface(anEdge, myFace, aFPar, aLPar);
164
165       if (!aC2d.IsNull()) {
166         // Treatment of infinite cases.
167         if (Precision::IsNegativeInfinite(aFPar)) {
168           if (Precision::IsPositiveInfinite(aLPar)) {
169             aFPar = -1.;
170             aLPar = 1.;
171           }
172           else {
173             aFPar = aLPar - 1.;
174           }
175         }
176         else if (Precision::IsPositiveInfinite(aLPar))
177           aLPar = aFPar + 1.;
178
179         for (; myCurEdgePar < Probing_End; myCurEdgePar += Probing_Step) {
180           aParamIn = myCurEdgePar*aFPar + (1. - myCurEdgePar)*aLPar;
181
182           gp_Vec2d aTanVec;
183           aC2d->D1(aParamIn, aPOnC, aTanVec);
184           Par = aPOnC.SquareDistance(P);
185
186           if (Par > aTolParConf2) {
187             gp_Vec2d aLinVec(P, aPOnC);
188             gp_Dir2d aLinDir(aLinVec);
189
190             Standard_Real aTanMod = aTanVec.SquareMagnitude();
191             if (aTanMod < aTolParConf2)
192               continue;
193             aTanVec /= Sqrt(aTanMod);
194             Standard_Real aSinA = aTanVec.Crossed(aLinDir.XY());
195             const Standard_Real SmallAngle = 0.001;
196             Standard_Boolean isSmallAngle = Standard_False;
197             if (Abs(aSinA) < SmallAngle)
198             {
199               isSmallAngle = Standard_True;
200               // The line from the input point P to the current point on edge
201               // is tangent to the edge curve. This condition is bad for classification.
202               // Therefore try to go to another point in the hope that there will be 
203               // no tangent. If there tangent is preserved then leave the last point in 
204               // order to get this edge chanse to participate in classification.
205               if (myCurEdgePar + Probing_Step < Probing_End)
206                 continue;
207             }
208
209             L = gp_Lin2d(P, aLinDir);
210
211             // Check if ends of a curve lie on a line.
212             aC2d->D0(aFPar, aPOnC);
213             gp_Pnt2d aFPOnC = aPOnC;
214             if (L.SquareDistance(aPOnC) > aTolParConf2) {
215               aC2d->D0(aLPar, aPOnC);
216               if (L.SquareDistance(aPOnC) > aTolParConf2) {
217
218                 if (isSmallAngle)
219                 {
220                   //Try to find minimal distance between curve and line
221
222                   Geom2dAPI_ProjectPointOnCurve aProj;
223                   aProj.Init(P, aC2d, aFPar, aLPar);
224                   if (aProj.NbPoints() > 0)
225                   {
226                     gp_Pnt2d aLPOnC = aPOnC;
227                     Standard_Real aFDist = P.SquareDistance(aFPOnC);
228                     Standard_Real aLDist = P.SquareDistance(aLPOnC);
229                     Standard_Real aMinDist = aProj.LowerDistance();
230                     aMinDist *= aMinDist;
231                     aPOnC = aProj.NearestPoint();
232                     if (aMinDist > aFDist)
233                     {
234                       aMinDist = aFDist;
235                       aPOnC = aFPOnC;
236                     }
237                     //
238                     if (aMinDist > aLDist)
239                     {
240                       aMinDist = aLDist;
241                       aPOnC = aLPOnC;
242                     }
243                     //
244                     if (aMinDist < Par)
245                     {
246                       Par = aMinDist;
247                       if (Par < aTolParConf2)
248                       {
249                         continue;
250                       }
251                       aLinVec.SetXY((aPOnC.XY() - P.XY()));
252                       aLinDir.SetXY(aLinVec.XY());
253                       L = gp_Lin2d(P, aLinDir);
254                     }
255                   }
256                 }
257                 myCurEdgePar += Probing_Step;
258                 if (myCurEdgePar >= Probing_End) {
259                   myCurEdgeInd++;
260                   myCurEdgePar = Probing_Start;
261                 }
262
263                 Par = Sqrt(Par);
264                 return Standard_True;
265               }
266             }
267           }
268         }
269       } // if (!aC2d.IsNull()) {
270     } // if (anOrientation == TopAbs_FORWARD ...
271
272     // This curve is not valid for line construction. Go to another edge.
273     myCurEdgeInd++;
274     myCurEdgePar = Probing_Start;
275   }
276
277   // nothing found, return an horizontal line
278   Par = RealLast();
279   L = gp_Lin2d(P, gp_Dir2d(1, 0));
280
281   return Standard_False;
282 }
283
284 //=======================================================================
285 //function : InitWires
286 //purpose  : 
287 //=======================================================================
288
289 void  BRepClass_FaceExplorer::InitWires()
290 {
291   myWExplorer.Init(myFace,TopAbs_WIRE);
292 }
293
294 //=======================================================================
295 //function : RejectWire NYI
296 //purpose  : 
297 //=======================================================================
298
299 Standard_Boolean  BRepClass_FaceExplorer::RejectWire
300   (const gp_Lin2d& , 
301    const Standard_Real)const 
302 {
303   return Standard_False;
304 }
305
306 //=======================================================================
307 //function : InitEdges
308 //purpose  : 
309 //=======================================================================
310
311 void  BRepClass_FaceExplorer::InitEdges()
312 {
313   myEExplorer.Init(myWExplorer.Current(),TopAbs_EDGE);
314 }
315
316 //=======================================================================
317 //function : RejectEdge NYI
318 //purpose  : 
319 //=======================================================================
320
321 Standard_Boolean  BRepClass_FaceExplorer::RejectEdge
322   (const gp_Lin2d& , 
323    const Standard_Real )const 
324 {
325   return Standard_False;
326 }
327
328
329 //=======================================================================
330 //function : CurrentEdge
331 //purpose  : 
332 //=======================================================================
333
334 void  BRepClass_FaceExplorer::CurrentEdge(BRepClass_Edge& E, 
335                                           TopAbs_Orientation& Or) const 
336 {
337   E.Edge() = TopoDS::Edge(myEExplorer.Current());
338   E.Face() = myFace;
339   Or = E.Edge().Orientation();
340 }
341