b311480e |
1 | // Created on: 1994-07-22 |
2 | // Created by: Remi LEQUETTE |
3 | // Copyright (c) 1994-1999 Matra Datavision |
973c2be1 |
4 | // Copyright (c) 1999-2014 OPEN CASCADE SAS |
b311480e |
5 | // |
973c2be1 |
6 | // This file is part of Open CASCADE Technology software library. |
b311480e |
7 | // |
d5f74e42 |
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 |
973c2be1 |
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. |
b311480e |
13 | // |
973c2be1 |
14 | // Alternatively, this file may be used under the terms of Open CASCADE |
15 | // commercial license or contractual agreement. |
7fd59977 |
16 | |
7fd59977 |
17 | |
42cf5bc1 |
18 | #include <BRep_Builder.hxx> |
19 | #include <BRep_Tool.hxx> |
20 | #include <BRepAdaptor_Curve.hxx> |
21 | #include <BRepAdaptor_Surface.hxx> |
22 | #include <BRepLib_FindSurface.hxx> |
23 | #include <BRepLib_MakeFace.hxx> |
24 | #include <BRepTools_WireExplorer.hxx> |
25 | #include <BRepTopAdaptor_FClass2d.hxx> |
26 | #include <Geom2d_Curve.hxx> |
27 | #include <Geom_BezierCurve.hxx> |
28 | #include <Geom_BSplineCurve.hxx> |
29 | #include <Geom_Plane.hxx> |
30 | #include <Geom_RectangularTrimmedSurface.hxx> |
31 | #include <Geom_Surface.hxx> |
32 | #include <GeomLib.hxx> |
33 | #include <gp_Ax2.hxx> |
34 | #include <gp_Ax3.hxx> |
7fd59977 |
35 | #include <gp_Circ.hxx> |
36 | #include <gp_Elips.hxx> |
37 | #include <gp_Hypr.hxx> |
42cf5bc1 |
38 | #include <gp_Lin.hxx> |
7fd59977 |
39 | #include <gp_Parab.hxx> |
7fd59977 |
40 | #include <gp_Vec.hxx> |
42cf5bc1 |
41 | #include <math_Jacobi.hxx> |
42 | #include <math_Matrix.hxx> |
43 | #include <math_Vector.hxx> |
44 | #include <Precision.hxx> |
45 | #include <Standard_ErrorHandler.hxx> |
46 | #include <Standard_NoSuchObject.hxx> |
7fd59977 |
47 | #include <TColgp_Array1OfPnt.hxx> |
48 | #include <TColgp_HArray1OfPnt.hxx> |
42cf5bc1 |
49 | #include <TColgp_SequenceOfPnt.hxx> |
50 | #include <TColStd_SequenceOfReal.hxx> |
0f5cd7d5 |
51 | #include <TopExp.hxx> |
52 | #include <TopExp_Explorer.hxx> |
42cf5bc1 |
53 | #include <TopLoc_Location.hxx> |
54 | #include <TopoDS.hxx> |
55 | #include <TopoDS_Shape.hxx> |
0f5cd7d5 |
56 | #include <TopoDS_Vertex.hxx> |
57 | #include <TopoDS_Wire.hxx> |
5646c90e |
58 | #include <NCollection_Vector.hxx> |
7fd59977 |
59 | |
60 | //======================================================================= |
61 | //function : Controle |
62 | //purpose : |
63 | //======================================================================= |
64 | static Standard_Real Controle(const TColgp_SequenceOfPnt& thePoints, |
873c119f |
65 | const Handle(Geom_Plane)& thePlane) |
7fd59977 |
66 | { |
67 | Standard_Real dfMaxDist=0.; |
68 | Standard_Real a,b,c,d, dist; |
69 | Standard_Integer ii; |
70 | thePlane->Coefficients(a,b,c,d); |
71 | for (ii=1; ii<=thePoints.Length(); ii++) { |
72 | const gp_XYZ& xyz = thePoints(ii).XYZ(); |
73 | dist = Abs(a*xyz.X() + b*xyz.Y() + c*xyz.Z() + d); |
74 | if (dist > dfMaxDist) |
75 | dfMaxDist = dist; |
76 | } |
77 | |
78 | return dfMaxDist; |
79 | } |
0f5cd7d5 |
80 | //======================================================================= |
81 | //function : Is2DConnected |
82 | //purpose : Return true if the last vertex of theEdge1 coincides with |
83 | // the first vertex of theEdge2 in parametric space of theFace |
84 | //======================================================================= |
26347898 |
85 | inline static Standard_Boolean Is2DConnected(const TopoDS_Edge& theEdge1, |
873c119f |
86 | const TopoDS_Edge& theEdge2, |
87 | const Handle(Geom_Surface)& theSurface, |
88 | const TopLoc_Location& theLocation) |
0f5cd7d5 |
89 | { |
90 | Standard_Real f,l; |
26347898 |
91 | //TopLoc_Location aLoc; |
0f5cd7d5 |
92 | Handle(Geom2d_Curve) aCurve; |
93 | gp_Pnt2d p1, p2; |
94 | |
95 | // get 2D points |
26347898 |
96 | aCurve=BRep_Tool::CurveOnSurface(theEdge1, theSurface, theLocation, f, l); |
0f5cd7d5 |
97 | p1 = aCurve->Value( theEdge1.Orientation() == TopAbs_FORWARD ? l : f ); |
26347898 |
98 | aCurve=BRep_Tool::CurveOnSurface(theEdge2, theSurface, theLocation, f, l); |
0f5cd7d5 |
99 | p2 = aCurve->Value( theEdge2.Orientation() == TopAbs_FORWARD ? f : l ); |
100 | |
101 | // compare 2D points |
26347898 |
102 | GeomAdaptor_Surface aSurface( theSurface ); |
103 | TopoDS_Vertex aV = TopExp::FirstVertex( theEdge2, Standard_True ); |
0f5cd7d5 |
104 | Standard_Real tol3D = BRep_Tool::Tolerance( aV ); |
105 | Standard_Real tol2D = aSurface.UResolution( tol3D ) + aSurface.VResolution( tol3D ); |
106 | Standard_Real dist2 = p1.SquareDistance( p2 ); |
107 | return dist2 < tol2D * tol2D; |
108 | } |
109 | |
110 | //======================================================================= |
111 | //function : Is2DClosed |
112 | //purpose : Return true if edges of theShape form a closed wire in |
113 | // parametric space of theSurface |
114 | //======================================================================= |
115 | |
26347898 |
116 | static Standard_Boolean Is2DClosed(const TopoDS_Shape& theShape, |
873c119f |
117 | const Handle(Geom_Surface)& theSurface, |
118 | const TopLoc_Location& theLocation) |
0f5cd7d5 |
119 | { |
120 | try |
121 | { |
1f0adf31 |
122 | OCC_CATCH_SIGNALS |
0f5cd7d5 |
123 | // get a wire theShape |
124 | TopExp_Explorer aWireExp( theShape, TopAbs_WIRE ); |
26347898 |
125 | if ( !aWireExp.More() ) { |
0f5cd7d5 |
126 | return Standard_False; |
26347898 |
127 | } |
0f5cd7d5 |
128 | TopoDS_Wire aWire = TopoDS::Wire( aWireExp.Current() ); |
129 | // a tmp face |
130 | TopoDS_Face aTmpFace = BRepLib_MakeFace( theSurface, Precision::PConfusion() ); |
131 | |
132 | // check topological closeness using wire explorer, if the wire is not closed |
133 | // the 1st and the last vertices of wire are different |
134 | BRepTools_WireExplorer aWireExplorer( aWire, aTmpFace ); |
26347898 |
135 | if ( !aWireExplorer.More()) { |
0f5cd7d5 |
136 | return Standard_False; |
26347898 |
137 | } |
0f5cd7d5 |
138 | // remember the 1st and the last edges of aWire |
139 | TopoDS_Edge aFisrtEdge = aWireExplorer.Current(), aLastEdge = aFisrtEdge; |
140 | // check if edges connected topologically (that is assured by BRepTools_WireExplorer) |
141 | // are connected in 2D |
142 | TopoDS_Edge aPrevEdge = aFisrtEdge; |
26347898 |
143 | for ( aWireExplorer.Next(); aWireExplorer.More(); aWireExplorer.Next() ) { |
0f5cd7d5 |
144 | aLastEdge = aWireExplorer.Current(); |
26347898 |
145 | if ( !Is2DConnected( aPrevEdge, aLastEdge, theSurface, theLocation)) { |
0f5cd7d5 |
146 | return false; |
26347898 |
147 | } |
0f5cd7d5 |
148 | aPrevEdge = aLastEdge; |
149 | } |
150 | // wire is closed if ( 1st vertex of aFisrtEdge ) == |
151 | // ( last vertex of aLastEdge ) in 2D |
26347898 |
152 | TopoDS_Vertex aV1 = TopExp::FirstVertex( aFisrtEdge, Standard_True ); |
153 | TopoDS_Vertex aV2 = TopExp::LastVertex( aLastEdge, Standard_True ); |
154 | return ( aV1.IsSame( aV2 ) && Is2DConnected( aLastEdge, aFisrtEdge, theSurface, theLocation)); |
0f5cd7d5 |
155 | } |
a738b534 |
156 | catch (Standard_Failure const&) { |
0f5cd7d5 |
157 | return Standard_False; |
158 | } |
159 | } |
7fd59977 |
160 | //======================================================================= |
161 | //function : BRepLib_FindSurface |
162 | //purpose : |
163 | //======================================================================= |
d533dafb |
164 | BRepLib_FindSurface::BRepLib_FindSurface() |
165 | : myTolerance(0.0), |
166 | myTolReached(0.0), |
167 | isExisted(Standard_False) |
7fd59977 |
168 | { |
169 | } |
170 | //======================================================================= |
171 | //function : BRepLib_FindSurface |
172 | //purpose : |
173 | //======================================================================= |
174 | BRepLib_FindSurface::BRepLib_FindSurface(const TopoDS_Shape& S, |
873c119f |
175 | const Standard_Real Tol, |
176 | const Standard_Boolean OnlyPlane, |
177 | const Standard_Boolean OnlyClosed) |
7fd59977 |
178 | { |
0f5cd7d5 |
179 | Init(S,Tol,OnlyPlane,OnlyClosed); |
7fd59977 |
180 | } |
5646c90e |
181 | |
182 | namespace |
183 | { |
184 | static void fillParams (const TColStd_Array1OfReal& theKnots, |
185 | Standard_Integer theDegree, |
186 | Standard_Real theParMin, |
187 | Standard_Real theParMax, |
188 | NCollection_Vector<Standard_Real>& theParams) |
189 | { |
190 | Standard_Real aPrevPar = theParMin; |
191 | theParams.Append (aPrevPar); |
192 | |
193 | Standard_Integer aNbP = Max (theDegree, 1); |
194 | |
195 | for (Standard_Integer i = 1; |
196 | (i < theKnots.Length()) && (theKnots (i) < (theParMax - Precision::PConfusion())); ++i) |
197 | { |
198 | if (theKnots (i + 1) < theParMin + Precision::PConfusion()) |
199 | continue; |
200 | |
201 | Standard_Real aStep = (theKnots (i + 1) - theKnots (i)) / aNbP; |
202 | for (Standard_Integer k = 1; k <= aNbP ; ++k) |
203 | { |
204 | Standard_Real aPar = theKnots (i) + k * aStep; |
205 | if (aPar > theParMax - Precision::PConfusion()) |
206 | break; |
207 | |
208 | if (aPar > aPrevPar + Precision::PConfusion()) |
209 | { |
210 | theParams.Append (aPar); |
211 | aPrevPar = aPar; |
212 | } |
213 | } |
214 | } |
215 | theParams.Append (theParMax); |
216 | } |
217 | |
218 | static void fillPoints (const BRepAdaptor_Curve& theCurve, |
219 | const NCollection_Vector<Standard_Real> theParams, |
220 | TColgp_SequenceOfPnt& thePoints, |
221 | TColStd_SequenceOfReal& theWeights) |
222 | { |
223 | Standard_Real aDistPrev = 0., aDistNext; |
224 | gp_Pnt aPPrev (theCurve.Value (theParams (0))), aPNext; |
225 | |
226 | for (Standard_Integer iP = 1; iP <= theParams.Length(); ++iP) |
227 | { |
228 | if (iP < theParams.Length()) |
229 | { |
230 | Standard_Real aParam = theParams (iP); |
231 | aPNext = theCurve.Value (aParam); |
232 | aDistNext = aPPrev.Distance (aPNext); |
233 | } |
234 | else |
235 | aDistNext = 0.0; |
236 | |
237 | thePoints.Append (aPPrev); |
238 | theWeights.Append (aDistPrev + aDistNext); |
239 | aDistPrev = aDistNext; |
240 | aPPrev = aPNext; |
241 | } |
242 | } |
243 | |
244 | } |
7fd59977 |
245 | //======================================================================= |
246 | //function : Init |
247 | //purpose : |
248 | //======================================================================= |
249 | void BRepLib_FindSurface::Init(const TopoDS_Shape& S, |
873c119f |
250 | const Standard_Real Tol, |
251 | const Standard_Boolean OnlyPlane, |
252 | const Standard_Boolean OnlyClosed) |
7fd59977 |
253 | { |
254 | myTolerance = Tol; |
255 | myTolReached = 0.; |
256 | isExisted = Standard_False; |
257 | myLocation.Identity(); |
258 | mySurface.Nullify(); |
259 | |
260 | // compute the tolerance |
261 | TopExp_Explorer ex; |
262 | |
263 | for (ex.Init(S,TopAbs_EDGE); ex.More(); ex.Next()) { |
264 | Standard_Real t = BRep_Tool::Tolerance(TopoDS::Edge(ex.Current())); |
265 | if (t > myTolerance) myTolerance = t; |
266 | } |
267 | |
268 | // search an existing surface |
269 | ex.Init(S,TopAbs_EDGE); |
270 | if (!ex.More()) return; // no edges .... |
271 | |
272 | TopoDS_Edge E = TopoDS::Edge(ex.Current()); |
273 | Standard_Real f,l,ff,ll; |
f1a70360 |
274 | Handle(Geom2d_Curve) PC,aPPC; |
7fd59977 |
275 | Handle(Geom_Surface) SS; |
276 | TopLoc_Location L; |
277 | Standard_Integer i = 0,j; |
278 | |
279 | // iterate on the surfaces of the first edge |
302f96fb |
280 | for(;;) { |
7fd59977 |
281 | i++; |
282 | BRep_Tool::CurveOnSurface(E,PC,mySurface,myLocation,f,l,i); |
283 | if (mySurface.IsNull()) { |
284 | break; |
285 | } |
286 | // check the other edges |
287 | for (ex.Init(S,TopAbs_EDGE); ex.More(); ex.Next()) { |
288 | if (!E.IsSame(ex.Current())) { |
43dbdb15 |
289 | j = 0; |
290 | for(;;) { |
291 | j++; |
f1a70360 |
292 | BRep_Tool::CurveOnSurface(TopoDS::Edge(ex.Current()),aPPC,SS,L,ff,ll,j); |
43dbdb15 |
293 | if (SS.IsNull()) { |
294 | break; |
295 | } |
1f0adf31 |
296 | if ((SS == mySurface) && (L.IsEqual(myLocation))) { |
43dbdb15 |
297 | break; |
298 | } |
299 | SS.Nullify(); |
300 | } |
7fd59977 |
301 | |
43dbdb15 |
302 | if (SS.IsNull()) { |
303 | mySurface.Nullify(); |
304 | break; |
305 | } |
7fd59977 |
306 | } |
307 | } |
308 | |
309 | // if OnlyPlane, eval if mySurface is a plane. |
310 | if ( OnlyPlane && !mySurface.IsNull() ) |
0f5cd7d5 |
311 | { |
312 | if ( mySurface->IsKind( STANDARD_TYPE(Geom_RectangularTrimmedSurface))) |
313 | mySurface = Handle(Geom_RectangularTrimmedSurface)::DownCast(mySurface)->BasisSurface(); |
7fd59977 |
314 | mySurface = Handle(Geom_Plane)::DownCast(mySurface); |
0f5cd7d5 |
315 | } |
7fd59977 |
316 | |
0f5cd7d5 |
317 | if (!mySurface.IsNull()) |
318 | // if S is e.g. the bottom face of a cylinder, mySurface can be the |
319 | // lateral (cylindrical) face of the cylinder; reject an improper mySurface |
26347898 |
320 | if ( !OnlyClosed || Is2DClosed( S, mySurface, myLocation )) |
0f5cd7d5 |
321 | break; |
7fd59977 |
322 | } |
323 | |
324 | if (!mySurface.IsNull()) { |
325 | isExisted = Standard_True; |
326 | return; |
327 | } |
328 | // |
329 | // no existing surface, search a plane |
330 | // 07/02/02 akm vvv : (OCC157) changed algorithm |
331 | // 1. Collect the points along all edges of the shape |
332 | // For each point calculate the WEIGHT = sum of |
333 | // distances from neighboring points (_only_ same edge) |
334 | // 2. Minimizing the weighed sum of squared deviations |
335 | // compute coefficients of the sought plane. |
43dbdb15 |
336 | |
7fd59977 |
337 | TColgp_SequenceOfPnt aPoints; |
338 | TColStd_SequenceOfReal aWeight; |
339 | |
340 | // ======================= Step #1 |
341 | for (ex.Init(S,TopAbs_EDGE); ex.More(); ex.Next()) |
342 | { |
343 | BRepAdaptor_Curve c(TopoDS::Edge(ex.Current())); |
344 | |
345 | Standard_Real dfUf = c.FirstParameter(); |
346 | Standard_Real dfUl = c.LastParameter(); |
347 | if (IsEqual(dfUf,dfUl)) { |
348 | // Degenerate |
349 | continue; |
350 | } |
351 | Standard_Integer iNbPoints=0; |
352 | |
5646c90e |
353 | // Fill the parameters of the sampling points |
354 | NCollection_Vector<Standard_Real> aParams; |
7fd59977 |
355 | switch (c.GetType()) |
356 | { |
5646c90e |
357 | case GeomAbs_BezierCurve: |
7fd59977 |
358 | { |
43dbdb15 |
359 | Handle(Geom_BezierCurve) GC = c.Bezier(); |
5646c90e |
360 | TColStd_Array1OfReal aKnots (1, 2); |
361 | aKnots.SetValue (1, GC->FirstParameter()); |
362 | aKnots.SetValue (2, GC->LastParameter()); |
363 | |
364 | fillParams (aKnots, GC->Degree(), dfUf, dfUl, aParams); |
365 | break; |
7fd59977 |
366 | } |
5646c90e |
367 | case GeomAbs_BSplineCurve: |
7fd59977 |
368 | { |
43dbdb15 |
369 | Handle(Geom_BSplineCurve) GC = c.BSpline(); |
5646c90e |
370 | fillParams (GC->Knots(), GC->Degree(), dfUf, dfUl, aParams); |
371 | break; |
7fd59977 |
372 | } |
5646c90e |
373 | case GeomAbs_Line: |
374 | { |
375 | // Two points on a straight segment |
376 | aParams.Append (dfUf); |
377 | aParams.Append (dfUl); |
378 | break; |
379 | } |
380 | case GeomAbs_Circle: |
381 | case GeomAbs_Ellipse: |
382 | case GeomAbs_Hyperbola: |
383 | case GeomAbs_Parabola: |
384 | // Four points on other analytical curves |
385 | iNbPoints = 4; |
386 | Standard_FALLTHROUGH |
387 | default: |
7fd59977 |
388 | { |
43dbdb15 |
389 | // Put some points on other curves |
5646c90e |
390 | if (iNbPoints == 0) |
391 | iNbPoints = 15 + c.NbIntervals (GeomAbs_C3); |
392 | |
393 | TColStd_Array1OfReal aBounds (1, 2); |
394 | aBounds.SetValue (1, dfUf); |
395 | aBounds.SetValue (2, dfUl); |
396 | |
397 | fillParams (aBounds, iNbPoints - 1, dfUf, dfUl, aParams); |
398 | } |
399 | } |
400 | |
401 | // Add the points with weights to the sequences |
402 | fillPoints (c, aParams, aPoints, aWeight); |
403 | } |
43dbdb15 |
404 | |
7fd59977 |
405 | if (aPoints.Length() < 3) { |
406 | return; |
407 | } |
408 | |
409 | // ======================= Step #2 |
410 | myLocation.Identity(); |
411 | Standard_Integer iPoint; |
412 | math_Matrix aMat (1,3,1,3, 0.); |
413 | math_Vector aVec (1,3, 0.); |
414 | // Find the barycenter and normalize weights |
415 | Standard_Real dfMaxWeight=0.; |
416 | gp_XYZ aBaryCenter(0.,0.,0.); |
417 | Standard_Real dfSumWeight=0.; |
418 | for (iPoint=1; iPoint<=aPoints.Length(); iPoint++) { |
419 | Standard_Real dfW = aWeight(iPoint); |
420 | aBaryCenter += dfW*aPoints(iPoint).XYZ(); |
421 | dfSumWeight += dfW; |
422 | if (dfW > dfMaxWeight) { |
423 | dfMaxWeight = dfW; |
424 | } |
425 | } |
426 | aBaryCenter /= dfSumWeight; |
427 | |
428 | // Fill the matrix and the right vector |
429 | for (iPoint=1; iPoint<=aPoints.Length(); iPoint++) { |
430 | gp_XYZ p=aPoints(iPoint).XYZ()-aBaryCenter; |
431 | Standard_Real w=aWeight(iPoint)/dfMaxWeight; |
432 | aMat(1,1)+=w*p.X()*p.X(); |
43dbdb15 |
433 | aMat(1,2)+=w*p.X()*p.Y(); |
434 | aMat(1,3)+=w*p.X()*p.Z(); |
873c119f |
435 | // |
43dbdb15 |
436 | aMat(2,2)+=w*p.Y()*p.Y(); |
437 | aMat(2,3)+=w*p.Y()*p.Z(); |
873c119f |
438 | // |
43dbdb15 |
439 | aMat(3,3)+=w*p.Z()*p.Z(); |
7fd59977 |
440 | } |
873c119f |
441 | aMat(2,1) = aMat(1,2); |
442 | aMat(3,1) = aMat(1,3); |
443 | aMat(3,2) = aMat(2,3); |
7fd59977 |
444 | // |
873c119f |
445 | math_Jacobi anEignval(aMat); |
446 | math_Vector anEVals(1,3); |
447 | Standard_Boolean isSolved = anEignval.IsDone(); |
448 | Standard_Integer isol = 0; |
449 | if(isSolved) |
450 | { |
451 | anEVals = anEignval.Values(); |
452 | //We need vector with eigenvalue ~ 0. |
453 | Standard_Real anEMin = RealLast(); |
454 | Standard_Real anEMax = -anEMin; |
455 | for(i = 1; i <= 3; ++i) |
456 | { |
457 | Standard_Real anE = Abs(anEVals(i)); |
458 | if(anEMin > anE) |
459 | { |
460 | anEMin = anE; |
461 | isol = i; |
462 | } |
463 | if(anEMax < anE) |
464 | { |
465 | anEMax = anE; |
466 | } |
467 | } |
468 | |
469 | if(isol == 0) |
470 | { |
7fd59977 |
471 | isSolved = Standard_False; |
472 | } |
873c119f |
473 | else |
474 | { |
475 | Standard_Real eps = Epsilon(anEMax); |
476 | if(anEMin <= eps) |
477 | { |
478 | anEignval.Vector(isol, aVec); |
479 | } |
480 | else |
481 | { |
482 | //try using vector product of other axes |
483 | Standard_Integer ind[2] = {0,0}; |
484 | for(i = 1; i <= 3; ++i) |
485 | { |
486 | if(i == isol) |
487 | { |
488 | continue; |
489 | } |
490 | if(ind[0] == 0) |
491 | { |
492 | ind[0] = i; |
493 | continue; |
494 | } |
495 | if(ind[1] == 0) |
496 | { |
497 | ind[1] = i; |
498 | continue; |
499 | } |
500 | } |
501 | math_Vector aVec1(1, 3, 0.), aVec2(1, 3, 0.); |
502 | anEignval.Vector(ind[0], aVec1); |
503 | anEignval.Vector(ind[1], aVec2); |
504 | gp_Vec aV1(aVec1(1), aVec1(2), aVec1(3)); |
505 | gp_Vec aV2(aVec2(1), aVec2(2), aVec2(3)); |
506 | gp_Vec aN = aV1^ aV2; |
507 | aVec(1) = aN.X(); |
508 | aVec(2) = aN.Y(); |
509 | aVec(3) = aN.Z(); |
510 | } |
511 | if (aVec.Norm2() < gp::Resolution()) { |
512 | isSolved = Standard_False; |
513 | } |
514 | } |
7fd59977 |
515 | } |
873c119f |
516 | |
5646c90e |
517 | if (!isSolved) |
518 | return; |
873c119f |
519 | |
5646c90e |
520 | gp_Vec aN (aVec (1), aVec (2), aVec (3)); |
521 | Handle(Geom_Plane) aPlane = new Geom_Plane (aBaryCenter, aN); |
522 | myTolReached = Controle (aPoints, aPlane); |
523 | const Standard_Real aWeakness = 5.0; |
524 | if (myTolReached <= myTolerance || (Tol < 0 && myTolReached < myTolerance * aWeakness)) |
525 | { |
7fd59977 |
526 | mySurface = aPlane; |
873c119f |
527 | //If S is wire, try to orient surface according to orientation of wire. |
5646c90e |
528 | if (S.ShapeType() == TopAbs_WIRE && S.Closed()) |
873c119f |
529 | { |
5646c90e |
530 | TopoDS_Wire aW = TopoDS::Wire (S); |
531 | TopoDS_Face aTmpFace = BRepLib_MakeFace (mySurface, Precision::Confusion()); |
873c119f |
532 | BRep_Builder BB; |
5646c90e |
533 | BB.Add (aTmpFace, aW); |
534 | BRepTopAdaptor_FClass2d FClass (aTmpFace, 0.); |
535 | if (FClass.PerformInfinitePoint() == TopAbs_IN) |
873c119f |
536 | { |
5646c90e |
537 | gp_Dir aNorm = aPlane->Position().Direction(); |
538 | aNorm.Reverse(); |
539 | mySurface = new Geom_Plane (aPlane->Position().Location(), aNorm); |
873c119f |
540 | } |
873c119f |
541 | } |
7fd59977 |
542 | } |
7fd59977 |
543 | } |
544 | //======================================================================= |
545 | //function : Found |
546 | //purpose : |
547 | //======================================================================= |
548 | Standard_Boolean BRepLib_FindSurface::Found() const |
549 | { |
550 | return !mySurface.IsNull(); |
551 | } |
552 | //======================================================================= |
553 | //function : Surface |
554 | //purpose : |
555 | //======================================================================= |
556 | Handle(Geom_Surface) BRepLib_FindSurface::Surface() const |
557 | { |
558 | return mySurface; |
559 | } |
560 | //======================================================================= |
561 | //function : Tolerance |
562 | //purpose : |
563 | //======================================================================= |
564 | Standard_Real BRepLib_FindSurface::Tolerance() const |
565 | { |
566 | return myTolerance; |
567 | } |
568 | //======================================================================= |
569 | //function : ToleranceReached |
570 | //purpose : |
571 | //======================================================================= |
572 | Standard_Real BRepLib_FindSurface::ToleranceReached() const |
573 | { |
574 | return myTolReached; |
575 | } |
576 | //======================================================================= |
577 | //function : Existed |
578 | //purpose : |
579 | //======================================================================= |
580 | Standard_Boolean BRepLib_FindSurface::Existed() const |
581 | { |
582 | return isExisted; |
583 | } |
584 | //======================================================================= |
585 | //function : Location |
586 | //purpose : |
587 | //======================================================================= |
588 | TopLoc_Location BRepLib_FindSurface::Location() const |
589 | { |
590 | return myLocation; |
591 | } |
26347898 |
592 | |