1 // Created on: 2015-04-24
2 // Created by: NIKOLAI BUKHALOV
3 // Copyright (c) 2015 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 <BRepBuilderAPI_FastSewing.hxx>
18 #include <BRepTools_Quilt.hxx>
19 #include <Bnd_Box.hxx>
21 #include <Geom2d_Line.hxx>
22 #include <Geom2d_TrimmedCurve.hxx>
23 #include <Geom_Curve.hxx>
24 #include <Geom_RectangularTrimmedSurface.hxx>
25 #include <Geom_Surface.hxx>
27 #include <Precision.hxx>
29 #include <Standard_NullObject.hxx>
31 #include <TopExp_Explorer.hxx>
33 #include <TopTools_MapOfShape.hxx>
36 IMPLEMENT_STANDARD_RTTIEXT(BRepBuilderAPI_FastSewing,Standard_Transient)
38 //=======================================================================
39 //function : IntersetctionOfSets
40 //purpose : Returns minimal value of intersection result
41 //=======================================================================
42 static Standard_Integer
43 IntersectionOfSets( const NCollection_List<Standard_Integer>& theSet1,
44 const NCollection_List<Standard_Integer>& theSet2)
46 const Standard_Integer anIntMax = IntegerLast();
47 Standard_Integer aRetVal = anIntMax;
48 for(NCollection_List<Standard_Integer>::Iterator
49 anIt1 = theSet1.begin().Iterator();
50 anIt1.More(); anIt1.Next())
52 const Standard_Integer aVal1 = anIt1.Value();
53 for(NCollection_List<Standard_Integer>::Iterator
54 anIt2 = theSet2.begin().Iterator();
55 anIt2.More(); anIt2.Next())
57 const Standard_Integer aVal2 = anIt2.Value();
60 //theIntersectionResult.Append(aVal1);
67 if(aRetVal == anIntMax)
73 //=======================================================================
74 //function : Get2DCurve
76 //=======================================================================
77 static Handle(Geom2d_Curve)
78 Get2DCurve( const Standard_Integer theIndex,
79 const Standard_Real theUfirst,
80 const Standard_Real theUlast,
81 const Standard_Real theVfirst,
82 const Standard_Real theVlast,
83 const Standard_Boolean theIsReverse = Standard_False)
85 if((theIndex < 0) || (theIndex > 3))
86 throw Standard_OutOfRange("BRepBuilderAPI_FastSewing.cxx, Get2DCurve(): OUT of Range");
88 Handle(Geom2d_Curve) a2dCurv;
96 new Geom2d_TrimmedCurve(new Geom2d_Line(
97 gp_Pnt2d(0.0, theVfirst), gp_Dir2d(1.0,0.0)),
102 new Geom2d_TrimmedCurve(new Geom2d_Line(
103 gp_Pnt2d(theUlast, 0.0), gp_Dir2d(0.0,1.0)),
104 theVfirst, theVlast);
108 new Geom2d_TrimmedCurve(new Geom2d_Line(
109 gp_Pnt2d(0.0, theVlast), gp_Dir2d(1.0,0.0)),
110 theUfirst, theUlast);
114 new Geom2d_TrimmedCurve(new Geom2d_Line(
115 gp_Pnt2d(theUfirst, 0.0), gp_Dir2d(0.0,1.0)),
116 theVfirst, theVlast);
128 new Geom2d_TrimmedCurve(new Geom2d_Line(
129 gp_Pnt2d(theUfirst+theUlast, theVfirst),
131 theUfirst, theUlast);
135 new Geom2d_TrimmedCurve(new Geom2d_Line(
136 gp_Pnt2d(theUlast, theVfirst+theVlast),
138 theVfirst, theVlast);
142 new Geom2d_TrimmedCurve(new Geom2d_Line(
143 gp_Pnt2d(theUfirst+theUlast, theVlast),
145 theUfirst, theUlast);
149 new Geom2d_TrimmedCurve(new Geom2d_Line(
150 gp_Pnt2d(theUfirst, theVfirst+theVlast),
152 theVfirst, theVlast);
162 //=======================================================================
163 //function : Constructor
165 //=======================================================================
166 BRepBuilderAPI_FastSewing::
167 BRepBuilderAPI_FastSewing( const Standard_Real theTol):
173 //=======================================================================
176 //=======================================================================
177 Standard_Boolean BRepBuilderAPI_FastSewing::Add(const TopoDS_Shape& theShape)
179 Standard_Boolean aResult = Standard_False;
180 if(theShape.IsNull())
182 SetStatus(FS_EmptyInput);
186 TopTools_MapOfShape aMS;
188 TopExp_Explorer aFExp(theShape,TopAbs_FACE);
189 for (; aFExp.More(); aFExp.Next())
191 const TopoDS_Face& aFace = TopoDS::Face(aFExp.Current());
194 Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace);
197 SetStatus(FS_FaceWithNullSurface);
201 if(aSurf->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface)))
203 SetStatus(FS_NotNaturalBoundsFace);
207 Standard_Real aUf = 0.0, aUl = 0.0, aVf = 0.0, aVl = 0.0;
208 aSurf->Bounds(aUf, aUl, aVf, aVl);
210 if(Precision::IsInfinite(aUf) || Precision::IsInfinite(aUl) ||
211 Precision::IsInfinite(aVf) || Precision::IsInfinite(aVl))
213 SetStatus(FS_InfiniteSurface);
218 aFFace.mySrcFace = aFace;
219 aFFace.myID = myFaceVec.Length();//because start index is 0
220 myFaceVec.Append(aFFace);
221 aResult = Standard_True;
228 //=======================================================================
231 //=======================================================================
232 Standard_Boolean BRepBuilderAPI_FastSewing::Add(const Handle(Geom_Surface)& theSurface)
234 if(theSurface.IsNull())
236 SetStatus(FS_FaceWithNullSurface);
237 return Standard_False;
240 if(theSurface->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface)))
242 SetStatus(FS_NotNaturalBoundsFace);
243 return Standard_False;
246 Standard_Real aUf = 0.0, aUl = 0.0, aVf = 0.0, aVl = 0.0;
247 theSurface->Bounds(aUf, aUl, aVf, aVl);
249 if(Precision::IsInfinite(aUf) || Precision::IsInfinite(aUl) ||
250 Precision::IsInfinite(aVf) || Precision::IsInfinite(aVl))
252 SetStatus(FS_InfiniteSurface);
253 return Standard_False;
258 BRep_Builder aBuilder;
259 aBuilder.MakeFace(aFace.mySrcFace);
260 aBuilder.MakeFace(aFace.mySrcFace, theSurface, myTolerance);
261 aBuilder.NaturalRestriction(aFace.mySrcFace, Standard_True);
263 aFace.myID = myFaceVec.Length();//because start index is 0
264 myFaceVec.Append(aFace);
266 return Standard_True;
270 //=======================================================================
273 //=======================================================================
274 void BRepBuilderAPI_FastSewing::Perform(void)
276 if(myFaceVec.IsEmpty())
278 SetStatus(FS_EmptyInput);
285 // create vertices having unique coordinates
286 Standard_Real aRange = Compute3DRange();
287 Handle(NCollection_IncAllocator) anAlloc = new NCollection_IncAllocator;
288 NCollection_CellFilter<NodeInspector>
289 aCells(Max(myTolerance, aRange/IntegerLast()), anAlloc);
291 for(Standard_Integer i = myFaceVec.Lower(); i <= myFaceVec.Upper(); i++)
293 FindVertexes(i, aCells);
297 for(Standard_Integer i = myFaceVec.Lower(); i <= myFaceVec.Upper(); i++)
302 //Create topological structures
304 for(Standard_Integer i = myVertexVec.Lower(); i <= myVertexVec.Upper(); i++)
306 myVertexVec.ChangeValue(i).CreateTopologicalVertex(myTolerance);
310 for(Standard_Integer i = myEdgeVec.Lower(); i <= myEdgeVec.Upper(); i++)
312 myEdgeVec.ChangeValue(i).CreateTopologicalEdge(myVertexVec, myFaceVec, myTolerance);
316 BRepTools_Quilt aQuilt;
319 for(Standard_Integer i = myFaceVec.Lower(); i <= myFaceVec.Upper(); i++)
321 FS_Face& aFace = myFaceVec.ChangeValue(i);
322 aFace.CreateTopologicalWire(myEdgeVec, myTolerance);
323 aFace.CreateTopologicalFace();
324 aQuilt.Add(aFace.myRetFace);
327 myResShape = aQuilt.Shells();
329 catch(Standard_Failure)
331 SetStatus(FS_Exception);
333 //Standard_Failure::Caught()->Print(cout);
339 //=======================================================================
340 //function : UpdateEdgeInfo
342 //=======================================================================
343 void BRepBuilderAPI_FastSewing::UpdateEdgeInfo( const Standard_Integer theIDPrevVertex,
344 const Standard_Integer theIDCurrVertex,
345 const Standard_Integer theFaceID,
346 const Standard_Integer theIDCurvOnFace)
348 //Indeed, two vertices combine into one edge only.
349 const Standard_Integer anEdgeID =
350 IntersectionOfSets(myVertexVec.Value(theIDPrevVertex).myEdges,
351 myVertexVec.Value(theIDCurrVertex).myEdges);
353 //For DEBUG mode only
354 Standard_ProgramError_Raise_if(anEdgeID < 0,
355 "BRepBuilderAPI_FastSewing::UpdateEdgeInfo: Update not existing edge.");
357 FS_Edge& anEdge = myEdgeVec.ChangeValue(anEdgeID);
358 anEdge.myFaces.Append(theFaceID);
359 FS_Face& aFace = myFaceVec.ChangeValue(theFaceID);
360 aFace.SetEdge(theIDCurvOnFace, anEdge.myID);
363 //=======================================================================
364 //function : CreateNewEdge
365 //purpose : Creates FS_Edge
366 //=======================================================================
367 void BRepBuilderAPI_FastSewing::CreateNewEdge(const Standard_Integer theIDPrevVertex,
368 const Standard_Integer theIDCurrVertex,
369 const Standard_Integer theFaceID,
370 const Standard_Integer theIDCurvOnFace)
372 FS_Edge anEdge(theIDPrevVertex, theIDCurrVertex);
373 anEdge.myID = myEdgeVec.Length(); //because start index is 0
376 anEdge.myFaces.Append(theFaceID);
377 FS_Face& aFace = myFaceVec.ChangeValue(theFaceID);
378 aFace.SetEdge(theIDCurvOnFace, anEdge.myID);
380 myVertexVec.ChangeValue(theIDPrevVertex).myEdges.Append(anEdge.myID);
382 if(theIDPrevVertex == theIDCurrVertex)
383 {//the Edge is degenerated
384 SetStatus(FS_Degenerated);
388 myVertexVec.ChangeValue(theIDCurrVertex).myEdges.Append(anEdge.myID);
391 myEdgeVec.Append(anEdge);
394 //=======================================================================
395 //function : FindVertexes
397 //=======================================================================
398 void BRepBuilderAPI_FastSewing::
399 FindVertexes(const Standard_Integer theSurfID,
400 NCollection_CellFilter<NodeInspector>& theCells)
402 const Standard_Integer aNbPoints = 4;
403 FS_Face& aFace = myFaceVec.ChangeValue(theSurfID);
404 const Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace.mySrcFace);
405 Standard_Real aUf = 0.0, aUl = 0.0, aVf = 0.0, aVl = 0.0;
406 aSurf->Bounds(aUf, aUl, aVf, aVl);
408 const gp_Pnt aPnts[aNbPoints] = { aSurf->Value(aUf, aVf),
409 aSurf->Value(aUl, aVf),
410 aSurf->Value(aUl, aVl),
411 aSurf->Value(aUf, aVl)};
413 for(Standard_Integer i = 0; i < aNbPoints; i++)
417 NodeInspector anInspector(myVertexVec, aPnts[i], myTolerance);
420 aBox.Enlarge(myTolerance);
422 theCells.Inspect(aBox.CornerMin().XYZ(), aBox.CornerMax().XYZ(), anInspector);
423 NodeInspector::Target aResID = anInspector.GetResult();
427 aVert.myID = myVertexVec.Length(); //because start index is 0
428 aVert.myPnt = aPnts[i];
429 aVert.myFaces.Append(theSurfID);
430 myVertexVec.Append(aVert);
431 aFace.SetVertex(i, aVert.myID);
433 theCells.Add(aVert.myID, aBox.CornerMin().XYZ(), aBox.CornerMax().XYZ());
436 {//Change existing vertex
437 aFace.SetVertex(i, aResID);
438 myVertexVec.ChangeValue(aResID).myFaces.Append(theSurfID);
443 //=======================================================================
444 //function : FindEdges
446 //=======================================================================
447 void BRepBuilderAPI_FastSewing::FindEdges(const Standard_Integer theSurfID)
449 const Standard_Integer aNbPoints = 4;
450 FS_Face& aFace = myFaceVec.ChangeValue(theSurfID);
452 const Standard_Integer aFirstInd[aNbPoints] = {0, 1, 3, 0};
453 const Standard_Integer aLastInd[aNbPoints] = {1, 2, 2, 3};
455 for(Standard_Integer i = 0; i < aNbPoints; i++)
457 const Standard_Integer aFirstVertIndex = aFirstInd[i],
458 aLastVertIndex = aLastInd[i];
459 const Standard_Integer aFirstVertID = aFace.myVertices[aFirstVertIndex],
460 aLastVertID = aFace.myVertices[aLastVertIndex];
462 if(aFirstVertID == aLastVertID)
463 {//Edge is degenerated.
464 CreateNewEdge(aFirstVertID, aLastVertID, theSurfID, i);
468 //Must be minimal element from list
469 const Standard_Integer anIntRes =
470 IntersectionOfSets(myVertexVec.Value(aFirstVertID).myFaces,
471 myVertexVec.Value(aLastVertID).myFaces);
473 if((anIntRes < 0) || (anIntRes >= theSurfID))
475 CreateNewEdge(aFirstVertID, aLastVertID, theSurfID, i);
478 {//if(theSurfID > anIntRes) => The edge has been processed earlier
479 UpdateEdgeInfo(aFirstVertID, aLastVertID, theSurfID, i);
484 //=======================================================================
485 //function : GetStatuses
487 //=======================================================================
488 BRepBuilderAPI_FastSewing::FS_VARStatuses
489 BRepBuilderAPI_FastSewing::GetStatuses(Standard_OStream* const theOS)
496 *theOS << "Fast Sewing OK!\n";
501 const Standard_Integer aNumMax = 8*sizeof(myStatusList);
502 FS_Statuses anIDS = static_cast<FS_Statuses>(0x0001);
503 for(Standard_Integer i = 1; i <= aNumMax; i++,
504 anIDS = static_cast<FS_Statuses>(anIDS << 1))
506 if((anIDS & myStatusList) == 0)
512 *theOS << "Degenerated case. Try to reduce tolerance.\n";
514 case FS_FindVertexError:
515 *theOS << "Error while creating list of vertices.\n";
517 case FS_FindEdgeError:
518 *theOS << "Error while creating list of edges.\n";
521 *theOS << "Exception during the operation.\n";
523 case FS_FaceWithNullSurface:
524 *theOS << "Source face has null surface.\n";
526 case FS_NotNaturalBoundsFace:
527 *theOS << "Source face has trimmed surface.\n";
529 case FS_InfiniteSurface:
530 *theOS << "Source face has the surface with infinite boundaries.\n";
533 *theOS << "Empty source data.\n";
545 //=======================================================================
546 //function : Compute3DRange
548 //=======================================================================
549 Standard_Real BRepBuilderAPI_FastSewing::Compute3DRange()
553 for(Standard_Integer i = myFaceVec.Lower(); i <= myFaceVec.Upper(); i++)
555 FS_Face& aFace = myFaceVec.ChangeValue(i);
556 const Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace.mySrcFace);
559 Standard_Real aUf = 0.0, aUl = 0.0, aVf = 0.0, aVl = 0.0;
560 aSurf->Bounds(aUf, aUl, aVf, aVl);
562 aBox.Add(aSurf->Value(aUf, aVf));
563 aBox.Add(aSurf->Value(aUl, aVf));
564 aBox.Add(aSurf->Value(aUl, aVl));
565 aBox.Add(aSurf->Value(aUf, aVl));
568 Standard_Real aXm = 0.0, aYm = 0.0, aZm = 0.0, aXM = 0.0, aYM = 0.0, aZM = 0.0;
569 aBox.Get(aXm, aYm, aZm, aXM, aYM, aZM);
570 Standard_Real aDelta = aXM - aXm;
571 aDelta = Max(aDelta, aYM - aYm);
572 aDelta = Max(aDelta, aZM - aZm);
577 //=======================================================================
578 //function : NodeInspector constructor
580 //=======================================================================
581 BRepBuilderAPI_FastSewing::NodeInspector::
582 NodeInspector(const NCollection_Vector<FS_Vertex>& theVec,
583 const gp_Pnt& thePnt,
584 const Standard_Real theTol):
585 myVecOfVertexes(theVec), myPoint(thePnt), myResID(-1)
587 mySQToler = theTol*theTol;
590 //=======================================================================
591 //function : ::NodeInspector::Inspect
593 //=======================================================================
594 NCollection_CellFilter_Action BRepBuilderAPI_FastSewing::
595 NodeInspector::Inspect(const Target theID)
597 const gp_Pnt& aPt = myVecOfVertexes.Value(theID).myPnt;
598 const Standard_Real aSQDist = aPt.SquareDistance(myPoint);
599 if(aSQDist < mySQToler)
605 return CellFilter_Keep;
608 //=======================================================================
609 //function : ::FS_Edge::CreateTopologicalEdge
611 //=======================================================================
612 void BRepBuilderAPI_FastSewing::FS_Edge::
613 CreateTopologicalEdge(const NCollection_Vector<FS_Vertex>& theVertexVec,
614 const NCollection_Vector<FS_Face>& theFaceVec,
615 const Standard_Real theTol)
617 BRep_Builder aBuilder;
619 TopoDS_Vertex aV1 = theVertexVec(myVertices[0]).myTopoVert;
620 TopoDS_Vertex aV2 = theVertexVec(myVertices[1]).myTopoVert;
622 aV1.Orientation(TopAbs_FORWARD);
623 aV2.Orientation(TopAbs_REVERSED);
625 Handle(Geom_Curve) a3dCurv;
626 TopLoc_Location aLocation;
628 const FS_Face& aFace = theFaceVec.Value(myFaces.Value(myFaces.Lower()));
630 //3D-curves in 1st and 2nd faces are considered to be in same-range
631 const Handle(Geom_Surface)& aSurf = BRep_Tool::Surface(aFace.mySrcFace, aLocation);
633 Standard_Real aUf = 0.0, aUl = 0.0, aVf = 0.0, aVl = 0.0;
634 aSurf->Bounds(aUf, aUl, aVf, aVl);
636 Standard_Integer anEdgeID = -1;
637 for(Standard_Integer anInd = 0; anInd < 4; anInd++)
639 if(myID == aFace.myEdges[anInd])
646 //For DEBUG mode only
647 Standard_ProgramError_Raise_if(anEdgeID < 0,
648 "BRepBuilderAPI_FastSewing::FS_Edge::CreateTopologicalEdge: Single edge.");
652 Handle(Geom2d_Curve) a2dCurv = Get2DCurve(anEdgeID, aUf, aUl, aVf, aVl);
653 const Standard_Real aFPar = a2dCurv->FirstParameter(),
654 aLPar = a2dCurv->LastParameter();
656 aBuilder.MakeEdge(myTopoEdge);
657 aBuilder.UpdateEdge(myTopoEdge, a2dCurv, aSurf, aLocation, theTol);
658 aBuilder.Add(myTopoEdge, aV1);
659 aBuilder.Add(myTopoEdge, aV2);
660 aBuilder.Range(myTopoEdge, aFPar, aLPar);
661 aBuilder.Degenerated(myTopoEdge, Standard_True);
668 a3dCurv = aSurf->VIso(aVf);
671 a3dCurv = aSurf->UIso(aUl);
674 a3dCurv = aSurf->VIso(aVl);
677 a3dCurv = aSurf->UIso(aUf);
680 throw Standard_OutOfRange("FS_Edge::CreateTopologicalEdge()");
684 aBuilder.MakeEdge(myTopoEdge, a3dCurv, theTol);
685 aBuilder.Add(myTopoEdge, aV1);
686 aBuilder.Add(myTopoEdge, aV2);
687 aBuilder.Range(myTopoEdge, a3dCurv->FirstParameter(), a3dCurv->LastParameter());
690 //=======================================================================
691 //function : ::FS_Face::CreateTopologicalWire
693 //=======================================================================
694 void BRepBuilderAPI_FastSewing::FS_Face::
695 CreateTopologicalWire(const NCollection_Vector<FS_Edge>& theEdgeVec,
696 const Standard_Real theToler)
698 TopLoc_Location aLocation;
699 //3D-curves in 1st and 2nd faces are considered to be in same-range
700 const Handle(Geom_Surface)& aSurf = BRep_Tool::Surface(mySrcFace, aLocation);
701 Standard_Real aUf = 0.0, aUl = 0.0, aVf = 0.0, aVl = 0.0;
702 aSurf->Bounds(aUf, aUl, aVf, aVl);
706 for(Standard_Integer anEdge = 0; anEdge < 4; anEdge++)
708 Standard_ProgramError_Raise_if(myEdges[anEdge] < 0,
709 "BRepBuilderAPI_FastSewing::FS_Face::CreateTopologicalWire: Wire is not closed.");
711 const BRepBuilderAPI_FastSewing::FS_Edge& aFSEdge = theEdgeVec.Value(myEdges[anEdge]);
712 TopAbs_Orientation anOri = anEdge < 2 ? TopAbs_FORWARD : TopAbs_REVERSED;
713 TopoDS_Edge anTopE = aFSEdge.myTopoEdge;
715 if(aFSEdge.IsDegenerated())
717 anTopE.Orientation(anOri);
718 aB.Add(myWire, anTopE);
722 //Check if 3D and 2D-curve have same-orientation.
723 //If it is not, 2d-curve will be reversed.
725 Standard_Real aFirstPar = 0.0, aLastPar = 0.0;
727 const Handle(Geom_Curve) a3dCurv = BRep_Tool::Curve(anTopE, aFirstPar, aLastPar);
728 Handle(Geom2d_Curve) a2dCurv = Get2DCurve(anEdge, aUf, aUl, aVf, aVl);
729 const gp_Pnt aPref(a3dCurv->Value(aFirstPar));
730 const gp_Pnt2d aP2df(a2dCurv->Value(aFirstPar)), aP2dl(a2dCurv->Value(aLastPar));
731 gp_Pnt aP3df(aSurf->Value(aP2df.X(), aP2df.Y()));
732 gp_Pnt aP3dl(aSurf->Value(aP2dl.X(), aP2dl.Y()));
733 aP3df.Transform(aLocation);
734 aP3dl.Transform(aLocation);
735 const Standard_Real aSqD1 = aP3df.SquareDistance(aPref);
736 const Standard_Real aSqD2 = aP3dl.SquareDistance(aPref);
740 a2dCurv = Get2DCurve(anEdge, aUf, aUl, aVf, aVl, Standard_True);
741 anOri = TopAbs::Reverse(anOri);
744 aB.UpdateEdge(anTopE, a2dCurv, aSurf, aLocation, theToler);
747 anTopE.Orientation(anOri);
749 aB.Add(myWire, anTopE);
752 myWire.Closed(Standard_True);
755 //=======================================================================
756 //function : ::FS_Face::CreateTopologicalFace
758 //=======================================================================
759 void BRepBuilderAPI_FastSewing::FS_Face::CreateTopologicalFace()
761 Standard_ProgramError_Raise_if(myWire.IsNull(),
762 "BRepBuilderAPI_FastSewing::FS_Face::CreateTopologicalFace: Cannot create wire.");
764 BRep_Builder aBuilder;
765 myRetFace = TopoDS::Face(mySrcFace.EmptyCopied());
766 aBuilder.Add(myRetFace, myWire);
767 aBuilder.NaturalRestriction(myRetFace, Standard_True);