1 // Created on: 2000-01-21
2 // Created by: data exchange team
3 // Copyright (c) 2000-2014 OPEN CASCADE SAS
5 // This file is part of Open CASCADE Technology software library.
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
16 #include <ShapeFix.hxx>
17 //:k2 abv 16.12.98: eliminating code duplication
18 //pdn 18.12.98: checking deviation for SP edges
19 //: abv 22.02.99: method FillFace() removed since PRO13123 is fixed
21 //szv#9:S4244:19Aug99: Added method FixWireGaps
22 //szv#10:S4244:23Aug99: Added method FixFaceGaps
24 #include <BRep_Builder.hxx>
25 #include <BRep_Tool.hxx>
27 #include <Geom2d_Curve.hxx>
28 #include <Geom_Curve.hxx>
30 #include <Precision.hxx>
32 #include <Standard_ErrorHandler.hxx>
33 #include <Standard_Failure.hxx>
35 #include <TopExp_Explorer.hxx>
36 #include <TopLoc_Location.hxx>
38 #include <TopoDS_Edge.hxx>
39 #include <TopoDS_Face.hxx>
40 #include <Geom_Surface.hxx>
44 #include <Geom_Plane.hxx>
45 #include <ShapeFix_Edge.hxx>
46 #include <Geom2dAdaptor_HCurve.hxx>
47 #include <Adaptor3d_CurveOnSurface.hxx>
48 #include <Geom_RectangularTrimmedSurface.hxx>
49 #include <ShapeAnalysis_Surface.hxx>
51 #include <ShapeFix_Edge.hxx>
52 #include <ShapeFix_Shape.hxx>
53 #include <ShapeFix_Wire.hxx>
54 #include <ShapeFix_Face.hxx>
55 #include <TopoDS_Iterator.hxx>
56 #include <GeomAdaptor_HSurface.hxx>
57 #include <TopTools_MapOfShape.hxx>
58 #include <BRepLib.hxx>
60 #include <ShapeAnalysis_Edge.hxx>
61 #include <ShapeBuild_Edge.hxx>
62 #include <TopoDS_Vertex.hxx>
63 #include <ShapeBuild_ReShape.hxx>
64 #include <TColgp_SequenceOfPnt.hxx>
65 #include <TopTools_ListOfShape.hxx>
66 #include <TopTools_ListIteratorOfListOfShape.hxx>
67 #include <TopTools_SequenceOfShape.hxx>
68 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
71 #include <Message_ProgressSentry.hxx>
72 #include <Message_Msg.hxx>
73 #include <ShapeExtend_BasicMsgRegistrator.hxx>
75 //=======================================================================
76 //function : SameParameter
78 //=======================================================================
80 Standard_Boolean ShapeFix::SameParameter(const TopoDS_Shape& shape,
81 const Standard_Boolean enforce,
82 const Standard_Real preci,
83 const Handle(Message_ProgressIndicator)& theProgress,
84 const Handle(ShapeExtend_BasicMsgRegistrator)& theMsgReg)
86 // Calculate number of edges
87 Standard_Integer aNbEdges = 0;
88 for ( TopExp_Explorer anEdgeExp(shape, TopAbs_EDGE); anEdgeExp.More(); anEdgeExp.Next() )
91 // Calculate number of faces
92 Standard_Integer aNbFaces = 0;
93 for ( TopExp_Explorer anEdgeExp(shape, TopAbs_FACE); anEdgeExp.More(); anEdgeExp.Next() )
96 TopTools_IndexedDataMapOfShapeListOfShape aMapEF;
97 TopExp::MapShapesAndAncestors(shape, TopAbs_EDGE, TopAbs_FACE, aMapEF);
100 //Standard_Integer nbexcp = 0;
101 Standard_Integer nbfail = 0, numedge = 0;
102 Standard_Boolean status = Standard_True;
103 Standard_Real tol = preci;
104 Standard_Boolean iatol = (tol > 0);
105 Handle(ShapeFix_Edge) sfe = new ShapeFix_Edge;
106 TopExp_Explorer ex(shape,TopAbs_EDGE);
107 Message_Msg doneMsg("FixEdge.SameParameter.MSG0");
109 // Start progress scope (no need to check if progress exists -- it is safe)
110 Message_ProgressSentry aPSentryForSameParam(theProgress, "Fixing same parameter problem", 0, 2, 1);
113 // Start progress scope (no need to check if progress exists -- it is safe)
114 Message_ProgressSentry aPSentry(theProgress, "Fixing edge", 0, aNbEdges, 1);
119 while ( ex.More() && aPSentry.More() )
124 E = TopoDS::Edge (ex.Current());
128 tol = BRep_Tool::Tolerance (E);
131 B.SameRange (E,Standard_False);
132 B.SameParameter (E,Standard_False);
135 TopTools_ListOfShape aListOfFaces;
136 aMapEF.FindFromKey(E, aListOfFaces);
137 if (aListOfFaces.Extent() != 0)
139 TopTools_ListOfShape::Iterator aListOfFacesIt(aListOfFaces);
140 for ( ; aListOfFacesIt.More() ; aListOfFacesIt.Next())
142 TopoDS_Face aF = TopoDS::Face( aListOfFacesIt.Value() );
143 sfe->FixSameParameter (E, aF);
148 sfe->FixSameParameter (E); // K2-SEP97
151 if (!BRep_Tool::SameParameter (E)) { ierr = 1; nbfail ++; }
155 status = Standard_False;
156 B.SameRange (E,Standard_False);
157 B.SameParameter (E,Standard_False);
159 else if ( !theMsgReg.IsNull() && !sfe->Status( ShapeExtend_OK ) )
161 theMsgReg->Send( E, doneMsg, Message_Warning );
164 // Complete step in current progress scope
168 // Halt algorithm in case of user's abort
169 if ( !aPSentry.More() )
170 return Standard_False;
174 // Switch to "Update tolerances" step
175 aPSentryForSameParam.Next();
178 // Start progress scope (no need to check if progress exists -- it is safe)
179 Message_ProgressSentry aPSentry(theProgress, "Update tolerances", 0, aNbFaces, 1);
181 //:i2 abv 21 Aug 98: ProSTEP TR8 Motor.rle face 710:
182 // Update tolerance of edges on planes (no pcurves are stored)
183 for ( TopExp_Explorer exp ( shape, TopAbs_FACE ); exp.More() && aPSentry.More(); exp.Next(), aPSentry.Next() )
185 TopoDS_Face face = TopoDS::Face ( exp.Current() );
186 Handle(Geom_Surface) Surf = BRep_Tool::Surface ( face );
188 Handle(Geom_Plane) plane = Handle(Geom_Plane)::DownCast ( Surf );
189 if ( plane.IsNull() ) {
190 Handle(Geom_RectangularTrimmedSurface) GRTS =
191 Handle(Geom_RectangularTrimmedSurface)::DownCast ( Surf );
192 if ( ! GRTS.IsNull() )
193 plane = Handle(Geom_Plane)::DownCast ( GRTS->BasisSurface() );
194 if ( plane.IsNull() )
198 Handle(GeomAdaptor_HSurface) AS = new GeomAdaptor_HSurface ( plane );
199 for ( TopExp_Explorer ed ( face, TopAbs_EDGE ); ed.More(); ed.Next() ) {
200 TopoDS_Edge edge = TopoDS::Edge ( ed.Current() );
202 Handle(Geom_Curve) crv = BRep_Tool::Curve ( edge, f, l );
206 Handle(Geom2d_Curve) c2d = BRep_Tool::CurveOnSurface ( edge, face, f, l );;
207 if ( c2d.IsNull() ) continue;
208 Handle(Geom2dAdaptor_HCurve) GHPC = new Geom2dAdaptor_HCurve ( c2d, f, l );
209 Adaptor3d_CurveOnSurface ACS(GHPC,AS);
211 Standard_Real tol0 = BRep_Tool::Tolerance(edge);
213 Standard_Real tol2 = tol*tol;
214 const Standard_Integer NCONTROL = 23;
215 for ( Standard_Integer i = 0; i < NCONTROL; i++ )
217 Standard_Real par = ( f * ( NCONTROL - 1 - i ) + l * i ) / ( NCONTROL - 1 );
218 gp_Pnt pnt = crv->Value ( par );
219 gp_Pnt prj = ACS.Value( par );
220 Standard_Real dist = pnt.SquareDistance(prj);
224 tol = 1.00005 * sqrt(tol2); // coeff: see trj3_pm1-ct-203.stp #19681, edge 10
227 B.UpdateEdge ( edge, tol );
228 for ( TopoDS_Iterator itV(edge); itV.More(); itV.Next() )
230 TopoDS_Shape S = itV.Value();
231 B.UpdateVertex ( TopoDS::Vertex ( S ), tol );
236 // Halt algorithm in case of user's abort
237 if ( !aPSentry.More() )
238 return Standard_False;
244 cout<<"** SameParameter not complete. On "<<numedge<<" Edges:";
245 if (nbfail > 0) cout<<" "<<nbfail<<" Failed";
253 //=======================================================================
254 //function : EncodeRegularity
256 //=======================================================================
258 static void EncodeRegularity (const TopoDS_Shape& shape,
259 const Standard_Real tolang,
260 TopTools_MapOfShape &aMap)
262 TopoDS_Shape S = shape;
265 if ( ! aMap.Add ( S ) ) return;
267 if ( S.ShapeType() == TopAbs_COMPOUND ||
268 S.ShapeType() == TopAbs_COMPSOLID ) {
269 for ( TopoDS_Iterator it(S); it.More(); it.Next() ) {
270 EncodeRegularity ( it.Value(), tolang, aMap );
277 BRepLib::EncodeRegularity ( S, tolang );
279 catch(Standard_Failure) {
281 cout << "Warning: Exception in ShapeFix::EncodeRegularity(): ";
282 Standard_Failure::Caught()->Print ( cout );
288 void ShapeFix::EncodeRegularity (const TopoDS_Shape& shape,
289 const Standard_Real tolang)
291 TopTools_MapOfShape aMap;
292 ::EncodeRegularity ( shape, tolang, aMap );
296 //=======================================================================
297 //function : RemoveSmallEdges
299 //=======================================================================
301 TopoDS_Shape ShapeFix::RemoveSmallEdges (TopoDS_Shape& Shape,
302 const Standard_Real Tolerance,
303 Handle(ShapeBuild_ReShape)& context)
305 Handle(ShapeFix_Shape) sfs = new ShapeFix_Shape;
307 sfs->SetPrecision(Tolerance);
308 sfs->FixFaceTool()->FixMissingSeamMode() = Standard_False;
309 sfs->FixFaceTool()->FixOrientationMode() = Standard_False;
310 sfs->FixFaceTool()->FixSmallAreaWireMode() = Standard_False;
311 sfs->FixWireTool()->ModifyTopologyMode() = Standard_True;
312 //sfs.FixWireTool().FixReorderMode() = Standard_False;
313 sfs->FixWireTool()->FixConnectedMode() = Standard_False;
314 sfs->FixWireTool()->FixEdgeCurvesMode() = Standard_False;
315 sfs->FixWireTool()->FixDegeneratedMode() = Standard_False;
316 sfs->FixWireTool()->FixSelfIntersectionMode() = Standard_False;
317 sfs->FixWireTool()->FixLackingMode() = Standard_False;
318 sfs->FixWireTool()->FixSmallMode() = Standard_True;
320 TopoDS_Shape result = sfs->Shape();
321 context = sfs->Context();
326 //=======================================================================
327 //function : ReplaceVertex
328 //purpose : auxilary for FixVertexPosition
329 //=======================================================================
330 static TopoDS_Edge ReplaceVertex(const TopoDS_Edge& theEdge,
332 const Standard_Boolean theFwd)
334 TopoDS_Vertex aNewVertex;
336 aB.MakeVertex(aNewVertex,theP,Precision::Confusion());
337 TopoDS_Vertex aV1,aV2;
340 aV1.Orientation( TopAbs_FORWARD);
344 aV2.Orientation( TopAbs_REVERSED);
346 ShapeBuild_Edge aSbe;
347 TopoDS_Edge e1 = theEdge;
348 TopAbs_Orientation Ori = e1.Orientation();
349 e1.Orientation(TopAbs_FORWARD);
350 TopoDS_Edge aNewEdge = aSbe.CopyReplaceVertices(e1,aV1,aV2);
351 aNewEdge.Orientation(Ori);
356 //=======================================================================
357 //function : getNearPoint
358 //purpose : auxilary for FixVertexPosition
359 //=======================================================================
360 static Standard_Real getNearPoint(const TColgp_SequenceOfPnt& aSeq1,
361 const TColgp_SequenceOfPnt& aSeq2,
364 Standard_Integer i =1;
365 Standard_Integer ind1 =0,ind2 =0;
366 Standard_Real mindist =RealLast();
367 for( ; i <= aSeq1.Length(); i++) {
368 gp_Pnt p1 = aSeq1.Value(i);
369 Standard_Integer j=1;
370 for( ; j <= aSeq2.Length(); j++) {
371 gp_Pnt p2 = aSeq2.Value(j);
372 Standard_Real d = p1.Distance(p2);
373 if(fabs(d -mindist ) <= Precision::Confusion())
384 acent = (aSeq1.Value(ind1).XYZ() + aSeq2.Value(ind2).XYZ())/2.0;
389 //=======================================================================
390 //function : getNearestEdges
391 //purpose : auxilary for FixVertexPosition
392 //=======================================================================
393 static Standard_Boolean getNearestEdges(TopTools_ListOfShape& theLEdges,
394 const TopoDS_Vertex theVert,
395 TopTools_SequenceOfShape& theSuitEdges,
396 TopTools_SequenceOfShape& theRejectEdges,
397 const Standard_Real theTolerance,
398 gp_XYZ& thecentersuit,
399 gp_XYZ& thecenterreject)
401 if(theLEdges.IsEmpty())
402 return Standard_False;
403 TopTools_MapOfShape aMapEdges;
405 TopTools_ListOfShape atempList;
406 atempList= theLEdges;
407 TopTools_ListIteratorOfListOfShape alIter(atempList);
409 TopoDS_Edge aEdge1 = TopoDS::Edge(alIter.Value());
410 TopoDS_Vertex aVert11,aVert12;
411 TopExp::Vertices(aEdge1, aVert11,aVert12 );
412 aMapEdges.Add(aEdge1);
413 Standard_Real aFirst1,aLast1;
414 Handle(Geom_Curve) aCurve1 = BRep_Tool::Curve(aEdge1,aFirst1,aLast1);
417 Standard_Boolean isFirst1 = theVert.IsSame(aVert11);
418 Standard_Boolean isSame1 = aVert11.IsSame(aVert12);
419 if( !aCurve1.IsNull()) {
421 p11 = aCurve1->Value(aFirst1);
423 p11 = aCurve1->Value(aLast1);
425 p12 = aCurve1->Value(aLast1);
427 else return Standard_False;
429 TopTools_SequenceOfShape aseqreject;
430 TopTools_SequenceOfShape aseqsuit;
432 Standard_Integer anumLoop =0;
433 for( ; alIter.More(); ) {
434 TopoDS_Edge aEdge = TopoDS::Edge(alIter.Value());
435 if( aMapEdges.Contains(aEdge)) {
436 atempList.Remove(alIter);
440 TopoDS_Vertex aVert1,aVert2;
441 TopExp::Vertices(aEdge, aVert1,aVert2 );
442 Standard_Real isFirst = theVert.IsSame(aVert1);
443 Standard_Boolean isSame = aVert1.IsSame(aVert2);
445 Standard_Boolean isLoop = ((aVert1.IsSame(aVert11) && aVert2.IsSame(aVert12)) ||
446 (aVert1.IsSame(aVert12) && aVert2.IsSame(aVert11)));
447 if(isLoop /*&& !aseqsuit.Length()*/ && (atempList.Extent() >anumLoop)) {
448 atempList.Append(aEdge);
449 atempList.Remove(alIter);
453 aMapEdges.Add(aEdge);
454 Standard_Real aFirst,aLast;
455 Handle(Geom_Curve) aCurve = BRep_Tool::Curve(aEdge,aFirst,aLast);
456 if( !aCurve.IsNull()) {
460 p1 = aCurve->Value(aFirst);
462 p1 = aCurve->Value(aLast);
464 p2 = aCurve->Value(aLast);
465 Standard_Real aMinDist = RealLast();
467 if(!isSame && ! isSame1) {
468 aMinDist = p1.Distance(p11);
469 acent = (p1.XYZ() + p11.XYZ())/2.0;
472 TColgp_SequenceOfPnt aSeq1;
473 TColgp_SequenceOfPnt aSeq2;
480 aMinDist = getNearPoint(aSeq1,aSeq2,acent);
483 if(aMinDist > theTolerance) {
484 if(!aseqreject.Length())
485 thecenterreject = acent;
486 aseqreject.Append(aEdge);
489 if(!aseqsuit.Length()) {
490 thecentersuit = acent;
491 aseqsuit.Append(aEdge);
494 aseqsuit.Append(aEdge);
495 else if((thecentersuit - acent).Modulus() < theTolerance)
496 aseqsuit.Append(aEdge);
498 aseqreject.Append(aEdge);
502 atempList.Remove(alIter);
505 Standard_Boolean isDone = (!aseqsuit.IsEmpty() || !aseqreject.IsEmpty());
507 if(aseqsuit.IsEmpty()) {
508 theRejectEdges.Append(aEdge1);
509 theLEdges.RemoveFirst();
511 getNearestEdges(theLEdges,theVert,theSuitEdges,theRejectEdges,
512 theTolerance,thecentersuit,thecenterreject);
515 theSuitEdges.Append(aEdge1);
516 theSuitEdges.Append(aseqsuit);
517 theRejectEdges.Append(aseqreject);
521 theRejectEdges.Append(aEdge1);
527 //=======================================================================
528 //function : FixVertexPosition
530 //=======================================================================
532 Standard_Boolean ShapeFix::FixVertexPosition(TopoDS_Shape& theshape,
533 const Standard_Real theTolerance,
534 const Handle(ShapeBuild_ReShape)& thecontext)
536 TopTools_IndexedDataMapOfShapeListOfShape aMapVertEdges;
537 TopExp_Explorer aExp1(theshape,TopAbs_EDGE);
538 for( ; aExp1.More(); aExp1.Next()) {
540 Standard_Integer nV =1;
541 TopoDS_Iterator aExp3(aExp1.Current());
542 for( ; aExp3.More(); aExp3.Next(),nV++) {
543 TopoDS_Shape aVert = aExp3.Value();
546 else if(aVert1.IsSame(aVert))
548 if(aMapVertEdges.Contains(aVert))
549 aMapVertEdges.ChangeFromKey(aVert).Append(aExp1.Current());
551 TopTools_ListOfShape alEdges;
552 alEdges.Append(aExp1.Current());
553 aMapVertEdges.Add(aVert,alEdges);
557 Standard_Boolean isDone = Standard_False;
558 Standard_Integer i=1;
559 for( ; i <= aMapVertEdges.Extent(); i++) {
560 TopoDS_Vertex aVert = TopoDS::Vertex(aMapVertEdges.FindKey(i));
561 Standard_Real aTolVert = BRep_Tool::Tolerance(aVert);
562 if(aTolVert <= theTolerance)
566 aB1.UpdateVertex(aVert,theTolerance);
567 gp_Pnt aPvert = BRep_Tool::Pnt(aVert);
568 gp_XYZ acenter(aPvert.XYZ()), acenterreject(aPvert.XYZ());
570 TopTools_SequenceOfShape aSuitEdges;
571 TopTools_SequenceOfShape aRejectEdges;
572 TopTools_ListOfShape aledges;
573 aledges= aMapVertEdges.FindFromIndex(i);
574 if(aledges.Extent() ==1)
576 //if tolerance of vertex is more than specified tolerance
577 // check distance between curves and vertex
579 if(!getNearestEdges(aledges,aVert,aSuitEdges,aRejectEdges,theTolerance,acenter,acenterreject))
582 //update vertex by nearest point
583 Standard_Boolean isAdd = Standard_False;
584 Standard_Integer k =1;
585 for( ; k <= aSuitEdges.Length(); k++) {
587 TopoDS_Edge aEdgeOld = TopoDS::Edge(aSuitEdges.Value(k));
588 TopoDS_Vertex aVert1,aVert2;
589 TopExp::Vertices(aEdgeOld, aVert1,aVert2 );
591 Standard_Boolean isFirst = (aVert1.IsSame(aVert));
592 Standard_Boolean isLast = (aVert2.IsSame(aVert));
593 if(!isFirst && !isLast)
595 Standard_Real aFirst,aLast;
596 Handle(Geom_Curve) aCurve;
597 TopoDS_Edge aEdge = TopoDS::Edge(thecontext->Apply(aEdgeOld));
599 TopoDS_Vertex aVert1n,aVert2n;
600 TopExp::Vertices(aEdge, aVert1n,aVert2n );
601 aCurve = BRep_Tool::Curve(aEdge,aFirst,aLast);
602 if( !aCurve.IsNull()) {
603 gp_Pnt p1 = aCurve->Value(aFirst);
604 gp_Pnt p2 = aCurve->Value(aLast);
606 //if distance between ends of curve more than specified tolerance
607 //but vertices are the same that one of the vertex will be replaced.
609 Standard_Boolean isReplace = (aVert1n.IsSame(aVert2n) && p1.Distance(p2) >theTolerance);
611 //Standard_Real dd1 = (acenter - p1.XYZ()).Modulus();
612 //Standard_Real dd2 = (acenter - p2.XYZ()).Modulus();
620 if(p1.Distance(acenter) < p2.Distance(acenter))
621 enew = ReplaceVertex(aEdge,p2,Standard_False);
623 enew = ReplaceVertex(aEdge,p1,Standard_True);
624 thecontext->Replace(aEdge,enew);
625 isDone = Standard_True;
635 if(p1.Distance(acenter) < p2.Distance(acenter))
636 enew = ReplaceVertex(aEdge,p2,Standard_False);
638 enew = ReplaceVertex(aEdge,p1,Standard_True);
639 thecontext->Replace(aEdge,enew);
640 isDone = Standard_True;
646 isAdd = Standard_True;
652 if(isAdd && aPvert.Distance(acenter) > theTolerance)
657 // aB.UpdateVertex(aVert,Precision::Confusion());
659 isDone = Standard_True;
660 TopoDS_Vertex aNewVertex;
661 aB.MakeVertex(aNewVertex,acenter,Precision::Confusion());
662 aNewVertex.Orientation(aVert.Orientation());
663 thecontext->Replace(aVert,aNewVertex);
667 for( k =1; k <= aRejectEdges.Length(); k++) {
668 TopoDS_Edge aEdgeOld = TopoDS::Edge( aRejectEdges.Value(k));
669 TopoDS_Vertex aVert1,aVert2;
670 TopExp::Vertices(aEdgeOld, aVert1,aVert2 );
672 Standard_Boolean isFirst = (aVert1.IsSame(aVert));
673 Standard_Boolean isLast = (aVert2.IsSame(aVert));
674 if(!isFirst && !isLast)
676 Standard_Boolean isSame = aVert1.IsSame(aVert2);
677 Handle(Geom_Curve) aCurve;
678 TopoDS_Edge aEdge = TopoDS::Edge(thecontext->Apply(aEdgeOld));
680 TopoDS_Vertex aVert1n,aVert2n;
681 TopExp::Vertices(aEdge, aVert1n,aVert2n );
683 Standard_Real aFirst,aLast;
684 aCurve = BRep_Tool::Curve(aEdge,aFirst,aLast);
685 if( !aCurve.IsNull()) {
686 gp_Pnt p1 = aCurve->Value(aFirst);
687 gp_Pnt p2 = aCurve->Value(aLast);
690 enew = ReplaceVertex(aEdge,p1,Standard_True);
692 enew = ReplaceVertex(enew,p2,Standard_False);
695 enew = ReplaceVertex(aEdge,p2,Standard_False);
697 enew = ReplaceVertex(enew ,p1,Standard_True);
700 thecontext->Replace(aEdge,enew);
701 isDone = Standard_True;
709 theshape = thecontext->Apply(theshape);
714 //=======================================================================
715 //function : LeastEdgeSize
717 //=======================================================================
719 Standard_Real ShapeFix::LeastEdgeSize(TopoDS_Shape& theShape)
721 Standard_Real aRes = RealLast();
722 for(TopExp_Explorer exp(theShape,TopAbs_EDGE); exp.More(); exp.Next()) {
723 TopoDS_Edge edge = TopoDS::Edge ( exp.Current() );
724 Standard_Real first,last;
725 Handle(Geom_Curve) c3d = BRep_Tool::Curve(edge, first, last);
728 bb.Add(c3d->Value(first));
729 bb.Add(c3d->Value(last));
730 bb.Add(c3d->Value((last+first)/2.));
731 Standard_Real x1,x2,y1,y2,z1,z2,size;
732 bb.Get(x1,y1,z1,x2,y2,z2);
733 size = (x2-x1)*(x2-x1) + (y2-y1)*(y2-y1) + (z2-z1)*(z2-z1);
734 if(size<aRes) aRes = size;