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