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