0032781: Coding - get rid of unused headers [BRepCheck to ChFiKPart]
[occt.git] / src / BRepOffset / BRepOffset_MakeSimpleOffset.cxx
1 // Created on: 2016-10-13
2 // Created by: Alexander MALYSHEV
3 // Copyright (c) 1995-1999 Matra Datavision
4 // Copyright (c) 1999-2016 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
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
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.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17 // Include self.
18 #include <BRepOffset_MakeSimpleOffset.hxx>
19
20 #include <Adaptor3d_CurveOnSurface.hxx>
21 #include <BRep_Builder.hxx>
22 #include <BRep_Tool.hxx>
23 #include <BRepLib.hxx>
24 #include <BRepLib_MakeEdge.hxx>
25 #include <BRepLib_MakeFace.hxx>
26 #include <BRepTools_Quilt.hxx>
27 #include <BRepAdaptor_Curve2d.hxx>
28 #include <BRepAdaptor_Surface.hxx>
29 #include <BRepOffset_SimpleOffset.hxx>
30 #include <BRepTools_Modifier.hxx>
31 #include <Geom_TrimmedCurve.hxx>
32 #include <Geom2d_Line.hxx>
33 #include <GeomFill_Generator.hxx>
34 #include <Extrema_LocateExtPC.hxx>
35 #include <NCollection_List.hxx>
36 #include <ShapeAnalysis_FreeBounds.hxx>
37 #include <ShapeFix_Edge.hxx>
38 #include <TopExp.hxx>
39 #include <TopExp_Explorer.hxx>
40 #include <TopoDS_Edge.hxx>
41 #include <TopoDS_Face.hxx>
42 #include <TopoDS.hxx>
43 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
44
45
46 //=============================================================================
47 //function : BRepOffset_MakeSimpleOffset
48 //purpose  : Constructor
49 //=============================================================================
50 BRepOffset_MakeSimpleOffset::BRepOffset_MakeSimpleOffset()
51 : myOffsetValue(0.),
52   myTolerance(Precision::Confusion()),
53   myIsBuildSolid(Standard_False),
54   myMaxAngle(0.0),
55   myError(BRepOffsetSimple_OK),
56   myIsDone(Standard_False)
57 {
58   myReShape = new ShapeBuild_ReShape();
59 }
60
61 //=============================================================================
62 //function : BRepOffset_MakeSimpleOffset
63 //purpose  : Constructor
64 //=============================================================================
65 BRepOffset_MakeSimpleOffset::BRepOffset_MakeSimpleOffset(const TopoDS_Shape& theInputShape,
66                                                          const Standard_Real theOffsetValue)
67 : myInputShape(theInputShape),
68   myOffsetValue(theOffsetValue),
69   myTolerance(Precision::Confusion()),
70   myIsBuildSolid(Standard_False),
71   myMaxAngle(0.0),
72   myError(BRepOffsetSimple_OK),
73   myIsDone(Standard_False)
74 {
75   myReShape = new ShapeBuild_ReShape();
76 }
77
78 //=============================================================================
79 //function : Initialize
80 //purpose  :
81 //=============================================================================
82 void BRepOffset_MakeSimpleOffset::Initialize(const TopoDS_Shape& theInputShape,
83                                              const Standard_Real theOffsetValue)
84 {
85   myInputShape = theInputShape;
86   myOffsetValue = theOffsetValue;
87   Clear();
88 }
89
90 //=============================================================================
91 //function : GetErrorMessage
92 //purpose  :
93 //=============================================================================
94 TCollection_AsciiString BRepOffset_MakeSimpleOffset::GetErrorMessage() const
95 {
96   TCollection_AsciiString anError = "";
97
98   if (myError == BRepOffsetSimple_NullInputShape)
99   {
100     anError = "Null input shape";
101     return anError;
102   }
103   else if (myError == BRepOffsetSimple_ErrorOffsetComputation)
104   {
105     anError = "Error during offset construction";
106     return anError;
107   }
108   else if (myError == BRepOffsetSimple_ErrorWallFaceComputation)
109   {
110     anError = "Error during building wall face";
111     return anError;
112   }
113   else if (myError == BRepOffsetSimple_ErrorInvalidNbShells)
114   {
115     anError = "Result contains two or more shells";
116     return anError;
117   }
118   else if (myError == BRepOffsetSimple_ErrorNonClosedShell)
119   {
120     anError = "Result shell is not closed";
121     return anError;
122   }
123
124   return anError;
125 }
126
127 //=============================================================================
128 //function : Clear
129 //purpose  : 
130 //=============================================================================
131 void BRepOffset_MakeSimpleOffset::Clear()
132 {
133   myIsDone = Standard_False;
134   myError = BRepOffsetSimple_OK;
135   myMaxAngle = 0.0;
136   myMapVE.Clear();
137   myReShape->Clear(); // Clear possible stored modifications.
138 }
139
140 //=============================================================================
141 //function : GetSafeOffset
142 //purpose  : 
143 //=============================================================================
144 Standard_Real BRepOffset_MakeSimpleOffset::GetSafeOffset(const Standard_Real theExpectedToler)
145 {
146   if (myInputShape.IsNull())
147     return 0.0; // Input shape is null.
148
149   // Compute max angle in faces junctions.
150   if (myMaxAngle == 0.0) // Non-initialized.
151     ComputeMaxAngle();
152
153   Standard_Real aMaxTol = 0.0;
154   aMaxTol = BRep_Tool::MaxTolerance(myInputShape, TopAbs_VERTEX);
155
156   const Standard_Real anExpOffset = Max((theExpectedToler - aMaxTol) / (2.0 * myMaxAngle),
157                                         0.0); // Minimal distance can't be lower than 0.0.
158   return anExpOffset;
159 }
160
161 //=============================================================================
162 //function : Perform
163 //purpose  : 
164 //=============================================================================
165 void BRepOffset_MakeSimpleOffset::Perform()
166 {
167   // Clear result of previous computations.
168   Clear();
169
170   // Check shape existence.
171   if (myInputShape.IsNull())
172   {
173     myError = BRepOffsetSimple_NullInputShape;
174     return;
175   }
176
177   if (myMaxAngle == 0.0) // Non-initialized.
178     ComputeMaxAngle();
179
180   myBuilder.Init(myInputShape);
181   Handle(BRepOffset_SimpleOffset) aMapper = new BRepOffset_SimpleOffset(myInputShape, myOffsetValue, myTolerance);
182   myBuilder.Perform(aMapper);
183
184   if (!myBuilder.IsDone())
185   {
186     myError = BRepOffsetSimple_ErrorOffsetComputation;
187     return;
188   }
189
190   myResShape = myBuilder.ModifiedShape(myInputShape);
191
192   // Fix degeneracy. Degenerated edge should be mapped to the degenerated.
193   BRep_Builder aBB;
194   TopExp_Explorer anExpSE(myInputShape, TopAbs_EDGE);
195   for(; anExpSE.More(); anExpSE.Next())
196   {
197     const TopoDS_Edge & aCurrEdge = TopoDS::Edge(anExpSE.Current());
198
199     if (!BRep_Tool::Degenerated(aCurrEdge))
200       continue;
201
202     const TopoDS_Edge & anEdge = TopoDS::Edge(myBuilder.ModifiedShape(aCurrEdge));
203     aBB.Degenerated(anEdge, Standard_True);
204   }
205
206   // Restore walls for solid.
207   if (myIsBuildSolid && !BuildMissingWalls())
208     return;
209
210   myIsDone = Standard_True;
211 }
212
213 //=============================================================================
214 //function : tgtfaces
215 //purpose  : check the angle at the border between two squares.
216 //           Two shares should have a shared front edge.
217 //=============================================================================
218 static void tgtfaces(const TopoDS_Edge& Ed,
219                      const TopoDS_Face& F1,
220                      const TopoDS_Face& F2,
221                      const Standard_Boolean couture,
222                      Standard_Real& theResAngle)
223 {
224  // Check that pcurves exist on both faces of edge.
225   Standard_Real aFirst,aLast;
226   Handle(Geom2d_Curve) aCurve;
227   aCurve = BRep_Tool::CurveOnSurface(Ed,F1,aFirst,aLast);
228   if(aCurve.IsNull())
229     return;
230   aCurve = BRep_Tool::CurveOnSurface(Ed,F2,aFirst,aLast);
231   if(aCurve.IsNull())
232     return;
233
234   Standard_Real u;
235   TopoDS_Edge E = Ed;
236   BRepAdaptor_Surface aBAS1(F1,Standard_False);
237   BRepAdaptor_Surface aBAS2(F2,Standard_False);
238
239   Handle(BRepAdaptor_Surface) HS1 = new BRepAdaptor_Surface (aBAS1);
240   Handle(BRepAdaptor_Surface) HS2;
241   if(couture) HS2 = HS1;
242   else HS2 = new BRepAdaptor_Surface(aBAS2);
243   //case when edge lies on the one face
244   
245   E.Orientation(TopAbs_FORWARD);
246   BRepAdaptor_Curve2d C2d1(E, F1);
247   if(couture) E.Orientation(TopAbs_REVERSED);
248   BRepAdaptor_Curve2d C2d2(E,F2);
249
250   Standard_Boolean rev1 = (F1.Orientation() == TopAbs_REVERSED);
251   Standard_Boolean rev2 = (F2.Orientation() == TopAbs_REVERSED);
252   Standard_Real f,l,eps;
253   BRep_Tool::Range(E,f,l);
254   Extrema_LocateExtPC ext;
255
256   eps = (l - f) / 100.0;
257   f += eps; // to avoid calculations on  
258   l -= eps; // points of pointed squares.
259   gp_Pnt2d p;
260   gp_Pnt pp1,pp2;//,PP;
261   gp_Vec du1, dv1;
262   gp_Vec du2, dv2;
263   gp_Vec d1,d2;
264   Standard_Real norm;
265
266   const Standard_Integer NBPNT = 23;
267   for(Standard_Integer i = 0; i <= NBPNT; i++)
268   {
269     // First suppose that this is sameParameter
270     u = f + (l - f) * i / NBPNT;
271
272     // take derivatives of surfaces at the same u, and compute normals
273     C2d1.D0(u,p);
274     HS1->D1 (p.X(), p.Y(), pp1, du1, dv1);
275     d1 = (du1.Crossed(dv1));
276     norm = d1.Magnitude(); 
277     if (norm > 1.e-12) d1 /= norm;
278     else continue; // skip degenerated point
279     if(rev1) d1.Reverse();
280
281     C2d2.D0(u,p);
282     HS2->D1 (p.X(), p.Y(), pp2, du2, dv2);
283     d2 = (du2.Crossed(dv2));
284     norm = d2.Magnitude();
285     if (norm > 1.e-12) d2 /= norm;
286     else continue; // skip degenerated point
287     if(rev2) d2.Reverse();
288
289     // Compute angle.
290     Standard_Real aCurrentAng = d1.Angle(d2);
291
292     theResAngle = Max(theResAngle, aCurrentAng);
293   }
294 }
295
296 //=============================================================================
297 // function : ComputeMaxAngleOnShape
298 // purpose  : Code the regularities on all edges of the shape, boundary of 
299 //            two faces that do not have it.
300 //=============================================================================
301 static void ComputeMaxAngleOnShape(const TopoDS_Shape& S,
302                                    Standard_Real& theResAngle)
303 {
304   TopTools_IndexedDataMapOfShapeListOfShape M;
305   TopExp::MapShapesAndAncestors(S,TopAbs_EDGE,TopAbs_FACE,M);
306   TopTools_ListIteratorOfListOfShape It;
307   TopExp_Explorer Ex;
308   TopoDS_Face F1,F2;
309   Standard_Boolean found, couture;
310   for(Standard_Integer i = 1; i <= M.Extent(); i++)
311   {
312     TopoDS_Edge E = TopoDS::Edge(M.FindKey(i));
313     found = Standard_False; couture = Standard_False;
314     F1.Nullify();
315     for(It.Initialize(M.FindFromIndex(i));It.More() && !found;It.Next())
316     {
317       if(F1.IsNull()) { F1 = TopoDS::Face(It.Value()); }
318       else
319       {
320         if(!F1.IsSame(TopoDS::Face(It.Value())))
321         {
322           found = Standard_True;
323           F2 = TopoDS::Face(It.Value());
324         }
325       }
326     }
327     if (!found && !F1.IsNull()){//is it a sewing edge?
328       TopAbs_Orientation orE = E.Orientation();
329       TopoDS_Edge curE;
330       for(Ex.Init(F1,TopAbs_EDGE);Ex.More() && !found;Ex.Next()){
331         curE= TopoDS::Edge(Ex.Current());
332         if(E.IsSame(curE) && orE != curE.Orientation()) 
333         {
334           found = Standard_True;
335           couture = Standard_True;
336           F2 = F1;
337         }
338       }
339     }
340     if(found)
341     {
342       if(BRep_Tool::Continuity(E,F1,F2)<=GeomAbs_C0)
343       {
344         try
345         {
346           tgtfaces(E, F1, F2, couture, theResAngle);
347         }
348         catch(Standard_Failure const&)
349         {
350         }
351       }
352     }
353   }
354 }
355
356 //=============================================================================
357 //function : ComputeMaxAngle
358 //purpose  : Computes max angle in faces junction
359 //=============================================================================
360 void BRepOffset_MakeSimpleOffset::ComputeMaxAngle()
361 {
362   ComputeMaxAngleOnShape(myInputShape, myMaxAngle);
363 }
364
365 //=============================================================================
366 //function : BuildMissingWalls
367 //purpose  : Builds walls to the result solid.
368 //=============================================================================
369 Standard_Boolean BRepOffset_MakeSimpleOffset::BuildMissingWalls()
370 {
371   // Internal list of new faces.
372   TopoDS_Compound aNewFaces;
373   BRep_Builder aBB;
374   aBB.MakeCompound(aNewFaces);
375
376   // Compute outer bounds of original shape.
377   ShapeAnalysis_FreeBounds aFB(myInputShape);
378   const TopoDS_Compound& aFreeWires = aFB.GetClosedWires();
379
380   // Build linear faces on each edge and its image.
381   TopExp_Explorer anExpCW(aFreeWires,TopAbs_WIRE);
382   for(; anExpCW.More() ; anExpCW.Next())
383   {
384     const TopoDS_Wire& aCurWire = TopoDS::Wire(anExpCW.Current());
385
386     // Iterate over outer edges in outer wires.
387     TopExp_Explorer anExpWE(aCurWire, TopAbs_EDGE);
388     for(; anExpWE.More() ; anExpWE.Next())
389     {
390       const TopoDS_Edge& aCurEdge = TopoDS::Edge(anExpWE.Current());
391
392       TopoDS_Face aNewFace = BuildWallFace(aCurEdge);
393
394       if (aNewFace.IsNull())
395       {
396         myError = BRepOffsetSimple_ErrorWallFaceComputation;
397         return Standard_False;
398       }
399
400       aBB.Add(aNewFaces, aNewFace);
401     }
402   }
403
404   // Update edges from wall faces.
405   ShapeFix_Edge aSFE;
406   aSFE.SetContext(myReShape);
407   TopExp_Explorer anExpCE(aNewFaces, TopAbs_EDGE);
408   for ( ; anExpCE.More() ; anExpCE.Next())
409   {
410     // Fix same parameter and same range flags.
411     const TopoDS_Edge& aCurrEdge = TopoDS::Edge(anExpCE.Current());
412     aSFE.FixSameParameter(aCurrEdge);
413   }
414
415   // Update result to be compound.
416   TopoDS_Compound aResCompound;
417   aBB.MakeCompound(aResCompound);
418
419   // Add old faces the result.
420   TopExp_Explorer anExpSF(myInputShape, TopAbs_FACE);
421   for ( ; anExpSF.More() ; anExpSF.Next())
422     aBB.Add(aResCompound, anExpSF.Current());
423
424   // Add new faces the result.
425   anExpSF.Init(myResShape, TopAbs_FACE);
426   for ( ; anExpSF.More() ; anExpSF.Next())
427     aBB.Add(aResCompound, anExpSF.Current());
428
429   // Add wall faces to the result.
430   TopExp_Explorer anExpCF(aNewFaces, TopAbs_FACE);
431   for ( ; anExpCF.More() ; anExpCF.Next())
432   {
433     const TopoDS_Face& aF = TopoDS::Face(anExpCF.Current());
434     aBB.Add(aResCompound, aF);
435   }
436
437   // Apply stored modifications.
438   aResCompound = TopoDS::Compound(myReShape->Apply(aResCompound));
439
440   // Create result shell.
441   BRepTools_Quilt aQuilt;
442   aQuilt.Add(aResCompound);
443   TopoDS_Shape aShells = aQuilt.Shells();
444
445   TopExp_Explorer anExpSSh(aShells, TopAbs_SHELL);
446   TopoDS_Shell aResShell;
447   for ( ; anExpSSh.More() ; anExpSSh.Next() )
448   {
449     if (!aResShell.IsNull())
450     {
451       // Shell is not null -> explorer contains two or more shells.
452       myError = BRepOffsetSimple_ErrorInvalidNbShells;
453       return Standard_False;
454     }
455     aResShell = TopoDS::Shell(anExpSSh.Current());
456   }
457
458   if (!BRep_Tool::IsClosed(aResShell))
459   {
460     myError = BRepOffsetSimple_ErrorNonClosedShell;
461     return Standard_False;
462   }
463
464   // Create result solid.
465   TopoDS_Solid aResSolid;
466   aBB.MakeSolid(aResSolid);
467   aBB.Add(aResSolid, aResShell);
468   myResShape = aResSolid;
469
470   return Standard_True;
471 }
472
473 //=============================================================================
474 //function : BuildWallFace
475 //purpose  :
476 //=============================================================================
477 TopoDS_Face BRepOffset_MakeSimpleOffset::BuildWallFace(const TopoDS_Edge& theOrigEdge)
478 {
479   TopoDS_Face aResFace;
480
481   // Get offset edge. offset edge is revered to create correct wire.
482   TopoDS_Edge aNewEdge = TopoDS::Edge(myBuilder.ModifiedShape(theOrigEdge));
483   aNewEdge.Orientation(TopAbs_REVERSED);
484
485   TopoDS_Vertex aNewV1, aNewV2;
486   TopExp::Vertices(aNewEdge, aNewV1, aNewV2);
487
488   // Wire contour is:
489   // theOrigEdge (forcible forward) -> wall1 -> aNewEdge (forcible reversed) -> wall2
490   // Firstly it is necessary to create copy of original shape with forward direction.
491   // This simplifies walls creation.
492   TopoDS_Edge anOrigCopy = theOrigEdge;
493   anOrigCopy.Orientation(TopAbs_FORWARD);
494   TopoDS_Vertex aV1, aV2;
495   TopExp::Vertices(anOrigCopy, aV1, aV2);
496
497   // To simplify work with map.
498   TopoDS_Vertex aForwardV1 = TopoDS::Vertex(aV1.Oriented(TopAbs_FORWARD));
499   TopoDS_Vertex aForwardV2 = TopoDS::Vertex(aV2.Oriented(TopAbs_FORWARD));
500
501   // Check existence of edges in stored map: Edge1
502   TopoDS_Edge aWall1;
503   if (myMapVE.IsBound(aForwardV2))
504   {
505     // Edge exists - get it from map.
506     aWall1 = myMapVE(aForwardV2);
507   }
508   else
509   {
510     // Edge does not exist - create it and add to the map.
511     BRepLib_MakeEdge aME1(TopoDS::Vertex(aV2.Oriented(TopAbs_FORWARD)), 
512                           TopoDS::Vertex(aNewV2.Oriented(TopAbs_REVERSED)));
513     if (!aME1.IsDone())
514       return aResFace;
515     aWall1 = aME1.Edge();
516
517     myMapVE.Bind(aForwardV2, aWall1);
518   }
519
520   // Check existence of edges in stored map: Edge2
521   TopoDS_Edge aWall2;
522   if (myMapVE.IsBound(aForwardV1))
523   {
524     // Edge exists - get it from map.
525     aWall2 = TopoDS::Edge(myMapVE(aForwardV1).Oriented(TopAbs_REVERSED));
526   }
527   else
528   {
529     // Edge does not exist - create it and add to the map.
530     BRepLib_MakeEdge aME2(TopoDS::Vertex(aV1.Oriented(TopAbs_FORWARD)), 
531                           TopoDS::Vertex(aNewV1.Oriented(TopAbs_REVERSED)));
532     if (!aME2.IsDone())
533       return aResFace;
534     aWall2 = aME2.Edge();
535
536     myMapVE.Bind(aForwardV1, aWall2);
537
538     // Orient it in reversed direction.
539     aWall2.Orientation(TopAbs_REVERSED);
540   }
541
542   BRep_Builder aBB;
543
544   TopoDS_Wire aWire;
545   aBB.MakeWire(aWire);
546   aBB.Add(aWire, anOrigCopy);
547   aBB.Add(aWire, aWall1);
548   aBB.Add(aWire, aNewEdge);
549   aBB.Add(aWire, aWall2);
550
551   // Build 3d curves on wire
552   BRepLib::BuildCurves3d( aWire );
553
554   // Try to build using simple planar approach.
555   TopoDS_Face aF;
556   try
557   {
558     // Call of face maker is wrapped by try/catch since it generates exceptions sometimes.
559     BRepLib_MakeFace aFM(aWire, Standard_True);
560     if (aFM.IsDone())
561       aF = aFM.Face();
562   }
563   catch(Standard_Failure const&)
564   {
565   }
566
567   if (aF.IsNull()) // Exception in face maker or result is not computed.
568   {
569     // Build using thrusections.
570     Standard_Boolean ToReverse = Standard_False;
571     Standard_Real fpar, lpar, fparOE, lparOE;
572     Handle(Geom_Curve) EdgeCurve = BRep_Tool::Curve(theOrigEdge, fpar, lpar);
573     Handle(Geom_TrimmedCurve) TrEdgeCurve = new Geom_TrimmedCurve( EdgeCurve, fpar, lpar );
574     Handle(Geom_Curve) OffsetCurve = BRep_Tool::Curve(aNewEdge, fparOE, lparOE);
575     Handle(Geom_TrimmedCurve) TrOffsetCurve = new Geom_TrimmedCurve( OffsetCurve, fparOE, lparOE );
576
577     GeomFill_Generator ThrusecGenerator;
578     ThrusecGenerator.AddCurve( TrEdgeCurve );
579     ThrusecGenerator.AddCurve( TrOffsetCurve );
580     ThrusecGenerator.Perform( Precision::PConfusion() );
581     Handle(Geom_Surface) theSurf = ThrusecGenerator.Surface();
582     //theSurf = new Geom_SurfaceOfLinearExtrusion( TrOffsetCurve, OffsetDir );
583     Standard_Real Uf, Ul, Vf, Vl;
584     theSurf->Bounds(Uf, Ul, Vf, Vl);
585     TopLoc_Location Loc;
586     Handle(Geom2d_Line) EdgeLine2d, OELine2d, aLine2d, aLine2d2;
587     EdgeLine2d = new Geom2d_Line(gp_Pnt2d(0., Vf), gp_Dir2d(1., 0.));
588     aBB.UpdateEdge(theOrigEdge, EdgeLine2d, theSurf, Loc, Precision::Confusion());
589     OELine2d = new Geom2d_Line(gp_Pnt2d(0., Vl), gp_Dir2d(1., 0.));
590     aBB.UpdateEdge(aNewEdge, OELine2d, theSurf, Loc, Precision::Confusion());
591     Standard_Real UonV1 = (ToReverse)? Ul : Uf;
592     Standard_Real UonV2 = (ToReverse)? Uf : Ul;
593     aLine2d  = new Geom2d_Line(gp_Pnt2d(UonV2, 0.), gp_Dir2d(0., 1.));
594     aLine2d2 = new Geom2d_Line(gp_Pnt2d(UonV1, 0.), gp_Dir2d(0., 1.));
595     if (aWall1.IsSame(aWall2))
596     {
597       aBB.UpdateEdge(aWall1, aLine2d, aLine2d2, theSurf, Loc, Precision::Confusion());
598       Handle(Geom_Curve) BSplC34 = theSurf->UIso( Uf );
599       aBB.UpdateEdge(aWall1, BSplC34, Precision::Confusion());
600       aBB.Range(aWall1, Vf, Vl);
601     }
602     else
603     {
604       aBB.SameParameter(aWall1, Standard_False);
605       aBB.SameRange(aWall1, Standard_False);
606       aBB.SameParameter(aWall2, Standard_False);
607       aBB.SameRange(aWall2, Standard_False);
608       aBB.UpdateEdge(aWall1, aLine2d,  theSurf, Loc, Precision::Confusion());
609       aBB.Range(aWall1, theSurf, Loc, Vf, Vl);
610       aBB.UpdateEdge(aWall2, aLine2d2, theSurf, Loc, Precision::Confusion());
611       aBB.Range(aWall2, theSurf, Loc, Vf, Vl);
612       Handle(Geom_Curve) BSplC3 = theSurf->UIso( UonV2 );
613       aBB.UpdateEdge(aWall1, BSplC3, Precision::Confusion());
614       aBB.Range(aWall1, Vf, Vl, Standard_True); //only for 3d curve
615       Handle(Geom_Curve) BSplC4 = theSurf->UIso( UonV1 );
616       aBB.UpdateEdge(aWall2, BSplC4, Precision::Confusion());
617       aBB.Range(aWall2, Vf, Vl, Standard_True); //only for 3d curve
618     }
619
620     aF = BRepLib_MakeFace(theSurf, aWire);
621
622   }
623
624   return aF;
625 }
626
627 //=============================================================================
628 //function : Generated
629 //purpose  :
630 //=============================================================================
631 const TopoDS_Shape BRepOffset_MakeSimpleOffset::Generated(const TopoDS_Shape& theShape) const
632 {
633   // Shape generated by modification.
634   TopoDS_Shape aRes;
635   aRes = myBuilder.ModifiedShape(theShape);
636
637   if (aRes.IsNull())
638     return aRes;
639
640   // Shape modifications obtained in scope of shape healing.
641   aRes = myReShape->Apply(aRes);
642
643   return aRes;
644 }
645
646 //=============================================================================
647 //function : Modified
648 //purpose  :
649 //=============================================================================
650 const TopoDS_Shape BRepOffset_MakeSimpleOffset::Modified(const TopoDS_Shape& theShape) const
651 {
652   TopoDS_Shape aRes, anEmptyShape;
653
654   // Get modification status and new shape.
655   Standard_Integer aModStatus = myReShape->Status(theShape, aRes);
656
657   if (aModStatus == 0)
658     return anEmptyShape; // No modifications are applied to the shape or its sub-shapes.
659
660   return aRes;
661 }
662