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