0027954: Create topology-preserving offset computation algorithm
authoraml <aml@opencascade.com>
Thu, 8 Dec 2016 13:30:24 +0000 (16:30 +0300)
committerapn <apn@opencascade.com>
Thu, 8 Dec 2016 13:30:53 +0000 (16:30 +0300)
New topology-preserving offset algorithm has been added. It allows to construct offset shape of build solid.
test cases have been added.
Documentation has been updated to be up to date.

Minor corrections.
Grid is renamed for simplification purposes.
Old constructors are restored with Standard_DEPRECATED macros.

90 files changed:
dox/dev_guides/upgrade/upgrade.md
dox/tutorial/tutorial.md
dox/user_guides/modeling_algos/modeling_algos.md
samples/mfc/standard/02_Modeling/src/ModelingDoc.cpp
samples/qt/Tutorial/src/MakeBottle.cxx
src/BRepOffset/BRepOffset_MakeSimpleOffset.cxx [new file with mode: 0644]
src/BRepOffset/BRepOffset_MakeSimpleOffset.hxx [new file with mode: 0644]
src/BRepOffset/BRepOffset_SimpleOffset.cxx [new file with mode: 0644]
src/BRepOffset/BRepOffset_SimpleOffset.hxx [new file with mode: 0644]
src/BRepOffset/FILES
src/BRepOffsetAPI/BRepOffsetAPI_MakeOffsetShape.cxx
src/BRepOffsetAPI/BRepOffsetAPI_MakeOffsetShape.hxx
src/BRepOffsetAPI/BRepOffsetAPI_MakeThickSolid.cxx
src/BRepOffsetAPI/BRepOffsetAPI_MakeThickSolid.hxx
src/BRepTest/BRepTest_FeatureCommands.cxx
tests/offset/begin
tests/offset/grids.list
tests/offset/simple/A01 [new file with mode: 0644]
tests/offset/simple/A02 [new file with mode: 0644]
tests/offset/simple/A03 [new file with mode: 0644]
tests/offset/simple/A04 [new file with mode: 0644]
tests/offset/simple/A05 [new file with mode: 0644]
tests/offset/simple/A06 [new file with mode: 0644]
tests/offset/simple/A07 [new file with mode: 0644]
tests/offset/simple/A08 [new file with mode: 0644]
tests/offset/simple/A09 [new file with mode: 0644]
tests/offset/simple/A10 [new file with mode: 0644]
tests/offset/simple/A11 [new file with mode: 0644]
tests/offset/simple/A12 [new file with mode: 0644]
tests/offset/simple/A13 [new file with mode: 0644]
tests/offset/simple/A14 [new file with mode: 0644]
tests/offset/simple/B01 [new file with mode: 0644]
tests/offset/simple/B02 [new file with mode: 0644]
tests/offset/simple/B03 [new file with mode: 0644]
tests/offset/simple/B04 [new file with mode: 0644]
tests/offset/simple/B05 [new file with mode: 0644]
tests/offset/simple/B06 [new file with mode: 0644]
tests/offset/simple/B07 [new file with mode: 0644]
tests/offset/simple/B08 [new file with mode: 0644]
tests/offset/simple/B09 [new file with mode: 0644]
tests/offset/simple/B10 [new file with mode: 0644]
tests/offset/simple/B11 [new file with mode: 0644]
tests/offset/simple/B12 [new file with mode: 0644]
tests/offset/simple/B13 [new file with mode: 0644]
tests/offset/simple/B14 [new file with mode: 0644]
tests/offset/simple/B15 [new file with mode: 0644]
tests/offset/simple/C01 [new file with mode: 0644]
tests/offset/simple/C02 [new file with mode: 0644]
tests/offset/simple/C03 [new file with mode: 0644]
tests/offset/simple/C04 [new file with mode: 0644]
tests/offset/simple/C05 [new file with mode: 0644]
tests/offset/simple/C06 [new file with mode: 0644]
tests/offset/simple/C07 [new file with mode: 0644]
tests/offset/simple/C08 [new file with mode: 0644]
tests/offset/simple/C09 [new file with mode: 0644]
tests/offset/simple/C10 [new file with mode: 0644]
tests/offset/simple/C11 [new file with mode: 0644]
tests/offset/simple/C12 [new file with mode: 0644]
tests/offset/simple/C13 [new file with mode: 0644]
tests/offset/simple/C14 [new file with mode: 0644]
tests/offset/simple/C15 [new file with mode: 0644]
tests/offset/simple/D01 [new file with mode: 0644]
tests/offset/simple/D02 [new file with mode: 0644]
tests/offset/simple/D03 [new file with mode: 0644]
tests/offset/simple/D04 [new file with mode: 0644]
tests/offset/simple/D05 [new file with mode: 0644]
tests/offset/simple/D06 [new file with mode: 0644]
tests/offset/simple/D07 [new file with mode: 0644]
tests/offset/simple/E01 [new file with mode: 0644]
tests/offset/simple/E02 [new file with mode: 0644]
tests/offset/simple/E03 [new file with mode: 0644]
tests/offset/simple/E04 [new file with mode: 0644]
tests/offset/simple/E05 [new file with mode: 0644]
tests/offset/simple/E06 [new file with mode: 0644]
tests/offset/simple/E07 [new file with mode: 0644]
tests/offset/simple/E08 [new file with mode: 0644]
tests/offset/simple/E09 [new file with mode: 0644]
tests/offset/simple/E10 [new file with mode: 0644]
tests/offset/simple/E11 [new file with mode: 0644]
tests/offset/simple/E12 [new file with mode: 0644]
tests/offset/simple/E13 [new file with mode: 0644]
tests/offset/simple/E14 [new file with mode: 0644]
tests/offset/simple/E15 [new file with mode: 0644]
tests/offset/simple/E16 [new file with mode: 0644]
tests/offset/simple/E17 [new file with mode: 0644]
tests/offset/simple/E18 [new file with mode: 0644]
tests/offset/simple/E19 [new file with mode: 0644]
tests/offset/simple/E20 [new file with mode: 0644]
tests/offset/simple/begin [new file with mode: 0644]
tests/offset/simple/end [new file with mode: 0644]

index 4447221..bde8a46 100644 (file)
@@ -1103,3 +1103,28 @@ The following classes have been changed:
 *  The last optional argument *RemoveInvalidFaces* has been removed from the constructor of class  *BRepOffset_MakeOffset* and method *Initialize*.
 * The public method *BOPDS_DS::VerticesOnIn* has been renamed into *SubShapesOnIn* and the new output parameter *theCommonPB* has been added.
 
+@section upgrade_occt720 Upgrade to OCCT 7.2.0
+
+@subsection upgrade_occt720_correction_of_Offset_API Corrections in BRepOffset API
+
+Class *BRepOffsetAPI_MakeOffsetShape*:
+* *BRepOffsetAPI_MakeOffsetShape::BRepOffsetAPI_MakeOffsetShape()* - constructor with parameters has been deleted.
+* *BRepOffsetAPI_MakeOffsetShape::PerformByJoin()* - method has been added. This method is old algorithm behaviour. 
+
+The code below shows new calling procedure:
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
+    BRepOffsetAPI_MakeOffsetShape OffsetMaker;
+    OffsetMaker.PerformByJoin(Shape, OffsetValue, Tolerance);
+    NewShape = OffsetMaker.Shape();
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Class *BRepOffsetAPI_MakeThickSolid*:
+* *BRepOffsetAPI_MakeThickSolid::BRepOffsetAPI_MakeThickSolid()* - constructor with parameters has been deleted.
+* *BRepOffsetAPI_MakeThickSolid::MakeThickSolidByJoin()* - method has been added. This method is old algorithm behaviour. 
+
+The code below shows new calling procedure:
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
+    BRepOffsetAPI_MakeThickSolid BodyMaker;
+    BodyMaker.MakeThickSolidByJoin(myBody, facesToRemove, -myThickness / 50, 1.e-3);
+    myBody = BodyMaker.Shape();
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
index d13ec10..1ce1e89 100644 (file)
@@ -484,10 +484,12 @@ The collection for shapes can be found in the *TopTools* package. As *BRepOffset
     facesToRemove.Append(faceToRemove);
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-All the necessary data are now available so you can create your hollowed solid by calling the *BRepOffsetAPI_MakeThickSolid* constructor:
+All the necessary data are now available so you can create your hollowed solid by calling the *BRepOffsetAPI_MakeThickSolid* MakeThickSolidByJoin method:
 
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
-    MyBody = BRepOffsetAPI_MakeThickSolid(myBody, facesToRemove, -myThickness / 50, 1.e-3);
+    BRepOffsetAPI_MakeThickSolid BodyMaker;
+    BodyMaker.MakeThickSolidByJoin(myBody, facesToRemove, -myThickness / 50, 1.e-3);
+    myBody = BodyMaker.Shape();
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 
@@ -812,7 +814,9 @@ Complete definition of MakeBottle function (defined in the file src/MakeBottle.c
 
         TopTools_ListOfShape facesToRemove;
         facesToRemove.Append(faceToRemove);
-        myBody = BRepOffsetAPI_MakeThickSolid(myBody, facesToRemove, -myThickness / 50, 1.e-3);
+        BRepOffsetAPI_MakeThickSolid BodyMaker;
+        BodyMaker.MakeThickSolidByJoin(myBody, facesToRemove, -myThickness / 50, 1.e-3);
+        myBody = BodyMaker.Shape();
         // Threading : Create Surfaces
         Handle(Geom_CylindricalSurface) aCyl1 = new Geom_CylindricalSurface(neckAx2, myNeckRadius * 0.99);
         Handle(Geom_CylindricalSurface) aCyl2 = new Geom_CylindricalSurface(neckAx2, myNeckRadius * 1.05);
index 86104e9..09e5971 100644 (file)
@@ -2100,11 +2100,44 @@ These classes provide the following services:
   * Creation of tapered shapes using draft angles;
   * Creation of sweeps.
   
-@subsection occt_modalg_7_1 Shelling 
+@subsection occt_modalg_7_1 Offset computation
+
+Offset computation can be performed using *BRepOffsetAPI_MakeOffsetShape*. This class provides API to the two different offset algorithms:
+
+Offset algorithm based on computation of the analytical continuation. Meaning of the  parameters can be found in *BRepOffsetAPI_MakeOffsetShape::PerformByJoin* method description. The list below demonstrates principal scheme of this algorithm:
+
+* At the first step, the offsets are computed.
+* After this, the analytical continuations are computed for each offset.
+* Pairwise intersection is computed according to the original topological information (sharing, number of neighbors, etc.).
+* The offset shape is assembled.
+
+The second algorithm is based on the fact that the offset computation for a single face without continuation can always be built. The list below shows simple offset algorithm:
+* Each surface is mapped to its geometric offset surface.
+* For each edge, pcurves are mapped to the same pcurves on offset surfaces.
+* For each edge, 3d curve is constructed by re-approximation of pcurve on the first offset face.
+* Position of each vertex in a result shell is computed as average point of all ends of edges sharing that vertex.
+* Tolerances are updated according to the resulting geometry.
+The possible drawback of the simple algorithm is that it leads, in general case, to tolerance increasing. The tolerances have to grow in order to cover the gaps between the neighbor faces in the output. It should be noted that the actual tolerance growth depends on the offset distance and the quality of joints between the input faces. Anyway the good input shell (smooth connections between adjacent faces) will lead to good result.
+
+The snippets below show usage examples:
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
+    BRepOffsetAPI_MakeOffsetShape OffsetMaker1;
+    // Computes offset shape using analytical continuation mechanism.
+    OffsetMaker1.PerformByJoin(Shape, OffsetValue, Tolerance);
+    if (OffsetMaker1.IsDone())
+      NewShape = OffsetMaker1.Shape();
+    
+    BRepOffsetAPI_MakeOffsetShape OffsetMaker2;
+    // Computes offset shape using simple algorithm.
+    OffsetMaker2.PerformBySimple(Shape, OffsetValue);
+    if (OffsetMaker2.IsDone())
+      NewShape = OffsetMaker2.Shape();
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-Shelling is used to offset given faces of a solid by a specific value. It rounds or intersects adjacent faces along its edges depending on the convexity of the edge. 
+@subsection occt_modalg_7_2 Shelling 
 
-The constructor *BRepOffsetAPI_MakeThickSolid* shelling operator takes the solid, the list of faces to remove and an offset value as input.
+Shelling is used to offset given faces of a solid by a specific value. It rounds or intersects adjacent faces along its edges depending on the convexity of the edge. 
+The MakeThickSolidByJoin method of the *BRepOffsetAPI_MakeThickSolid* takes the solid, the list of faces to remove and an offset value as input.
 
 ~~~~~
 TopoDS_Solid SolidInitial = ...;
@@ -2119,17 +2152,28 @@ for (Standard_Integer i = 1 ;i <= n; i++) {
        LCF.Append(SF);
 }
 
-Result = BRepOffsetAPI_MakeThickSolid  (SolidInitial,
-                                                                               LCF,
-                                                                               Of,
-                                                                               Tol);
+BRepOffsetAPI_MakeThickSolid SolidMaker;
+SolidMaker.MakeThickSolidByJoin(SolidInitial,
+                                LCF,
+                                Of,
+                                Tol);
+if (SolidMaker.IsDone())
+  Result = SolidMaker.Shape();
 ~~~~~
 
 @image html /user_guides/modeling_algos/images/modeling_algos_image042.png     "Shelling"
 @image latex /user_guides/modeling_algos/images/modeling_algos_image042.png    "Shelling"
 
+Also it is possible to create solid between shell, offset shell. This functionality can be called using *BRepOffsetAPI_MakeThickSolid::MakeThickSolidBySimple* method. The code below shows usage example:
+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
+    BRepOffsetAPI_MakeThickSolid SolidMaker;
+    SolidMaker.MakeThickSolidBySimple(Shell, OffsetValue);
+    if (myDone.IsDone())
+      Solid = SolidMaker.Shape();
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-@subsection occt_modalg_7_2  Draft Angle
+@subsection occt_modalg_7_3  Draft Angle
 
 *BRepOffsetAPI_DraftAngle* class allows modifying a shape by applying draft angles to its planar, cylindrical and conical faces. 
 
@@ -2182,7 +2226,7 @@ else {
 @image html /user_guides/modeling_algos/images/modeling_algos_image043.png  "DraftAngle"
 @image latex /user_guides/modeling_algos/images/modeling_algos_image043.png  "DraftAngle"
 
-@subsection occt_modalg_7_3 Pipe  Constructor
+@subsection occt_modalg_7_4 Pipe  Constructor
 
 *BRepOffsetAPI_MakePipe* class allows creating a pipe from a Spine,  which is a Wire and a Profile which is a Shape. This implementation is limited  to spines with smooth transitions, sharp transitions are precessed by  *BRepOffsetAPI_MakePipeShell*. To be more precise the continuity must be G1,  which means that the tangent must have the same direction, though not necessarily the same magnitude, at neighboring edges. 
 
@@ -2197,7 +2241,7 @@ TopoDS_Shape Pipe =  BRepOffsetAPI_MakePipe(Spine,Profile);
 @image html /user_guides/modeling_algos/images/modeling_algos_image044.png "Example of a Pipe"
 @image latex /user_guides/modeling_algos/images/modeling_algos_image044.png "Example of a Pipe"
 
-@subsection occt_modalg_7_4 Evolved Solid
+@subsection occt_modalg_7_5 Evolved Solid
 
 *BRepOffsetAPI_MakeEvolved* class allows creating an evolved solid from a Spine (planar face or wire) and a profile (wire). 
 
index 7db6844..a6529e3 100755 (executable)
@@ -2558,8 +2558,10 @@ void CModelingDoc::OnThickLocal()
        Ex.Next();      //this is the front face
        TopoDS_Shape aFace = Ex.Current();
        aList.Append(aFace);
-               
-       TopoDS_Shape aThickSolid = BRepOffsetAPI_MakeThickSolid(S1,aList,10,0.01);
+       
+    BRepOffsetAPI_MakeThickSolid aSolidMaker;
+    aSolidMaker.MakeThickSolidByJoin(S1,aList,10,0.01);
+       TopoDS_Shape aThickSolid = aSolidMaker.Shape();
 
        Handle(AIS_Shape) ais1 = new AIS_Shape(aThickSolid);
        myAISContext->SetColor(ais1,Quantity_NOC_RED,Standard_False);
@@ -2607,7 +2609,9 @@ void CModelingDoc::OnOffsetLocal()
        Fit();
        Sleep(500);
 
-       TopoDS_Shape anOffsetShape1 = BRepOffsetAPI_MakeOffsetShape(S1,60,0.01);
+    BRepOffsetAPI_MakeOffsetShape aShapeMaker1;
+    aShapeMaker1.PerformByJoin(S1,60,0.01);
+       TopoDS_Shape anOffsetShape1 = aShapeMaker1.Shape();
 
        Handle(AIS_Shape) ais1 = new AIS_Shape(anOffsetShape1);
        myAISContext->SetColor(ais1,Quantity_NOC_MATRABLUE,Standard_False);
@@ -2627,8 +2631,10 @@ void CModelingDoc::OnOffsetLocal()
        Fit();
        Sleep(500);
 
-       TopoDS_Shape anOffsetShape2 = BRepOffsetAPI_MakeOffsetShape(S2,-40,0.01,
-               BRepOffset_Skin,Standard_False,Standard_False,GeomAbs_Arc);
+    BRepOffsetAPI_MakeOffsetShape aShapeMaker2;
+    aShapeMaker2.PerformByJoin(S2,-40,0.01,
+      BRepOffset_Skin,Standard_False,Standard_False,GeomAbs_Arc);
+       TopoDS_Shape anOffsetShape2 = aShapeMaker2.Shape();
 
        Handle(AIS_Shape) ais2 = new AIS_Shape(anOffsetShape2);
        myAISContext->SetColor(ais2,Quantity_NOC_MATRABLUE);
index d965af3..c89b96d 100755 (executable)
@@ -140,7 +140,9 @@ MakeBottle(const Standard_Real myWidth, const Standard_Real myHeight,
 
   TopTools_ListOfShape facesToRemove;
   facesToRemove.Append(faceToRemove);
-  myBody = BRepOffsetAPI_MakeThickSolid(myBody, facesToRemove, -myThickness / 50, 1.e-3);
+  BRepOffsetAPI_MakeThickSolid aSolidMaker;
+  aSolidMaker.MakeThickSolidByJoin(myBody, facesToRemove, -myThickness / 50, 1.e-3);
+  myBody = aSolidMaker.Shape();
   // Threading : Create Surfaces
   Handle(Geom_CylindricalSurface) aCyl1 = new Geom_CylindricalSurface(neckAx2, myNeckRadius * 0.99);
   Handle(Geom_CylindricalSurface) aCyl2 = new Geom_CylindricalSurface(neckAx2, myNeckRadius * 1.05);
diff --git a/src/BRepOffset/BRepOffset_MakeSimpleOffset.cxx b/src/BRepOffset/BRepOffset_MakeSimpleOffset.cxx
new file mode 100644 (file)
index 0000000..3b89a5a
--- /dev/null
@@ -0,0 +1,661 @@
+// Created on: 2016-10-13
+// Created by: Alexander MALYSHEV
+// Copyright (c) 1995-1999 Matra Datavision
+// Copyright (c) 1999-2016 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+// Include self.
+#include <BRepOffset_MakeSimpleOffset.hxx>
+
+#include <Adaptor3d_CurveOnSurface.hxx>
+#include <BRep_Builder.hxx>
+#include <BRep_Tool.hxx>
+#include <BRepLib.hxx>
+#include <BRepLib_MakeEdge.hxx>
+#include <BRepLib_MakeFace.hxx>
+#include <BRepTools_Quilt.hxx>
+#include <BRepAdaptor_HCurve2d.hxx>
+#include <BRepAdaptor_HSurface.hxx>
+#include <BRepAdaptor_Surface.hxx>
+#include <BRepOffset_SimpleOffset.hxx>
+#include <BRepTools_Modifier.hxx>
+#include <Geom_TrimmedCurve.hxx>
+#include <Geom2d_Line.hxx>
+#include <GeomFill_Generator.hxx>
+#include <Extrema_LocateExtPC.hxx>
+#include <NCollection_List.hxx>
+#include <ShapeAnalysis_FreeBounds.hxx>
+#include <ShapeFix_Edge.hxx>
+#include <TopExp.hxx>
+#include <TopExp_Explorer.hxx>
+#include <TopoDS_Edge.hxx>
+#include <TopoDS_Face.hxx>
+#include <TopoDS.hxx>
+#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
+#include <TopTools_ListIteratorOfListOfShape.hxx>
+
+
+//=============================================================================
+//function : BRepOffset_MakeSimpleOffset
+//purpose  : Constructor
+//=============================================================================
+BRepOffset_MakeSimpleOffset::BRepOffset_MakeSimpleOffset()
+: myIsBuildSolid(Standard_False),
+  myMaxAngle(0.0),
+  myError(BRepOffsetSimple_OK),
+  myIsDone(Standard_False)
+{
+  myReShape = new ShapeBuild_ReShape();
+}
+
+//=============================================================================
+//function : BRepOffset_MakeSimpleOffset
+//purpose  : Constructor
+//=============================================================================
+BRepOffset_MakeSimpleOffset::BRepOffset_MakeSimpleOffset(const TopoDS_Shape& theInputShape,
+                                                         const Standard_Real theOffsetValue)
+: myInputShape(theInputShape),
+  myOffsetValue(theOffsetValue),
+  myIsBuildSolid(Standard_False),
+  myMaxAngle(0.0),
+  myError(BRepOffsetSimple_OK),
+  myIsDone(Standard_False)
+{
+  myReShape = new ShapeBuild_ReShape();
+}
+
+//=============================================================================
+//function : Initialize
+//purpose  :
+//=============================================================================
+void BRepOffset_MakeSimpleOffset::Initialize(const TopoDS_Shape& theInputShape,
+                                             const Standard_Real theOffsetValue)
+{
+  myInputShape = theInputShape;
+  myOffsetValue = theOffsetValue;
+  Clear();
+}
+
+//=============================================================================
+//function : GetErrorMessage
+//purpose  :
+//=============================================================================
+TCollection_AsciiString BRepOffset_MakeSimpleOffset::GetErrorMessage() const
+{
+  TCollection_AsciiString anError = "";
+
+  if (myError == BRepOffsetSimple_NullInputShape)
+  {
+    anError = "Null input shape";
+    return anError;
+  }
+  else if (myError == BRepOffsetSimple_ErrorOffsetComputation)
+  {
+    anError = "Error during offset construction";
+    return anError;
+  }
+  else if (myError == BRepOffsetSimple_ErrorWallFaceComputation)
+  {
+    anError = "Error during building wall face";
+    return anError;
+  }
+  else if (myError == BRepOffsetSimple_ErrorInvalidNbShells)
+  {
+    anError = "Result contains two or more shells";
+    return anError;
+  }
+  else if (myError == BRepOffsetSimple_ErrorNonClosedShell)
+  {
+    anError = "Result shell is not closed";
+    return anError;
+  }
+
+  return anError;
+}
+
+//=============================================================================
+//function : Clear
+//purpose  : 
+//=============================================================================
+void BRepOffset_MakeSimpleOffset::Clear()
+{
+  myIsDone = Standard_False;
+  myError = BRepOffsetSimple_OK;
+  myMaxAngle = 0.0;
+  myMapVE.Clear();
+  myReShape->Clear(); // Clear possible stored modifications.
+}
+
+//=============================================================================
+//function : GetSafeOffset
+//purpose  : 
+//=============================================================================
+Standard_Real BRepOffset_MakeSimpleOffset::GetSafeOffset(const Standard_Real theExpectedToler)
+{
+  if (myInputShape.IsNull())
+    return 0.0; // Input shape is null.
+
+  // Compute max angle in faces junctions.
+  if (myMaxAngle == 0.0) // Non-initialized.
+    ComputeMaxAngle();
+
+  Standard_Real aMaxTol = 0.0;
+  aMaxTol = BRep_Tool::MaxTolerance(myInputShape, TopAbs_VERTEX);
+
+  const Standard_Real anExpOffset = Max((theExpectedToler - aMaxTol) / (2.0 * myMaxAngle),
+                                        0.0); // Minimal distance can't be lower than 0.0.
+  return anExpOffset;
+}
+
+//=============================================================================
+//function : Perform
+//purpose  : 
+//=============================================================================
+void BRepOffset_MakeSimpleOffset::Perform()
+{
+  // Clear result of previous computations.
+  Clear();
+
+  // Check shape existence.
+  if (myInputShape.IsNull())
+  {
+    myError = BRepOffsetSimple_NullInputShape;
+    return;
+  }
+
+  if (myMaxAngle == 0.0) // Non-initialized.
+    ComputeMaxAngle();
+
+  myBuilder.Init(myInputShape);
+  Handle(BRepOffset_SimpleOffset) aMapper = new BRepOffset_SimpleOffset(myInputShape, myOffsetValue);
+  myBuilder.Perform(aMapper);
+
+  if (!myBuilder.IsDone())
+  {
+    myError = BRepOffsetSimple_ErrorOffsetComputation;
+    return;
+  }
+
+  myResShape = myBuilder.ModifiedShape(myInputShape);
+
+  // Fix degeneracy. Degenerated edge should be mapped to the degenerated.
+  BRep_Builder aBB;
+  TopExp_Explorer anExpSE(myInputShape, TopAbs_EDGE);
+  for(; anExpSE.More(); anExpSE.Next())
+  {
+    const TopoDS_Edge & aCurrEdge = TopoDS::Edge(anExpSE.Current());
+
+    if (!BRep_Tool::Degenerated(aCurrEdge))
+      continue;
+
+    const TopoDS_Edge & anEdge = TopoDS::Edge(myBuilder.ModifiedShape(aCurrEdge));
+    aBB.Degenerated(anEdge, Standard_True);
+  }
+
+  // Restore walls for solid.
+  if (myIsBuildSolid && !BuildMissingWalls())
+    return;
+
+  myIsDone = Standard_True;
+}
+
+//=============================================================================
+//function : tgtfaces
+//purpose  : check the angle at the border between two squares.
+//           Two shares should have a shared front edge.
+//=============================================================================
+static void tgtfaces(const TopoDS_Edge& Ed,
+                     const TopoDS_Face& F1,
+                     const TopoDS_Face& F2,
+                     const Standard_Boolean couture,
+                     Standard_Real& theResAngle)
+{
+ // Check that pcurves exist on both faces of edge.
+  Standard_Real aFirst,aLast;
+  Handle(Geom2d_Curve) aCurve;
+  aCurve = BRep_Tool::CurveOnSurface(Ed,F1,aFirst,aLast);
+  if(aCurve.IsNull())
+    return;
+  aCurve = BRep_Tool::CurveOnSurface(Ed,F2,aFirst,aLast);
+  if(aCurve.IsNull())
+    return;
+
+  Standard_Real u;
+  TopoDS_Edge E = Ed;
+  BRepAdaptor_Surface aBAS1(F1,Standard_False);
+  BRepAdaptor_Surface aBAS2(F2,Standard_False);
+
+  Handle(BRepAdaptor_HSurface) HS1 = new BRepAdaptor_HSurface (aBAS1);
+  Handle(BRepAdaptor_HSurface) HS2;
+  if(couture) HS2 = HS1;
+  else HS2 = new BRepAdaptor_HSurface(aBAS2);
+  //case when edge lies on the one face
+  
+  E.Orientation(TopAbs_FORWARD);
+  BRepAdaptor_Curve2d C2d1(E, F1);
+  if(couture) E.Orientation(TopAbs_REVERSED);
+  BRepAdaptor_Curve2d C2d2(E,F2);
+
+  Standard_Boolean rev1 = (F1.Orientation() == TopAbs_REVERSED);
+  Standard_Boolean rev2 = (F2.Orientation() == TopAbs_REVERSED);
+  Standard_Real f,l,eps;
+  BRep_Tool::Range(E,f,l);
+  Extrema_LocateExtPC ext;
+
+  eps = (l - f) / 100.0;
+  f += eps; // to avoid calculations on  
+  l -= eps; // points of pointed squares.
+  gp_Pnt2d p;
+  gp_Pnt pp1,pp2;//,PP;
+  gp_Vec du1, dv1;
+  gp_Vec du2, dv2;
+  gp_Vec d1,d2;
+  Standard_Real norm;
+
+  const Standard_Integer NBPNT = 23;
+  for(Standard_Integer i = 0; i <= NBPNT; i++)
+  {
+    // First suppose that this is sameParameter
+    u = f + (l - f) * i / NBPNT;
+
+    // take derivatives of surfaces at the same u, and compute normals
+    C2d1.D0(u,p);
+    HS1->D1 (p.X(), p.Y(), pp1, du1, dv1);
+    d1 = (du1.Crossed(dv1));
+    norm = d1.Magnitude(); 
+    if (norm > 1.e-12) d1 /= norm;
+    else continue; // skip degenerated point
+    if(rev1) d1.Reverse();
+
+    C2d2.D0(u,p);
+    HS2->D1 (p.X(), p.Y(), pp2, du2, dv2);
+    d2 = (du2.Crossed(dv2));
+    norm = d2.Magnitude();
+    if (norm > 1.e-12) d2 /= norm;
+    else continue; // skip degenerated point
+    if(rev2) d2.Reverse();
+
+    // Compute angle.
+    Standard_Real aCurrentAng = d1.Angle(d2);
+
+    theResAngle = Max(theResAngle, aCurrentAng);
+  }
+}
+
+//=============================================================================
+// function : ComputeMaxAngleOnShape
+// purpose  : Code the regularities on all edges of the shape, boundary of 
+//            two faces that do not have it.
+//=============================================================================
+static void ComputeMaxAngleOnShape(const TopoDS_Shape& S,
+                                   Standard_Real& theResAngle)
+{
+  TopTools_IndexedDataMapOfShapeListOfShape M;
+  TopExp::MapShapesAndAncestors(S,TopAbs_EDGE,TopAbs_FACE,M);
+  TopTools_ListIteratorOfListOfShape It;
+  TopExp_Explorer Ex;
+  TopoDS_Face F1,F2;
+  Standard_Boolean found, couture;
+  for(Standard_Integer i = 1; i <= M.Extent(); i++)
+  {
+    TopoDS_Edge E = TopoDS::Edge(M.FindKey(i));
+    found = Standard_False; couture = Standard_False;
+    F1.Nullify();
+    for(It.Initialize(M.FindFromIndex(i));It.More() && !found;It.Next())
+    {
+      if(F1.IsNull()) { F1 = TopoDS::Face(It.Value()); }
+      else
+      {
+        if(!F1.IsSame(TopoDS::Face(It.Value())))
+        {
+          found = Standard_True;
+          F2 = TopoDS::Face(It.Value());
+        }
+      }
+    }
+    if (!found && !F1.IsNull()){//is it a sewing edge?
+      TopAbs_Orientation orE = E.Orientation();
+      TopoDS_Edge curE;
+      for(Ex.Init(F1,TopAbs_EDGE);Ex.More() && !found;Ex.Next()){
+        curE= TopoDS::Edge(Ex.Current());
+        if(E.IsSame(curE) && orE != curE.Orientation()) 
+        {
+          found = Standard_True;
+          couture = Standard_True;
+          F2 = F1;
+        }
+      }
+    }
+    if(found)
+    {
+      if(BRep_Tool::Continuity(E,F1,F2)<=GeomAbs_C0)
+      {
+        try
+        {
+          tgtfaces(E, F1, F2, couture, theResAngle);
+        }
+        catch(Standard_Failure)
+        {
+        }
+      }
+    }
+  }
+}
+
+//=============================================================================
+//function : ComputeMaxAngle
+//purpose  : Computes max angle in faces junction
+//=============================================================================
+void BRepOffset_MakeSimpleOffset::ComputeMaxAngle()
+{
+  ComputeMaxAngleOnShape(myInputShape, myMaxAngle);
+}
+
+//=============================================================================
+//function : BuildMissingWalls
+//purpose  : Builds walls to the result solid.
+//=============================================================================
+Standard_Boolean BRepOffset_MakeSimpleOffset::BuildMissingWalls()
+{
+  // Internal list of new faces.
+  TopoDS_Compound aNewFaces;
+  BRep_Builder aBB;
+  aBB.MakeCompound(aNewFaces);
+
+  // Compute outer bounds of original shape.
+  ShapeAnalysis_FreeBounds aFB(myInputShape);
+  const TopoDS_Compound& aFreeWires = aFB.GetClosedWires();
+
+  // Build linear faces on each edge and its image.
+  TopExp_Explorer anExpCW(aFreeWires,TopAbs_WIRE);
+  for(; anExpCW.More() ; anExpCW.Next())
+  {
+    const TopoDS_Wire& aCurWire = TopoDS::Wire(anExpCW.Current());
+
+    // Iterate over outer edges in outer wires.
+    TopExp_Explorer anExpWE(aCurWire, TopAbs_EDGE);
+    for(; anExpWE.More() ; anExpWE.Next())
+    {
+      const TopoDS_Edge& aCurEdge = TopoDS::Edge(anExpWE.Current());
+
+      TopoDS_Face aNewFace = BuildWallFace(aCurEdge);
+
+      if (aNewFace.IsNull())
+      {
+        myError = BRepOffsetSimple_ErrorWallFaceComputation;
+        return Standard_False;
+      }
+
+      aBB.Add(aNewFaces, aNewFace);
+    }
+  }
+
+  // Update edges from wall faces.
+  ShapeFix_Edge aSFE;
+  aSFE.SetContext(myReShape);
+  TopExp_Explorer anExpCE(aNewFaces, TopAbs_EDGE);
+  for ( ; anExpCE.More() ; anExpCE.Next())
+  {
+    // Fix same parameter and same range flags.
+    const TopoDS_Edge& aCurrEdge = TopoDS::Edge(anExpCE.Current());
+    aSFE.FixSameParameter(aCurrEdge);
+  }
+
+  // Update result to be compound.
+  TopoDS_Compound aResCompound;
+  aBB.MakeCompound(aResCompound);
+
+  // Add old faces the result.
+  TopExp_Explorer anExpSF(myInputShape, TopAbs_FACE);
+  for ( ; anExpSF.More() ; anExpSF.Next())
+    aBB.Add(aResCompound, anExpSF.Current());
+
+  // Add new faces the result.
+  anExpSF.Init(myResShape, TopAbs_FACE);
+  for ( ; anExpSF.More() ; anExpSF.Next())
+    aBB.Add(aResCompound, anExpSF.Current());
+
+  // Add wall faces to the result.
+  TopExp_Explorer anExpCF(aNewFaces, TopAbs_FACE);
+  for ( ; anExpCF.More() ; anExpCF.Next())
+  {
+    const TopoDS_Face& aF = TopoDS::Face(anExpCF.Current());
+    aBB.Add(aResCompound, aF);
+  }
+
+  // Apply stored modifications.
+  aResCompound = TopoDS::Compound(myReShape->Apply(aResCompound));
+
+  // Create result shell.
+  BRepTools_Quilt aQuilt;
+  aQuilt.Add(aResCompound);
+  TopoDS_Shape aShells = aQuilt.Shells();
+
+  TopExp_Explorer anExpSSh(aShells, TopAbs_SHELL);
+  TopoDS_Shell aResShell;
+  for ( ; anExpSSh.More() ; anExpSSh.Next() )
+  {
+    if (!aResShell.IsNull())
+    {
+      // Shell is not null -> explorer contains two or more shells.
+      myError = BRepOffsetSimple_ErrorInvalidNbShells;
+      return Standard_False;
+    }
+    aResShell = TopoDS::Shell(anExpSSh.Current());
+  }
+
+  if (!BRep_Tool::IsClosed(aResShell))
+  {
+    myError = BRepOffsetSimple_ErrorNonClosedShell;
+    return Standard_False;
+  }
+
+  // Create result solid.
+  TopoDS_Solid aResSolid;
+  aBB.MakeSolid(aResSolid);
+  aBB.Add(aResSolid, aResShell);
+  myResShape = aResSolid;
+
+  return Standard_True;
+}
+
+//=============================================================================
+//function : BuildWallFace
+//purpose  :
+//=============================================================================
+TopoDS_Face BRepOffset_MakeSimpleOffset::BuildWallFace(const TopoDS_Edge& theOrigEdge)
+{
+  TopoDS_Face aResFace;
+
+  // Get offset edge. offset edge is revered to create correct wire.
+  TopoDS_Edge aNewEdge = TopoDS::Edge(myBuilder.ModifiedShape(theOrigEdge));
+  aNewEdge.Orientation(TopAbs_REVERSED);
+
+  TopoDS_Vertex aNewV1, aNewV2;
+  TopExp::Vertices(aNewEdge, aNewV1, aNewV2);
+
+  // Wire contour is:
+  // theOrigEdge (forcible forward) -> wall1 -> aNewEdge (forcible reversed) -> wall2
+  // Firstly it is necessary to create copy of original shape with forward direction.
+  // This simplifies walls creation.
+  TopoDS_Edge anOrigCopy = theOrigEdge;
+  anOrigCopy.Orientation(TopAbs_FORWARD);
+  TopoDS_Vertex aV1, aV2;
+  TopExp::Vertices(anOrigCopy, aV1, aV2);
+
+  // To simplify work with map.
+  TopoDS_Vertex aForwardV1 = TopoDS::Vertex(aV1.Oriented(TopAbs_FORWARD));
+  TopoDS_Vertex aForwardV2 = TopoDS::Vertex(aV2.Oriented(TopAbs_FORWARD));
+
+  // Check existence of edges in stored map: Edge1
+  TopoDS_Edge aWall1;
+  if (myMapVE.IsBound(aForwardV2))
+  {
+    // Edge exists - get it from map.
+    aWall1 = myMapVE(aForwardV2);
+  }
+  else
+  {
+    // Edge does not exist - create it and add to the map.
+    BRepLib_MakeEdge aME1(TopoDS::Vertex(aV2.Oriented(TopAbs_FORWARD)), 
+                          TopoDS::Vertex(aNewV2.Oriented(TopAbs_REVERSED)));
+    if (!aME1.IsDone())
+      return aResFace;
+    aWall1 = aME1.Edge();
+
+    myMapVE.Bind(aForwardV2, aWall1);
+  }
+
+  // Check existence of edges in stored map: Edge2
+  TopoDS_Edge aWall2;
+  if (myMapVE.IsBound(aForwardV1))
+  {
+    // Edge exists - get it from map.
+    aWall2 = TopoDS::Edge(myMapVE(aForwardV1).Oriented(TopAbs_REVERSED));
+  }
+  else
+  {
+    // Edge does not exist - create it and add to the map.
+    BRepLib_MakeEdge aME2(TopoDS::Vertex(aV1.Oriented(TopAbs_FORWARD)), 
+                          TopoDS::Vertex(aNewV1.Oriented(TopAbs_REVERSED)));
+    if (!aME2.IsDone())
+      return aResFace;
+    aWall2 = aME2.Edge();
+
+    myMapVE.Bind(aForwardV1, aWall2);
+
+    // Orient it in reversed direction.
+    aWall2.Orientation(TopAbs_REVERSED);
+  }
+
+  BRep_Builder aBB;
+
+  TopoDS_Wire aWire;
+  aBB.MakeWire(aWire);
+  aBB.Add(aWire, anOrigCopy);
+  aBB.Add(aWire, aWall1);
+  aBB.Add(aWire, aNewEdge);
+  aBB.Add(aWire, aWall2);
+
+  // Build 3d curves on wire
+  BRepLib::BuildCurves3d( aWire );
+
+  // Try to build using simple planar approach.
+  TopoDS_Face aF;
+  try
+  {
+    // Call of face maker is wrapped by try/catch since it generates exceptions sometimes.
+    BRepLib_MakeFace aFM(aWire, Standard_True);
+    if (aFM.IsDone())
+      aF = aFM.Face();
+  }
+  catch(Standard_Failure)
+  {
+  }
+
+  if (aF.IsNull()) // Exception in face maker or result is not computed.
+  {
+    // Build using thrusections.
+    Standard_Boolean ToReverse = Standard_False;
+    Standard_Real fpar, lpar, fparOE, lparOE;
+    Handle(Geom_Curve) EdgeCurve = BRep_Tool::Curve(theOrigEdge, fpar, lpar);
+    Handle(Geom_TrimmedCurve) TrEdgeCurve = new Geom_TrimmedCurve( EdgeCurve, fpar, lpar );
+    Handle(Geom_Curve) OffsetCurve = BRep_Tool::Curve(aNewEdge, fparOE, lparOE);
+    Handle(Geom_TrimmedCurve) TrOffsetCurve = new Geom_TrimmedCurve( OffsetCurve, fparOE, lparOE );
+
+    GeomFill_Generator ThrusecGenerator;
+    ThrusecGenerator.AddCurve( TrEdgeCurve );
+    ThrusecGenerator.AddCurve( TrOffsetCurve );
+    ThrusecGenerator.Perform( Precision::PConfusion() );
+    Handle(Geom_Surface) theSurf = ThrusecGenerator.Surface();
+    //theSurf = new Geom_SurfaceOfLinearExtrusion( TrOffsetCurve, OffsetDir );
+    Standard_Real Uf, Ul, Vf, Vl;
+    theSurf->Bounds(Uf, Ul, Vf, Vl);
+    TopLoc_Location Loc;
+    Handle(Geom2d_Line) EdgeLine2d, OELine2d, aLine2d, aLine2d2;
+    EdgeLine2d = new Geom2d_Line(gp_Pnt2d(0., Vf), gp_Dir2d(1., 0.));
+    aBB.UpdateEdge(theOrigEdge, EdgeLine2d, theSurf, Loc, Precision::Confusion());
+    OELine2d = new Geom2d_Line(gp_Pnt2d(0., Vl), gp_Dir2d(1., 0.));
+    aBB.UpdateEdge(aNewEdge, OELine2d, theSurf, Loc, Precision::Confusion());
+    Standard_Real UonV1 = (ToReverse)? Ul : Uf;
+    Standard_Real UonV2 = (ToReverse)? Uf : Ul;
+    aLine2d  = new Geom2d_Line(gp_Pnt2d(UonV2, 0.), gp_Dir2d(0., 1.));
+    aLine2d2 = new Geom2d_Line(gp_Pnt2d(UonV1, 0.), gp_Dir2d(0., 1.));
+    if (aWall1.IsSame(aWall2))
+    {
+      aBB.UpdateEdge(aWall1, aLine2d, aLine2d2, theSurf, Loc, Precision::Confusion());
+      Handle(Geom_Curve) BSplC34 = theSurf->UIso( Uf );
+      aBB.UpdateEdge(aWall1, BSplC34, Precision::Confusion());
+      aBB.Range(aWall1, Vf, Vl);
+    }
+    else
+    {
+      aBB.SameParameter(aWall1, Standard_False);
+      aBB.SameRange(aWall1, Standard_False);
+      aBB.SameParameter(aWall2, Standard_False);
+      aBB.SameRange(aWall2, Standard_False);
+      aBB.UpdateEdge(aWall1, aLine2d,  theSurf, Loc, Precision::Confusion());
+      aBB.Range(aWall1, theSurf, Loc, Vf, Vl);
+      aBB.UpdateEdge(aWall2, aLine2d2, theSurf, Loc, Precision::Confusion());
+      aBB.Range(aWall2, theSurf, Loc, Vf, Vl);
+      Handle(Geom_Curve) BSplC3 = theSurf->UIso( UonV2 );
+      aBB.UpdateEdge(aWall1, BSplC3, Precision::Confusion());
+      aBB.Range(aWall1, Vf, Vl, Standard_True); //only for 3d curve
+      Handle(Geom_Curve) BSplC4 = theSurf->UIso( UonV1 );
+      aBB.UpdateEdge(aWall2, BSplC4, Precision::Confusion());
+      aBB.Range(aWall2, Vf, Vl, Standard_True); //only for 3d curve
+    }
+
+    aF = BRepLib_MakeFace(theSurf, aWire);
+
+  }
+
+  return aF;
+}
+
+//=============================================================================
+//function : Generated
+//purpose  :
+//=============================================================================
+const TopoDS_Shape BRepOffset_MakeSimpleOffset::Generated(const TopoDS_Shape& theShape) const
+{
+  // Shape generated by modification.
+  TopoDS_Shape aRes;
+  aRes = myBuilder.ModifiedShape(theShape);
+
+  if (aRes.IsNull())
+    return aRes;
+
+  // Shape modifications obtained in scope of shape healing.
+  aRes = myReShape->Apply(aRes);
+
+  return aRes;
+}
+
+//=============================================================================
+//function : Modified
+//purpose  :
+//=============================================================================
+const TopoDS_Shape BRepOffset_MakeSimpleOffset::Modified(const TopoDS_Shape& theShape) const
+{
+  TopoDS_Shape aRes, anEmptyShape;
+
+  // Get modification status and new shape.
+  Standard_Integer aModStatus = myReShape->Status(theShape, aRes);
+
+  if (aModStatus == 0)
+    return anEmptyShape; // No modifications are applied to the shape or its sub-shapes.
+
+  return aRes;
+}
+
diff --git a/src/BRepOffset/BRepOffset_MakeSimpleOffset.hxx b/src/BRepOffset/BRepOffset_MakeSimpleOffset.hxx
new file mode 100644 (file)
index 0000000..83d3fc2
--- /dev/null
@@ -0,0 +1,168 @@
+// Created on: 2016-10-13
+// Created by: Alexander MALYSHEV
+// Copyright (c) 1999-2016 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _BRepOffset_MakeSimpleOffset_HeaderFile
+#define _BRepOffset_MakeSimpleOffset_HeaderFile
+
+#include <BRepTools_Modifier.hxx>
+#include <ShapeBuild_ReShape.hxx>
+#include <NCollection_DataMap.hxx>
+#include <Standard_Macro.hxx>
+#include <Standard_Real.hxx>
+#include <TCollection_AsciiString.hxx>
+#include <TopoDS_Edge.hxx>
+#include <TopoDS_Face.hxx>
+#include <TopoDS_Vertex.hxx>
+#include <TopoDS_Shape.hxx>
+
+
+enum BRepOffsetSimple_Status
+{
+  BRepOffsetSimple_OK,
+  BRepOffsetSimple_NullInputShape,
+  BRepOffsetSimple_ErrorOffsetComputation,
+  BRepOffsetSimple_ErrorWallFaceComputation,
+  BRepOffsetSimple_ErrorInvalidNbShells,
+  BRepOffsetSimple_ErrorNonClosedShell
+};
+
+//! This class represents simple offset algorithm itself. It builds simple offset without intersection.
+//! Solid can be created using SetBuildSolidFlag method (set flag to true). By default shell will be constructed.
+//!
+//! Algorithm:
+//! 1. Build source-image maps for vertices, edges and faces.BRepTools_Modification class will be used
+//!    to store this information. An image of a shared edge can be constructed from the corresponding edge
+//!    of the first iterated face.
+//! 2. Run BRepTools_Modifier to obtain offset shape.
+//  3. Ensure topological integrity of the output shape.
+//!
+//! Limitations:
+//! According to the algorithm nature result depends on the smoothness of input data. Smooth (G1-continuity) input shape
+//! will lead to the good result.
+//!
+//! The possible drawback of the simple algorithm is that it leads, in general case, to tolerance increasing.
+//! The tolerances have to grow in order to cover the gaps between the neighbor faces in the output.
+//! It should be noted that the actual tolerance growth depends on the offset distance and the quality of 
+//! joints between the input faces. Anyway the good input shell (smooth connections between adjacent faces)
+//! will lead to good result.
+class BRepOffset_MakeSimpleOffset
+{
+public:
+
+
+  //! Constructor. Does nothing.
+  Standard_EXPORT BRepOffset_MakeSimpleOffset();
+
+  //! Constructor.
+  Standard_EXPORT BRepOffset_MakeSimpleOffset(const TopoDS_Shape& theInputShape,
+                                              const Standard_Real theOffsetValue);
+
+  //! Initialies shape for modifications.
+  Standard_EXPORT void Initialize(const TopoDS_Shape& theInputShape,
+                                  const Standard_Real theOffsetValue);
+
+  //! Computes offset shape.
+  Standard_EXPORT void Perform();
+
+  //! Gets error message.
+  Standard_EXPORT TCollection_AsciiString GetErrorMessage() const;
+
+  //! Gets error code.
+  BRepOffsetSimple_Status GetError() const { return myError; }
+
+  // Inline methods.
+  //! Gets solid building flag.
+  Standard_Boolean GetBuildSolidFlag() const { return myIsBuildSolid; }
+
+  //! Sets solid building flag.
+  void SetBuildSolidFlag(const Standard_Boolean theBuildFlag) { myIsBuildSolid = theBuildFlag; }
+
+  //! Gets offset value.
+  Standard_Real GetOffsetValue() const { return myOffsetValue; }
+
+  //! Sets offset value.
+  void SetOffsetValue(const Standard_Real theOffsetValue) { myOffsetValue = theOffsetValue; }
+
+  //! Gets done state.
+  Standard_Boolean IsDone() const { return myIsDone; } 
+
+  //! Returns result shape.
+  const TopoDS_Shape& GetResultShape() const { return myResShape; }
+
+  //! Computes max safe offset value for the given tolerance.
+  Standard_Real GetSafeOffset(const Standard_Real theExpectedToler);
+
+  //! Returnes result shape for the given one (if exists).
+  Standard_EXPORT const TopoDS_Shape Generated(const TopoDS_Shape& theShape) const;
+
+  //! Returnes modified shape for the given one (if exists).
+  Standard_EXPORT const TopoDS_Shape Modified(const TopoDS_Shape& theShape) const;
+
+protected:
+
+  //! Computes max angle in faces junction.
+  void ComputeMaxAngle();
+
+  //! Clears previous result.
+  void Clear();
+
+private:
+
+  //! Builds face on specified wall.
+  TopoDS_Face BuildWallFace(const TopoDS_Edge& theOrigEdge);
+
+  //! Builds missing walls.
+  Standard_Boolean BuildMissingWalls();
+
+  // Input data.
+
+  //! Input shape.
+  TopoDS_Shape myInputShape;
+
+  //! Offset value.
+  Standard_Real myOffsetValue;
+
+  //! Solid building flag. True means solid construction.
+  Standard_Boolean myIsBuildSolid;
+
+  // Internal data.
+
+  //! Maximal angle in faces junction. This value helps to estimate result tolerance.
+  Standard_Real myMaxAngle;
+
+  //! Error message.
+  BRepOffsetSimple_Status myError;
+
+  //! Done state.
+  Standard_Boolean myIsDone;
+
+  //! Map of vertex - wall edge.
+  //! Used to build shared edge between adjacent wall faces.
+  NCollection_DataMap<TopoDS_Vertex, TopoDS_Edge> myMapVE;
+
+  //! Used for histrory support.
+  BRepTools_Modifier myBuilder;
+
+  //! Used for history support.
+  Handle(ShapeBuild_ReShape) myReShape;
+
+  // Output data.
+
+  //! Result shape.
+  TopoDS_Shape myResShape;
+
+};
+
+#endif // _BRepOffset_MakeSimpleOffset_HeaderFile
diff --git a/src/BRepOffset/BRepOffset_SimpleOffset.cxx b/src/BRepOffset/BRepOffset_SimpleOffset.cxx
new file mode 100644 (file)
index 0000000..a02fccc
--- /dev/null
@@ -0,0 +1,413 @@
+// Created on: 2016-10-14
+// Created by: Alexander MALYSHEV
+// Copyright (c) 1995-1999 Matra Datavision
+// Copyright (c) 1999-2016 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+// Include self.
+#include <BRepOffset_SimpleOffset.hxx>
+
+#include <Adaptor3d_CurveOnSurface.hxx>
+#include <BRepBuilderAPI_MakeEdge.hxx>
+#include <BRepLib.hxx>
+#include <BRep_Tool.hxx>
+#include <Geom_OffsetSurface.hxx>
+#include <GeomAdaptor_Curve.hxx>
+#include <Geom2dAdaptor_HCurve.hxx>
+#include <GeomAdaptor_HSurface.hxx>
+#include <NCollection_Vector.hxx>
+#include <ShapeAnalysis_Edge.hxx>
+#include <TopExp.hxx>
+#include <TopExp_Explorer.hxx>
+#include <TopoDS.hxx>
+#include <TopoDS_Face.hxx>
+#include <TopoDS_Edge.hxx>
+#include <TopoDS_Vertex.hxx>
+
+static const Standard_Integer NCONTROL=22;
+
+
+//=============================================================================
+//function : BRepOffset_SimpleOffset
+//purpose  : Constructor
+//=============================================================================
+BRepOffset_SimpleOffset::BRepOffset_SimpleOffset(const TopoDS_Shape& theInputShape,
+                                                 const Standard_Real theOffsetValue)
+: myOffsetValue(theOffsetValue)
+{
+  FillOffsetData(theInputShape);
+}
+
+//=============================================================================
+//function : NewSurface
+//purpose  :
+//=============================================================================
+Standard_Boolean BRepOffset_SimpleOffset::NewSurface(const TopoDS_Face& F,
+                                                     Handle(Geom_Surface)& S,
+                                                     TopLoc_Location& L,
+                                                     Standard_Real& Tol,
+                                                     Standard_Boolean& RevWires,
+                                                     Standard_Boolean& RevFace)
+{
+  if (!myFaceInfo.IsBound(F))
+    return Standard_False;
+
+  const NewFaceData& aNFD = myFaceInfo.Find(F);
+
+  S = aNFD.myOffsetS;
+  L = aNFD.myL;
+  Tol = aNFD.myTol;
+  RevWires = aNFD.myRevWires;
+  RevFace = aNFD.myRevFace;
+
+  return Standard_True;
+}
+
+//=============================================================================
+//function : NewCurve
+//purpose  :
+//=============================================================================
+Standard_Boolean BRepOffset_SimpleOffset::NewCurve(const TopoDS_Edge& E,
+                                                   Handle(Geom_Curve)& C,
+                                                   TopLoc_Location& L,
+                                                   Standard_Real& Tol)
+{
+  if (!myEdgeInfo.IsBound(E))
+    return Standard_False;
+
+  const NewEdgeData& aNED = myEdgeInfo.Find(E);
+
+  C = aNED.myOffsetC;
+  L = aNED.myL;
+  Tol = aNED.myTol;
+
+  return Standard_True;
+}
+
+//=============================================================================
+//function : NewPoint
+//purpose  :
+//=============================================================================
+Standard_Boolean BRepOffset_SimpleOffset::NewPoint (const TopoDS_Vertex& V,
+                                                    gp_Pnt& P,
+                                                    Standard_Real& Tol)
+{
+  if (!myVertexInfo.IsBound(V))
+    return Standard_False;
+
+  const NewVertexData& aNVD = myVertexInfo.Find(V);
+
+  P = aNVD.myP;
+  Tol = aNVD.myTol;
+
+  return Standard_True;
+}
+
+//=============================================================================
+//function : NewCurve2d
+//purpose  :
+//=============================================================================
+Standard_Boolean BRepOffset_SimpleOffset::NewCurve2d (const TopoDS_Edge& E,
+                                                      const TopoDS_Face& F,
+                                                      const TopoDS_Edge& /*NewE*/,
+                                                      const TopoDS_Face& /*NewF*/,
+                                                      Handle(Geom2d_Curve)& C,
+                                                      Standard_Real& Tol)
+{
+  // Use original pcurve.
+  Standard_Real aF, aL;
+  C = BRep_Tool::CurveOnSurface(E, F, aF, aL);
+  Tol = BRep_Tool::Tolerance(E);
+
+  if (myEdgeInfo.IsBound(E))
+    Tol = myEdgeInfo.Find(E).myTol;
+
+  return Standard_True;
+}
+
+//=============================================================================
+//function : NewParameter
+//purpose  :
+//=============================================================================
+Standard_Boolean BRepOffset_SimpleOffset::NewParameter (const TopoDS_Vertex& V,
+                                                        const TopoDS_Edge& E,
+                                                        Standard_Real& P,
+                                                        Standard_Real& Tol)
+{
+  // Use original parameter.
+  P = BRep_Tool::Parameter(V, E);
+  Tol = BRep_Tool::Tolerance(V);
+
+  if (myVertexInfo.IsBound(V))
+    Tol = myVertexInfo.Find(V).myTol;
+
+  return Standard_True;
+}
+
+//=============================================================================
+//function : NewParameter
+//purpose  :
+//=============================================================================
+GeomAbs_Shape BRepOffset_SimpleOffset::Continuity (const TopoDS_Edge& E,
+                                                   const TopoDS_Face& F1,
+                                                   const TopoDS_Face& F2,
+                                                   const TopoDS_Edge& /*NewE*/,
+                                                   const TopoDS_Face& /*NewF1*/,
+                                                   const TopoDS_Face& /*NewF2*/)
+{
+  // Compute result using original continuity.
+  return BRep_Tool::Continuity(E, F1, F2);
+}
+
+//=============================================================================
+//function : FillOffsetData
+//purpose  : 
+//=============================================================================
+void BRepOffset_SimpleOffset::FillOffsetData(const TopoDS_Shape& theShape)
+{
+  // Clears old data.
+  myFaceInfo.Clear();
+  myEdgeInfo.Clear();
+  myVertexInfo.Clear();
+
+  // Faces loop. Compute offset surface for each face.
+  TopExp_Explorer anExpSF(theShape, TopAbs_FACE);
+  for(; anExpSF.More(); anExpSF.Next())
+  {
+    const TopoDS_Face& aCurrFace = TopoDS::Face(anExpSF.Current());
+    FillFaceData(aCurrFace);
+  }
+
+  // Iterate over edges to compute 3d curve.
+  TopTools_IndexedDataMapOfShapeListOfShape aEdgeFaceMap;
+  TopExp::MapShapesAndAncestors(theShape, TopAbs_EDGE, TopAbs_FACE, aEdgeFaceMap);
+  for (Standard_Integer anIdx = 1; anIdx <= aEdgeFaceMap.Size(); ++anIdx)
+  {
+    const TopoDS_Edge& aCurrEdge = TopoDS::Edge(aEdgeFaceMap.FindKey(anIdx));
+    FillEdgeData(aCurrEdge, aEdgeFaceMap, anIdx);
+  }
+
+  // Iterate over vertices to compute new vertex.
+  TopTools_IndexedDataMapOfShapeListOfShape aVertexEdgeMap;
+  TopExp::MapShapesAndAncestors(theShape, TopAbs_VERTEX, TopAbs_EDGE, aVertexEdgeMap);
+  for (Standard_Integer anIdx = 1; anIdx <= aVertexEdgeMap.Size(); ++anIdx)
+  {
+    const TopoDS_Vertex & aCurrVertex = TopoDS::Vertex(aVertexEdgeMap.FindKey(anIdx));
+    FillVertexData(aCurrVertex, aVertexEdgeMap, anIdx);
+  }
+}
+
+//=============================================================================
+//function : FillFaceData
+//purpose  : 
+//=============================================================================
+void BRepOffset_SimpleOffset::FillFaceData(const TopoDS_Face& theFace)
+{
+  NewFaceData aNFD;
+  aNFD.myRevWires = Standard_False;
+  aNFD.myRevFace = Standard_False;
+  aNFD.myTol = BRep_Tool::Tolerance(theFace);
+
+  // Create offset surface.
+
+  // Any existing transformation is applied to the surface.
+  // New face will have null transformation.
+  Handle(Geom_Surface) aS = BRep_Tool::Surface(theFace);
+
+  // Take into account face orientation.
+  Standard_Real aMult = 1.0;
+  if (theFace.Orientation() == TopAbs_REVERSED)
+    aMult = -1.0;
+
+  aNFD.myOffsetS = new Geom_OffsetSurface(aS, aMult * myOffsetValue, Standard_True);
+  aNFD.myL = TopLoc_Location(); // Null transformation.
+
+  // Save offset surface in map.
+  myFaceInfo.Bind(theFace, aNFD);
+}
+
+//=============================================================================
+//function : FillEdgeData
+//purpose  : 
+//=============================================================================
+void BRepOffset_SimpleOffset::FillEdgeData(const TopoDS_Edge& theEdge,
+                                           const TopTools_IndexedDataMapOfShapeListOfShape& theEdgeFaceMap,
+                                           const Standard_Integer theIdx)
+{
+  const TopTools_ListOfShape& aFacesList = theEdgeFaceMap(theIdx);
+
+  if (aFacesList.Size() == 0)
+    return; // Free edges are skipped.
+
+  // Get offset surface.
+  const TopoDS_Face& aCurrFace = TopoDS::Face(aFacesList.First());
+
+  if (!myFaceInfo.IsBound(aCurrFace))
+    return;
+
+  // No need to deal with transformation - it is applied in fill faces data method.
+  const NewFaceData & aNFD = myFaceInfo.Find(aCurrFace);
+  Handle(Geom_Surface) anOffsetSurf = aNFD.myOffsetS;
+
+  // Compute offset 3d curve.
+  Standard_Real aF, aL;
+  Handle(Geom2d_Curve) aC2d = BRep_Tool::CurveOnSurface(theEdge, aCurrFace, aF, aL);
+
+  BRepBuilderAPI_MakeEdge anEdgeMaker(aC2d, anOffsetSurf, aF, aL);
+  TopoDS_Edge aNewEdge = anEdgeMaker.Edge();
+
+  // Compute max tolerance. Vertex tolerance usage is taken from existing offset computation algorithm.
+  // This piece of code significantly influences resulting performance.
+  Standard_Real aTol = BRep_Tool::MaxTolerance(theEdge, TopAbs_VERTEX);
+  BRepLib::BuildCurves3d(aNewEdge, aTol);
+
+  NewEdgeData aNED;
+  aNED.myOffsetC = BRep_Tool::Curve(aNewEdge, aNED.myL, aF, aL);
+
+  // Iterate over adjacent faces for the current edge and compute max deviation.
+  Standard_Real anEdgeTol = 0.0;
+  TopTools_ListOfShape::Iterator anIter(aFacesList);
+  for ( ; !aNED.myOffsetC.IsNull() && anIter.More() ; anIter.Next())
+  {
+    const TopoDS_Face& aCurFace = TopoDS::Face(anIter.Value());
+
+    if (!myFaceInfo.IsBound(aCurFace))
+      continue;
+
+    // Create offset curve on surface.
+    Standard_Real aF, aL;
+    const Handle(Geom2d_Curve) aC2d = BRep_Tool::CurveOnSurface(theEdge, aCurFace, aF, aL);
+    const Handle(Adaptor2d_HCurve2d) aHCurve2d = new Geom2dAdaptor_HCurve(aC2d, aF, aL);
+    const Handle(Adaptor3d_HSurface) aHSurface = new GeomAdaptor_HSurface(myFaceInfo.Find(aCurFace).myOffsetS);
+    Adaptor3d_CurveOnSurface aCurveOnSurf(aHCurve2d, aHSurface);
+
+    // Extract 3d-curve (it is not null).
+    const GeomAdaptor_Curve aCurve3d(aNED.myOffsetC, aF, aL);
+
+    // It is necessary to compute maximal deviation (tolerance).
+    Standard_Real aMaxTol = 0.0;
+    ShapeAnalysis_Edge::ComputeDeviation(aCurve3d, aCurveOnSurf, Standard_True, aMaxTol, NCONTROL);
+    anEdgeTol = Max (anEdgeTol, aMaxTol);
+  }
+  aNED.myTol = Max(BRep_Tool::Tolerance(aNewEdge), anEdgeTol);
+
+  // Save computed 3d curve in map.
+  myEdgeInfo.Bind(theEdge, aNED);
+}
+
+//=============================================================================
+//function : FillVertexData
+//purpose  : 
+//=============================================================================
+void BRepOffset_SimpleOffset::FillVertexData(const TopoDS_Vertex& theVertex,
+                                             const TopTools_IndexedDataMapOfShapeListOfShape& theVertexEdgeMap,
+                                             const Standard_Integer theIdx)
+{
+  // Algorithm:
+  // Find adjacent edges for the given vertex.
+  // Find corresponding end on the each adjacent edge.
+  // Get offset points for founded end.
+  // Set result vertex position as barycenter of founded points.
+
+  gp_Pnt aCurrPnt = BRep_Tool::Pnt(theVertex);
+
+  const TopTools_ListOfShape& aEdgesList = theVertexEdgeMap(theIdx);
+
+  if (aEdgesList.Size() == 0)
+    return; // Free verices are skipped.
+
+  // Array to store offset points.
+  NCollection_Vector<gp_Pnt> anOffsetPointVec;
+
+  Standard_Real aMaxEdgeTol = 0.0;
+
+  // Iterate over adjacent edges.
+  TopTools_ListOfShape::Iterator anIterEdges(aEdgesList);
+  for (; anIterEdges.More() ; anIterEdges.Next() )
+  {
+    const TopoDS_Edge& aCurrEdge = TopoDS::Edge(anIterEdges.Value());
+
+    if (!myEdgeInfo.IsBound(aCurrEdge))
+      continue; // Skip shared edges with wrong orientation.
+
+    // Find the closest bound.
+    Standard_Real aF, aL;
+    Handle(Geom_Curve) aC3d = BRep_Tool::Curve(aCurrEdge, aF, aL);
+
+    // Protection from degenerated edges.
+    if (aC3d.IsNull())
+      continue;
+
+    const gp_Pnt aPntF = aC3d->Value(aF);
+    const gp_Pnt aPntL = aC3d->Value(aL);
+
+    const Standard_Real aSqDistF = aPntF.SquareDistance(aCurrPnt);
+    const Standard_Real aSqDistL = aPntL.SquareDistance(aCurrPnt);
+
+    Standard_Real aMinParam = aF, aMaxParam = aL;
+    if (aSqDistL < aSqDistF)
+    {
+      // Square distance to last point is closer.
+      aMinParam = aL; aMaxParam = aF;
+    }
+
+    // Compute point on offset edge.
+    const NewEdgeData& aNED = myEdgeInfo.Find(aCurrEdge);
+    const Handle(Geom_Curve) &anOffsetCurve = aNED.myOffsetC;
+    const gp_Pnt anOffsetPoint = anOffsetCurve->Value(aMinParam);
+    anOffsetPointVec.Append(anOffsetPoint);
+
+    // Handle situation when edge is closed.
+    TopoDS_Vertex aV1, aV2;
+    TopExp::Vertices(aCurrEdge, aV1, aV2);
+    if (aV1.IsSame(aV2))
+    {
+      const gp_Pnt anOffsetPoint = anOffsetCurve->Value(aMaxParam);
+      anOffsetPointVec.Append(anOffsetPoint);
+    }
+
+    aMaxEdgeTol = Max(aMaxEdgeTol, aNED.myTol);
+  }
+
+  // NCollection_Vector starts from 0 by default.
+  // It's better to use lower() and upper() in this case instead of direct indexes range.
+  gp_Pnt aCenter(0.0, 0.0, 0.0);
+  for(Standard_Integer i  = anOffsetPointVec.Lower();
+                       i <= anOffsetPointVec.Upper();
+                       ++i)
+  {
+    aCenter.SetXYZ(aCenter.XYZ() + anOffsetPointVec.Value(i).XYZ());
+  }
+  aCenter.SetXYZ(aCenter.XYZ() / anOffsetPointVec.Size());
+
+  // Compute max distance.
+  Standard_Real aSqMaxDist = 0.0;
+  for(Standard_Integer i  = anOffsetPointVec.Lower();
+                       i <= anOffsetPointVec.Upper();
+                       ++i)
+  {
+    const Standard_Real aSqDist = aCenter.SquareDistance(anOffsetPointVec.Value(i));
+    if (aSqDist > aSqMaxDist)
+      aSqMaxDist = aSqDist;
+  }
+
+  const Standard_Real aResTol = Max(aMaxEdgeTol, Sqrt(aSqMaxDist));
+
+  const Standard_Real aMultCoeff = 1.001; // Avoid tolernace problems.
+  NewVertexData aNVD;
+  aNVD.myP = aCenter;
+  aNVD.myTol = aResTol * aMultCoeff;
+
+  // Save computed vertex info.
+  myVertexInfo.Bind(theVertex, aNVD);
+}
diff --git a/src/BRepOffset/BRepOffset_SimpleOffset.hxx b/src/BRepOffset/BRepOffset_SimpleOffset.hxx
new file mode 100644 (file)
index 0000000..423f1fd
--- /dev/null
@@ -0,0 +1,183 @@
+// Created on: 2016-10-14
+// Created by: Alexander MALYSHEV
+// Copyright (c) 1999-2016 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _BRepOffset_SimpleOffset_HeaderFile
+#define _BRepOffset_SimpleOffset_HeaderFile
+
+#include <BRepTools_Modification.hxx>
+#include <GeomAbs_Shape.hxx>
+#include <Geom2d_Curve.hxx>
+#include <Standard_Real.hxx>
+#include <Standard_Macro.hxx>
+#include <Standard_Type.hxx>
+#include <TopoDS_Shape.hxx>
+#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
+#include <NCollection_DataMap.hxx>
+
+
+class BRepOffset_SimpleOffset;
+DEFINE_STANDARD_HANDLE(BRepOffset_SimpleOffset, BRepTools_Modification)
+
+//! This class represents mechanism of simple offset algorithm i. e.
+//! topology-preserve offset construction without intersection.
+//!
+//! The list below shows mapping scheme:
+//! - Each surface is mapped to its geometric offset surface.
+//! - For each edge, pcurves are mapped to the same pcurves on offset surfaces.
+//! - For each edge, 3d curve is constructed by re-approximation of pcurve on the first offset face.
+//! - Position of each vertex in a result shell is computed as average point of all ends of edges shared by that vertex.
+//! - Tolerances are updated according to the resulting geometry.
+class BRepOffset_SimpleOffset : public BRepTools_Modification
+{
+public:
+
+  DEFINE_STANDARD_RTTI_INLINE(BRepOffset_SimpleOffset, BRepTools_Modification)
+
+  //! Constructor.
+  Standard_EXPORT BRepOffset_SimpleOffset(const TopoDS_Shape& theInputShape,
+                                          const Standard_Real theOffsetValue);
+
+  //! Returns Standard_True  if  the face  <F> has  been
+  //! modified.  In this  case, <S> is the new geometric
+  //! support of  the  face, <L> the  new location,<Tol>
+  //! the new  tolerance.<RevWires> has  to  be set   to
+  //! Standard_True   when the modification reverses the
+  //! normal of  the   surface.(the wires   have  to  be
+  //! reversed).   <RevFace>   has   to   be   set    to
+  //! Standard_True if  the orientation  of the modified
+  //! face changes in the  shells which contain  it.  --
+  //! Here, <RevFace>  will  return Standard_True if the
+  //! -- gp_Trsf is negative.
+  Standard_EXPORT Standard_Boolean NewSurface (const TopoDS_Face& F,
+                                               Handle(Geom_Surface)& S,
+                                               TopLoc_Location& L,
+                                               Standard_Real& Tol,
+                                               Standard_Boolean& RevWires,
+                                               Standard_Boolean& RevFace) Standard_OVERRIDE;
+
+  //! Returns Standard_True  if  the edge  <E> has  been
+  //! modified.  In this case,  <C> is the new geometric
+  //! support of the  edge, <L> the  new location, <Tol>
+  //! the         new    tolerance.   Otherwise, returns
+  //! Standard_False,    and  <C>,  <L>,   <Tol> are not
+  //! significant.
+  Standard_EXPORT Standard_Boolean NewCurve (const TopoDS_Edge& E,
+                                             Handle(Geom_Curve)& C,
+                                             TopLoc_Location& L,
+                                             Standard_Real& Tol) Standard_OVERRIDE;
+
+  //! Returns  Standard_True if the  vertex <V> has been
+  //! modified.  In this  case, <P> is the new geometric
+  //! support of the vertex,   <Tol> the new  tolerance.
+  //! Otherwise, returns Standard_False, and <P>,  <Tol>
+  //! are not significant.
+  Standard_EXPORT Standard_Boolean NewPoint (const TopoDS_Vertex& V,
+                                             gp_Pnt& P,
+                                             Standard_Real& Tol) Standard_OVERRIDE;
+
+  //! Returns Standard_True if  the edge  <E> has a  new
+  //! curve on surface on the face <F>.In this case, <C>
+  //! is the new geometric support of  the edge, <L> the
+  //! new location, <Tol> the new tolerance.
+  //! Otherwise, returns  Standard_False, and <C>,  <L>,
+  //! <Tol> are not significant.
+  Standard_EXPORT Standard_Boolean NewCurve2d (const TopoDS_Edge& E,
+                                               const TopoDS_Face& F,
+                                               const TopoDS_Edge& NewE,
+                                               const TopoDS_Face& NewF,
+                                               Handle(Geom2d_Curve)& C,
+                                               Standard_Real& Tol) Standard_OVERRIDE;
+
+  //! Returns Standard_True if the Vertex  <V> has a new
+  //! parameter on the  edge <E>. In  this case,  <P> is
+  //! the parameter,    <Tol>  the     new    tolerance.
+  //! Otherwise, returns Standard_False, and <P>,  <Tol>
+  //! are not significant.
+  Standard_EXPORT Standard_Boolean NewParameter (const TopoDS_Vertex& V,
+                                                 const TopoDS_Edge& E,
+                                                 Standard_Real& P,
+                                                 Standard_Real& Tol) Standard_OVERRIDE;
+
+  //! Returns the  continuity of  <NewE> between <NewF1>
+  //! and <NewF2>.
+  //!
+  //! <NewE> is the new  edge created from <E>.  <NewF1>
+  //! (resp. <NewF2>) is the new  face created from <F1>
+  //! (resp. <F2>).
+  Standard_EXPORT GeomAbs_Shape Continuity (const TopoDS_Edge& E,
+                                            const TopoDS_Face& F1,
+                                            const TopoDS_Face& F2,
+                                            const TopoDS_Edge& NewE,
+                                            const TopoDS_Face& NewF1,
+                                            const TopoDS_Face& NewF2) Standard_OVERRIDE;
+
+private:
+
+  //! Method to fill new face data for single face.
+  void FillFaceData(const TopoDS_Face& theFace);
+
+  //! Method to fill new edge data for single edge.
+  void FillEdgeData(const TopoDS_Edge& theEdge,
+                    const TopTools_IndexedDataMapOfShapeListOfShape& theEdgeFaceMap,
+                    const Standard_Integer theIdx);
+
+  //! Method to fill new vertex data for single vertex.
+  void FillVertexData(const TopoDS_Vertex& theVertex,
+                      const TopTools_IndexedDataMapOfShapeListOfShape& theVertexEdgeMap,
+                      const Standard_Integer theIdx);
+
+  struct NewFaceData
+  {
+    Handle(Geom_Surface) myOffsetS;
+    TopLoc_Location myL;
+    Standard_Real myTol;
+    Standard_Boolean myRevWires;
+    Standard_Boolean myRevFace;
+  };
+
+  struct NewEdgeData
+  {
+    Handle(Geom_Curve) myOffsetC; // Resulting curve.
+    TopLoc_Location myL;
+    Standard_Real myTol;
+  };
+
+  struct NewVertexData
+  {
+    gp_Pnt myP;
+    Standard_Real myTol;
+  };
+
+  //! Fills offset data.
+  void FillOffsetData(const TopoDS_Shape& theInputShape);
+
+  //! Copy-assignment constructor and copy constructor are not allowed.
+  void operator=(const BRepOffset_SimpleOffset&);
+  BRepOffset_SimpleOffset(const BRepOffset_SimpleOffset&);
+
+  //! Map of faces to new faces information.
+  NCollection_DataMap<TopoDS_Face, NewFaceData> myFaceInfo;
+
+  //! Map of edges to new edges information.
+  NCollection_DataMap<TopoDS_Edge, NewEdgeData> myEdgeInfo;
+
+  //! Map of vertices to new vertices information.
+  NCollection_DataMap<TopoDS_Vertex, NewVertexData> myVertexInfo;
+
+  //! Offset value.
+  Standard_Real myOffsetValue;
+};
+
+#endif // _BRepOffset_SimpleOffset_HeaderFile
index c01c500..0f650d4 100644 (file)
@@ -23,9 +23,13 @@ BRepOffset_MakeLoops.hxx
 BRepOffset_MakeOffset.cxx
 BRepOffset_MakeOffset_1.cxx
 BRepOffset_MakeOffset.hxx
+BRepOffset_MakeSimpleOffset.cxx
+BRepOffset_MakeSimpleOffset.hxx
 BRepOffset_Mode.hxx
 BRepOffset_Offset.cxx
 BRepOffset_Offset.hxx
+BRepOffset_SimpleOffset.cxx
+BRepOffset_SimpleOffset.hxx
 BRepOffset_Offset.lxx
 BRepOffset_Status.hxx
 BRepOffset_Tool.cxx
index 5a7318f..c720e6c 100644 (file)
@@ -14,9 +14,6 @@
 // Alternatively, this file may be used under the terms of Open CASCADE
 // commercial license or contractual agreement.
 
-//  Modified by skv - Tue Mar 15 16:20:43 2005
-// Add methods for supporting history.
-
 #include <BRepOffset_MakeOffset.hxx>
 #include <BRepOffsetAPI_MakeOffsetShape.hxx>
 #include <Standard_ConstructionError.hxx>
@@ -28,6 +25,7 @@
 //purpose  : 
 //=======================================================================
 BRepOffsetAPI_MakeOffsetShape::BRepOffsetAPI_MakeOffsetShape()
+: myLastUsedAlgo(OffsetAlgo_NONE)
 {
 }
 
@@ -35,29 +33,72 @@ BRepOffsetAPI_MakeOffsetShape::BRepOffsetAPI_MakeOffsetShape()
 //function : BRepOffsetAPI_MakeOffsetShape
 //purpose  : 
 //=======================================================================
+BRepOffsetAPI_MakeOffsetShape::BRepOffsetAPI_MakeOffsetShape(const TopoDS_Shape& S,
+                                                             const Standard_Real Offset,
+                                                             const Standard_Real Tol,
+                                                             const BRepOffset_Mode Mode,
+                                                             const Standard_Boolean Intersection,
+                                                             const Standard_Boolean SelfInter,
+                                                             const GeomAbs_JoinType Join,
+                                                             const Standard_Boolean RemoveIntEdges)
+: myLastUsedAlgo(OffsetAlgo_NONE)
+{
+  PerformByJoin(S, Offset, Tol, Mode, Intersection, SelfInter, Join, RemoveIntEdges);
+}
 
-BRepOffsetAPI_MakeOffsetShape::BRepOffsetAPI_MakeOffsetShape
-(const TopoDS_Shape&    S, 
- const Standard_Real    Offset, 
- const Standard_Real    Tol, 
- const BRepOffset_Mode  Mode, 
+//=======================================================================
+//function : PerformByJoin
+//purpose  : 
+//=======================================================================
+void BRepOffsetAPI_MakeOffsetShape::PerformByJoin
+(const TopoDS_Shape&    S,
+ const Standard_Real    Offset,
+ const Standard_Real    Tol,
+ const BRepOffset_Mode  Mode,
  const Standard_Boolean Intersection,
  const Standard_Boolean SelfInter,
  const GeomAbs_JoinType Join,
  const Standard_Boolean RemoveIntEdges)
 {
+  NotDone();
+  myLastUsedAlgo = OffsetAlgo_JOIN;
+
   myOffsetShape.Initialize (S,Offset,Tol,Mode,Intersection,SelfInter,
                             Join, Standard_False, RemoveIntEdges);
-  Build();
+  myOffsetShape.MakeOffsetShape();
+
+  if (!myOffsetShape.IsDone())
+    return;
+
+  myShape  = myOffsetShape.Shape();
+  Done();
 }
 
+//=======================================================================
+//function : PerformBySimple
+//purpose  : 
+//=======================================================================
+void BRepOffsetAPI_MakeOffsetShape::PerformBySimple(const TopoDS_Shape& theS,
+                                                    const Standard_Real theOffsetValue)
+{
+  NotDone();
+  myLastUsedAlgo = OffsetAlgo_SIMPLE;
+
+  mySimpleOffsetShape.Initialize(theS, theOffsetValue);
+  mySimpleOffsetShape.Perform();
+
+  if (!mySimpleOffsetShape.IsDone())
+    return;
+
+  myShape = mySimpleOffsetShape.GetResultShape();
+  Done();
+}
 
 //=======================================================================
 //function :MakeOffset
 //purpose  : 
 //=======================================================================
-
-const BRepOffset_MakeOffset& BRepOffsetAPI_MakeOffsetShape::MakeOffset() const 
+const BRepOffset_MakeOffset& BRepOffsetAPI_MakeOffsetShape::MakeOffset() const
 {
   return myOffsetShape;
 }
@@ -66,72 +107,74 @@ const BRepOffset_MakeOffset& BRepOffsetAPI_MakeOffsetShape::MakeOffset() const
 //function : Build
 //purpose  : 
 //=======================================================================
-
 void BRepOffsetAPI_MakeOffsetShape::Build()
 {
-  if (!IsDone()) {
-    myOffsetShape.MakeOffsetShape();
-    if (!myOffsetShape.IsDone()) return;
-    myShape  = myOffsetShape.Shape();
-    Done();
-  }
 }
 
-
 //=======================================================================
 //function : Generated
 //purpose  : 
 //=======================================================================
-
-const TopTools_ListOfShape& BRepOffsetAPI_MakeOffsetShape::Generated (const TopoDS_Shape& S) 
-
-{  
+const TopTools_ListOfShape& BRepOffsetAPI_MakeOffsetShape::Generated (const TopoDS_Shape& S)
+{
   myGenerated.Clear();
-  if (!myOffsetShape.ClosingFaces().Contains(S)) {
+
+  if (myLastUsedAlgo == OffsetAlgo_JOIN && !myOffsetShape.ClosingFaces().Contains(S))
+  {
     myOffsetShape.OffsetFacesFromShapes ().LastImage (S, myGenerated);
-   
-    if (!myOffsetShape.ClosingFaces().IsEmpty()) {
+
+    if (!myOffsetShape.ClosingFaces().IsEmpty())
+    {
       // Reverse generated shapes in case of small solids.
       // Useful only for faces without influence on others.
       TopTools_ListIteratorOfListOfShape it(myGenerated);
       for (; it.More(); it.Next())
-       it.Value().Reverse();
+        it.Value().Reverse();
     }
   }
+  else if (myLastUsedAlgo == OffsetAlgo_SIMPLE)
+  {
+    TopoDS_Shape aGenShape = mySimpleOffsetShape.Generated(S);
+    if (!aGenShape.IsNull())
+      myGenerated.Append(aGenShape);
+  }
+
   return myGenerated;
 }
 
-
-//  Modified by skv - Tue Mar 15 16:20:43 2005 Begin
-
 //=======================================================================
 //function : GeneratedEdge
 //purpose  : 
 //=======================================================================
-
-const TopTools_ListOfShape& BRepOffsetAPI_MakeOffsetShape::GeneratedEdge (const TopoDS_Shape& S) 
-
-{  
+const TopTools_ListOfShape& BRepOffsetAPI_MakeOffsetShape::GeneratedEdge (const TopoDS_Shape& S)
+{
   myGenerated.Clear();
-  myOffsetShape.OffsetEdgesFromShapes ().LastImage (S, myGenerated);
 
-  if (!myGenerated.IsEmpty()) {
-    if (S.IsSame(myGenerated.First()))
-      myGenerated.RemoveFirst();
+  if (myLastUsedAlgo == OffsetAlgo_JOIN)
+  {
+    myOffsetShape.OffsetEdgesFromShapes().LastImage (S, myGenerated);
+
+    if (!myGenerated.IsEmpty())
+    {
+      if (S.IsSame(myGenerated.First()))
+        myGenerated.RemoveFirst();
+    }
+  }
+  else if (myLastUsedAlgo == OffsetAlgo_SIMPLE)
+  {
+    TopoDS_Shape aGenShape = mySimpleOffsetShape.Generated(S);
+    if (!aGenShape.IsNull())
+      myGenerated.Append(aGenShape);
   }
 
   return myGenerated;
 }
 
-
 //=======================================================================
 //function : GetJoinType
 //purpose  : Query offset join type.
 //=======================================================================
-
 GeomAbs_JoinType BRepOffsetAPI_MakeOffsetShape::GetJoinType() const
 {
   return myOffsetShape.GetJoinType();
 }
-
-//  Modified by skv - Tue Mar 15 16:20:43 2005 End
index f37ea51..b528e39 100644 (file)
@@ -22,6 +22,7 @@
 #include <Standard_Handle.hxx>
 
 #include <BRepOffset_MakeOffset.hxx>
+#include <BRepOffset_MakeSimpleOffset.hxx>
 #include <BRepBuilderAPI_MakeShape.hxx>
 #include <Standard_Real.hxx>
 #include <BRepOffset_Mode.hxx>
@@ -44,9 +45,24 @@ public:
 
   DEFINE_STANDARD_ALLOC
 
-  
+  //! Constructor does nothing.
   Standard_EXPORT BRepOffsetAPI_MakeOffsetShape();
-  
+
+  //! Deprecated constructor. Please avoid usage of this constructor.
+  Standard_DEPRECATED("Deprecated constructor. Please use constructor without parameters and one of perform methods.")
+  Standard_EXPORT BRepOffsetAPI_MakeOffsetShape(const TopoDS_Shape& S, 
+                                                const Standard_Real Offset, 
+                                                const Standard_Real Tol, 
+                                                const BRepOffset_Mode Mode = BRepOffset_Skin, 
+                                                const Standard_Boolean Intersection = Standard_False, 
+                                                const Standard_Boolean SelfInter = Standard_False, 
+                                                const GeomAbs_JoinType Join = GeomAbs_Arc,
+                                                const Standard_Boolean RemoveIntEdges = Standard_False);
+
+  //! Constructs offset shape for the given one using simple algorithm without intersections computation.
+  Standard_EXPORT void PerformBySimple(const TopoDS_Shape& theS,
+                                       const Standard_Real theOffsetValue);
+
   //! Constructs a shape parallel to the shape S, where
   //! - S may be a face, a shell, a solid or a compound of these shape kinds;
   //! - Offset is the offset value. The offset shape is constructed:
@@ -102,22 +118,22 @@ public:
   //! Exceptions
   //! Geom_UndefinedDerivative if the underlying
   //! geometry of S is BSpline with continuity C0.
-  Standard_EXPORT BRepOffsetAPI_MakeOffsetShape(const TopoDS_Shape& S, 
-                                                const Standard_Real Offset, 
-                                                const Standard_Real Tol, 
-                                                const BRepOffset_Mode Mode = BRepOffset_Skin, 
-                                                const Standard_Boolean Intersection = Standard_False, 
-                                                const Standard_Boolean SelfInter = Standard_False, 
-                                                const GeomAbs_JoinType Join = GeomAbs_Arc,
-                                                const Standard_Boolean RemoveIntEdges = Standard_False);
-
+  Standard_EXPORT void PerformByJoin(const TopoDS_Shape& S,
+                                     const Standard_Real Offset,
+                                     const Standard_Real Tol,
+                                     const BRepOffset_Mode Mode = BRepOffset_Skin,
+                                     const Standard_Boolean Intersection = Standard_False,
+                                     const Standard_Boolean SelfInter = Standard_False,
+                                     const GeomAbs_JoinType Join = GeomAbs_Arc,
+                                     const Standard_Boolean RemoveIntEdges = Standard_False);
+
+  //! Returns instance of the unrelying intersection / arc algorithm.
   Standard_EXPORT virtual const BRepOffset_MakeOffset& MakeOffset() const;
-  
-  //! Builds the resulting shape (redefined from MakeShape).
+
+  //! Does nothing.
   Standard_EXPORT virtual void Build() Standard_OVERRIDE;
   
-  //! Returns the  list   of shapes generated   from the
-  //! shape <S>.
+  //! Returns the  list   of shapes generated from the shape <S>.
   Standard_EXPORT virtual const TopTools_ListOfShape& Generated (const TopoDS_Shape& S) Standard_OVERRIDE;
   
   //! Returns the list of edges generated from the shape <S>.
@@ -126,28 +142,19 @@ public:
   //! Returns offset join type.
   Standard_EXPORT GeomAbs_JoinType GetJoinType() const;
 
-
-
-
 protected:
 
+  enum OffsetAlgo_Type
+  {
+    OffsetAlgo_NONE,
+    OffsetAlgo_JOIN,
+    OffsetAlgo_SIMPLE
+  };
 
+  OffsetAlgo_Type myLastUsedAlgo;
 
   BRepOffset_MakeOffset myOffsetShape;
-
-
-private:
-
-
-
-
-
+  BRepOffset_MakeSimpleOffset mySimpleOffsetShape;
 };
 
-
-
-
-
-
-
 #endif // _BRepOffsetAPI_MakeOffsetShape_HeaderFile
index 79f444c..b4a4a4c 100644 (file)
 #include <TopoDS_Shape.hxx>
 #include <TopTools_ListIteratorOfListOfShape.hxx>
 
+
 //=======================================================================
 //function : BRepOffsetAPI_MakeThickSolid
 //purpose  : 
 //=======================================================================
 BRepOffsetAPI_MakeThickSolid::BRepOffsetAPI_MakeThickSolid()
 {
+  // Build only solids.
+  mySimpleOffsetShape.SetBuildSolidFlag(Standard_True);
 }
 
-
 //=======================================================================
 //function : BRepOffsetAPI_MakeThickSolid
 //purpose  : 
 //=======================================================================
+BRepOffsetAPI_MakeThickSolid::BRepOffsetAPI_MakeThickSolid(const TopoDS_Shape& S,
+                                                           const TopTools_ListOfShape& ClosingFaces,
+                                                           const Standard_Real Offset,
+                                                           const Standard_Real Tol,
+                                                           const BRepOffset_Mode Mode,
+                                                           const Standard_Boolean Intersection,
+                                                           const Standard_Boolean SelfInter,
+                                                           const GeomAbs_JoinType Join,
+                                                           const Standard_Boolean RemoveIntEdges)
+{
+  // Build only solids.
+  mySimpleOffsetShape.SetBuildSolidFlag(Standard_True);
+
+  MakeThickSolidByJoin(S, ClosingFaces, Offset, Tol,
+                       Mode, Intersection, SelfInter, Join, RemoveIntEdges);
+}
 
-BRepOffsetAPI_MakeThickSolid::BRepOffsetAPI_MakeThickSolid
-(const TopoDS_Shape&         S, 
+//=======================================================================
+//function : MakeThickSolidByJoin
+//purpose  : 
+//=======================================================================
+void BRepOffsetAPI_MakeThickSolid::MakeThickSolidByJoin
+(const TopoDS_Shape&         S,
  const TopTools_ListOfShape& ClosingFaces,
  const Standard_Real         Offset, 
  const Standard_Real         Tol, 
@@ -47,51 +69,78 @@ BRepOffsetAPI_MakeThickSolid::BRepOffsetAPI_MakeThickSolid
  const GeomAbs_JoinType      Join,
  const Standard_Boolean      RemoveIntEdges)
 {
+  NotDone();
+  myLastUsedAlgo = OffsetAlgo_JOIN;
+
   myOffsetShape.Initialize (S,Offset,Tol,Mode,Intersection,SelfInter,
                             Join, Standard_False, RemoveIntEdges);
   TopTools_ListIteratorOfListOfShape it(ClosingFaces);
-  for (; it.More(); it.Next()) {
+  for (; it.More(); it.Next())
     myOffsetShape.AddFace(TopoDS::Face(it.Value()));
-  }
-  Build();
+
+  myOffsetShape.MakeThickSolid();
+  if (!myOffsetShape.IsDone())
+    return;
+
+  myShape  = myOffsetShape.Shape();
+  Done();
 }
 
 //=======================================================================
-//function : virtual
+//function : MakeThickSolidBySimple
 //purpose  : 
 //=======================================================================
+void BRepOffsetAPI_MakeThickSolid::MakeThickSolidBySimple(const TopoDS_Shape& theS,
+                                                          const Standard_Real theOffsetValue)
+{
+  NotDone();
+  myLastUsedAlgo = OffsetAlgo_SIMPLE;
+
+  mySimpleOffsetShape.Initialize(theS, theOffsetValue);
+  mySimpleOffsetShape.Perform();
+
+  if (!mySimpleOffsetShape.IsDone())
+    return;
 
+  myShape = mySimpleOffsetShape.GetResultShape();
+  Done();
+}
+
+//=======================================================================
+//function : Build
+//purpose  : 
+//=======================================================================
 void BRepOffsetAPI_MakeThickSolid::Build()
 {
-  if (!IsDone()) {
-    myOffsetShape.MakeThickSolid();
-    if (!myOffsetShape.IsDone()) return;
-    myShape  = myOffsetShape.Shape();
-    Done();
-  }
 }
 
-
-
 //=======================================================================
 //function : Modified
 //purpose  : 
 //=======================================================================
-
-const TopTools_ListOfShape& BRepOffsetAPI_MakeThickSolid::Modified (const TopoDS_Shape& F) 
-
+const TopTools_ListOfShape& BRepOffsetAPI_MakeThickSolid::Modified (const TopoDS_Shape& F)
 {
   myGenerated.Clear();
-  if (myOffsetShape.OffsetFacesFromShapes().HasImage(F)) {
-    if (myOffsetShape.ClosingFaces().Contains(F)) { 
-      myOffsetShape.OffsetFacesFromShapes().LastImage (F, myGenerated); 
-      // Les face du resultat sont orientees comme dans la piece initiale.
-      //si offset a l interieur.
+
+  if (myLastUsedAlgo == OffsetAlgo_JOIN && myOffsetShape.OffsetFacesFromShapes().HasImage(F))
+  {
+    if (myOffsetShape.ClosingFaces().Contains(F))
+    {
+      myOffsetShape.OffsetFacesFromShapes().LastImage (F, myGenerated);
+
+      // Reverse generated shapes in case of small solids.
+      // Useful only for faces without influence on others.
       TopTools_ListIteratorOfListOfShape it(myGenerated);
       for (; it.More(); it.Next())
-       it.Value().Reverse();
-   
+        it.Value().Reverse();
     }
   }
+  else if (myLastUsedAlgo == OffsetAlgo_SIMPLE)
+  {
+    TopoDS_Shape aModShape = mySimpleOffsetShape.Modified(F);
+    if (!aModShape.IsNull())
+      myGenerated.Append(aModShape);
+  }
+
   return myGenerated;
 }
index 1ef6c6b..7facdce 100644 (file)
@@ -51,9 +51,29 @@ public:
 
   DEFINE_STANDARD_ALLOC
 
-  
+  //! Constructor does nothing.
   Standard_EXPORT BRepOffsetAPI_MakeThickSolid();
-  
+
+  //! Deprecated constructor. Please avoid usage of this constructor.
+  Standard_DEPRECATED("Deprecated constructor. Please use constructor without parameters and one of make methods.")
+  Standard_EXPORT BRepOffsetAPI_MakeThickSolid(const TopoDS_Shape& S,
+                                               const TopTools_ListOfShape& ClosingFaces,
+                                               const Standard_Real Offset,
+                                               const Standard_Real Tol,
+                                               const BRepOffset_Mode Mode = BRepOffset_Skin,
+                                               const Standard_Boolean Intersection = Standard_False,
+                                               const Standard_Boolean SelfInter = Standard_False,
+                                               const GeomAbs_JoinType Join = GeomAbs_Arc,
+                                               const Standard_Boolean RemoveIntEdges = Standard_False);
+
+  //! Constructs solid using simple algorithm. 
+  //! According to its nature it is not possible to set list of the closing faces.
+  //! This algorithm does not support faces removing. It is caused by fact that 
+  //! intersections are not computed during offset creation.
+  //! Non-closed shell or face is expected as input.
+  Standard_EXPORT void MakeThickSolidBySimple(const TopoDS_Shape& theS,
+                                              const Standard_Real theOffsetValue);
+
   //! Constructs a hollowed solid from
   //! the solid S by removing the set of faces ClosingFaces from S, where:
   //! Offset defines the thickness of the walls. Its sign indicates
@@ -94,44 +114,22 @@ public:
   //! Since the algorithm of MakeThickSolid is based on
   //! MakeOffsetShape algorithm, the warnings are the same as for
   //! MakeOffsetShape.
-  Standard_EXPORT BRepOffsetAPI_MakeThickSolid(const TopoDS_Shape& S, 
-                                               const TopTools_ListOfShape& ClosingFaces, 
-                                               const Standard_Real Offset, 
-                                               const Standard_Real Tol, 
-                                               const BRepOffset_Mode Mode = BRepOffset_Skin, 
-                                               const Standard_Boolean Intersection = Standard_False,
-                                               const Standard_Boolean SelfInter = Standard_False, 
-                                               const GeomAbs_JoinType Join = GeomAbs_Arc,
-                                               const Standard_Boolean RemoveIntEdges = Standard_False);
-  
-  //! Builds the resulting shape (redefined from MakeOffsetShape).
+  Standard_EXPORT void MakeThickSolidByJoin(const TopoDS_Shape& S,
+                                            const TopTools_ListOfShape& ClosingFaces,
+                                            const Standard_Real Offset,
+                                            const Standard_Real Tol,
+                                            const BRepOffset_Mode Mode = BRepOffset_Skin,
+                                            const Standard_Boolean Intersection = Standard_False,
+                                            const Standard_Boolean SelfInter = Standard_False,
+                                            const GeomAbs_JoinType Join = GeomAbs_Arc,
+                                            const Standard_Boolean RemoveIntEdges = Standard_False);
+
+  // Does nothing.
   Standard_EXPORT virtual void Build() Standard_OVERRIDE;
   
   //! Returns the list  of shapes modified from the shape
   //! <S>.
   Standard_EXPORT virtual const TopTools_ListOfShape& Modified (const TopoDS_Shape& S) Standard_OVERRIDE;
-
-
-
-
-protected:
-
-
-
-
-
-private:
-
-
-
-
-
 };
 
-
-
-
-
-
-
 #endif // _BRepOffsetAPI_MakeThickSolid_HeaderFile
index bcf5f2e..d69a51a 100644 (file)
@@ -54,8 +54,8 @@
 #include <LocOpe_FindEdges.hxx>
 #include <LocOpe_FindEdgesInFace.hxx>
 
-#include <BRepOffsetAPI_MakeOffsetShape.hxx>
-#include <BRepOffsetAPI_MakeThickSolid.hxx>
+#include <BRepOffset_MakeOffset.hxx>
+#include <BRepOffset_MakeSimpleOffset.hxx>
 #include <BRep_Tool.hxx>
 #include <BRep_Builder.hxx>
 #include <DBRep.hxx>
@@ -2239,6 +2239,52 @@ static Standard_Integer BOSS(Draw_Interpretor& theCommands,
   return 1;
 }
 
+//=============================================================================
+//function : ComputeSimpleOffset
+//purpose  : Computes simple offset.
+//=============================================================================
+static Standard_Integer ComputeSimpleOffset(Draw_Interpretor& theCommands,
+                                            Standard_Integer narg, 
+                                            const char** a)
+{
+  if (narg != 4 && narg != 5)
+  {
+    theCommands << "offsetshapesimple result shape offsetvalue [solid]\n";
+    return 1;
+  }
+
+  // Input data.
+  TopoDS_Shape aShape = DBRep::Get(a[2]);
+  if (aShape.IsNull())
+  {
+    theCommands << "Input shape is null";
+    return 0;
+  }
+  const Standard_Real anOffsetValue = Draw::Atof(a[3]);
+  if (Abs(anOffsetValue) < gp::Resolution())
+  {
+    theCommands << "Null offset value";
+    return 0;
+  }
+
+  BRepOffset_MakeSimpleOffset aMaker(aShape, anOffsetValue);
+  if (narg == 5 && !strcasecmp(a[4],"solid") )
+  {
+    aMaker.SetBuildSolidFlag(Standard_True);
+  }
+
+  aMaker.Perform();
+
+  if (!aMaker.IsDone())
+  {
+    theCommands << "ERROR:" << aMaker.GetErrorMessage() << "\n";
+    return 0;
+  }
+
+  DBRep::Set(a[1], aMaker.GetResultShape());
+
+  return 0;
+}
 
 //=======================================================================
 //function : FeatureCommands
@@ -2385,4 +2431,7 @@ void BRepTest::FeatureCommands (Draw_Interpretor& theCommands)
                  " Perform fillet on top and bottom edges of dprism :bossage dprism result radtop radbottom First/LastShape (1/2)",
                  __FILE__,BOSS);
 
+  theCommands.Add("offsetshapesimple", 
+                  "offsetshapesimple result shape offsetvalue [solid]",
+                  __FILE__, ComputeSimpleOffset);
 }
index cceddc0..4308b17 100644 (file)
@@ -1,4 +1,4 @@
-# To prevent loops limit to 10 minutes
+# To prevent loops limit to 15 minutes
 cpulimit 900
 if { [array get Draw_Groups "TOPOLOGY Feature commands"] == "" } {
     pload TOPTEST
index 3d18842..e4364eb 100644 (file)
@@ -16,3 +16,4 @@
 016 with_intersect_20
 017 with_intersect_80
 018 shape_type_i_c
+019 simple
diff --git a/tests/offset/simple/A01 b/tests/offset/simple/A01
new file mode 100644 (file)
index 0000000..94cd957
--- /dev/null
@@ -0,0 +1,9 @@
+# Test data:
+puts "USER GUID: N/A"
+restore [locate_data_file bug26663_test_offset_J8.brep] s
+
+set OffsetValue 20.0
+
+# Reference data.
+set ExpectedMass 3.05711e+006
+set ExpectedMaxTol 26.38
\ No newline at end of file
diff --git a/tests/offset/simple/A02 b/tests/offset/simple/A02
new file mode 100644 (file)
index 0000000..47d6f84
--- /dev/null
@@ -0,0 +1,8 @@
+# Test data:
+puts "USER GUID: N/A"
+restore [locate_data_file bug26663_test_offset_K3.brep] s
+set OffsetValue 20.0
+
+# Reference data.
+set ExpectedMass 1.3279e+007
+set ExpectedMaxTol 0.09
\ No newline at end of file
diff --git a/tests/offset/simple/A03 b/tests/offset/simple/A03
new file mode 100644 (file)
index 0000000..4a36c6d
--- /dev/null
@@ -0,0 +1,8 @@
+# Test data:
+puts "USER GUID: N/A"
+restore [locate_data_file bug26663_test_offset_K4.brep] s
+set OffsetValue 20.0
+
+# Reference data.
+set ExpectedMass 2.72622e+006
+set ExpectedMaxTol 23.75
\ No newline at end of file
diff --git a/tests/offset/simple/A04 b/tests/offset/simple/A04
new file mode 100644 (file)
index 0000000..4e0f1aa
--- /dev/null
@@ -0,0 +1,8 @@
+# Test data:
+puts "USER GUID: N/A"
+restore [locate_data_file bug26663_test_offset_K5.brep] s
+set OffsetValue 20.0
+
+# Reference data.
+set ExpectedMass 2.96921e+006
+set ExpectedMaxTol 1.02
\ No newline at end of file
diff --git a/tests/offset/simple/A05 b/tests/offset/simple/A05
new file mode 100644 (file)
index 0000000..639c54e
--- /dev/null
@@ -0,0 +1,8 @@
+# Test data:
+puts "USER GUID: N/A"
+restore [locate_data_file bug26663_test_offset_K6.brep] s
+set OffsetValue 20.0
+
+# Reference data.
+set ExpectedMass 3.82881e+006
+set ExpectedMaxTol 1.25
\ No newline at end of file
diff --git a/tests/offset/simple/A06 b/tests/offset/simple/A06
new file mode 100644 (file)
index 0000000..ae9693b
--- /dev/null
@@ -0,0 +1,8 @@
+# Test data:
+puts "USER GUID: N/A"
+restore [locate_data_file bug26663_test_offset_K7.brep] s
+set OffsetValue 20.0
+
+# Reference data.
+set ExpectedMass 1.52853e+006
+set ExpectedMaxTol 26.38
\ No newline at end of file
diff --git a/tests/offset/simple/A07 b/tests/offset/simple/A07
new file mode 100644 (file)
index 0000000..c0a48b2
--- /dev/null
@@ -0,0 +1,8 @@
+# Test data:
+puts "USER GUID: N/A"
+restore [locate_data_file bug26663_test_offset_K9.brep] s
+set OffsetValue 20.0
+
+# Reference data.
+set ExpectedMass 2.65579e+007
+set ExpectedMaxTol 24.55
\ No newline at end of file
diff --git a/tests/offset/simple/A08 b/tests/offset/simple/A08
new file mode 100644 (file)
index 0000000..922f9f4
--- /dev/null
@@ -0,0 +1,8 @@
+# Test data:
+puts "USER GUID: N/A"
+restore [locate_data_file bug26663_test_offset_J8.brep] s
+set OffsetValue 80.0
+
+# Reference data.
+set ExpectedMass 3.03486e+006
+set ExpectedMaxTol 105.52
\ No newline at end of file
diff --git a/tests/offset/simple/A09 b/tests/offset/simple/A09
new file mode 100644 (file)
index 0000000..fe7acca
--- /dev/null
@@ -0,0 +1,8 @@
+# Test data:
+puts "USER GUID: N/A"
+restore [locate_data_file bug26663_test_offset_K3.brep] s
+set OffsetValue 80.0
+
+# Reference data.
+set ExpectedMass 1.32749e+007
+set ExpectedMaxTol 0.3556
\ No newline at end of file
diff --git a/tests/offset/simple/A10 b/tests/offset/simple/A10
new file mode 100644 (file)
index 0000000..6774615
--- /dev/null
@@ -0,0 +1,8 @@
+# Test data:
+puts "USER GUID: N/A"
+restore [locate_data_file bug26663_test_offset_K4.brep] s
+set OffsetValue 80.0
+
+# Reference data.
+set ExpectedMass 2.68488e+006
+set ExpectedMaxTol 94.99
\ No newline at end of file
diff --git a/tests/offset/simple/A11 b/tests/offset/simple/A11
new file mode 100644 (file)
index 0000000..d93bb44
--- /dev/null
@@ -0,0 +1,8 @@
+# Test data:
+puts "USER GUID: N/A"
+restore [locate_data_file bug26663_test_offset_K5.brep] s
+set OffsetValue 80.0
+
+# Reference data.
+set ExpectedMass 2.94956e+006
+set ExpectedMaxTol 4.06
\ No newline at end of file
diff --git a/tests/offset/simple/A12 b/tests/offset/simple/A12
new file mode 100644 (file)
index 0000000..16d8e67
--- /dev/null
@@ -0,0 +1,8 @@
+# Test data:
+puts "USER GUID: N/A"
+restore [locate_data_file bug26663_test_offset_K6.brep] s
+set OffsetValue 80.0
+
+# Reference data.
+set ExpectedMass 3.79364e+006
+set ExpectedMaxTol 5.02
\ No newline at end of file
diff --git a/tests/offset/simple/A13 b/tests/offset/simple/A13
new file mode 100644 (file)
index 0000000..cc9a0c9
--- /dev/null
@@ -0,0 +1,8 @@
+# Test data:
+puts "USER GUID: N/A"
+restore [locate_data_file bug26663_test_offset_K7.brep] s
+set OffsetValue 80.0
+
+# Reference data.
+set ExpectedMass 1.51738e+006
+set ExpectedMaxTol 105.52
\ No newline at end of file
diff --git a/tests/offset/simple/A14 b/tests/offset/simple/A14
new file mode 100644 (file)
index 0000000..0f51753
--- /dev/null
@@ -0,0 +1,8 @@
+# Test data:
+puts "USER GUID: N/A"
+restore [locate_data_file bug26663_test_offset_K9.brep] s
+set OffsetValue 80.0
+
+# Reference data.
+set ExpectedMass 2.65498e+007
+set ExpectedMaxTol 98.21
\ No newline at end of file
diff --git a/tests/offset/simple/B01 b/tests/offset/simple/B01
new file mode 100644 (file)
index 0000000..799452e
--- /dev/null
@@ -0,0 +1,9 @@
+# Test data:
+puts "USER GUID: N/A"
+restore [locate_data_file bug26663_test_offset_J9.brep] s
+
+set OffsetValue 20.0
+
+# Reference data.
+set ExpectedMass 3.44079e+006
+set ExpectedMaxTol 21.55
\ No newline at end of file
diff --git a/tests/offset/simple/B02 b/tests/offset/simple/B02
new file mode 100644 (file)
index 0000000..7dc985f
--- /dev/null
@@ -0,0 +1,9 @@
+# Test data:
+puts "USER GUID: N/A"
+restore [locate_data_file bug26663_test_offset_M9.brep] s
+
+set OffsetValue 20.0
+
+# Reference data.
+set ExpectedMass 2.82491e+007
+set ExpectedMaxTol 0.3932
\ No newline at end of file
diff --git a/tests/offset/simple/B03 b/tests/offset/simple/B03
new file mode 100644 (file)
index 0000000..8c07d42
--- /dev/null
@@ -0,0 +1,9 @@
+# Test data:
+puts "USER GUID: N/A"
+restore [locate_data_file bug26663_test_offset_K1.brep] s
+
+set OffsetValue 80.0
+
+# Reference data.
+set ExpectedMass 3.45168e+007
+set ExpectedMaxTol 1.141
\ No newline at end of file
diff --git a/tests/offset/simple/B04 b/tests/offset/simple/B04
new file mode 100644 (file)
index 0000000..4b1ff06
--- /dev/null
@@ -0,0 +1,9 @@
+# Test data:
+puts "USER GUID: N/A"
+restore [locate_data_file bug26663_test_offset_K2.brep] s
+
+set OffsetValue 80.0
+
+# Reference data.
+set ExpectedMass 1.2251e+007
+set ExpectedMaxTol 2.412
\ No newline at end of file
diff --git a/tests/offset/simple/B05 b/tests/offset/simple/B05
new file mode 100644 (file)
index 0000000..5fb28e7
--- /dev/null
@@ -0,0 +1,9 @@
+# Test data:
+puts "USER GUID: N/A"
+restore [locate_data_file bug26663_test_offset_L3.brep] s
+
+set OffsetValue 80.0
+
+# Reference data.
+set ExpectedMass 2.00982e+007
+set ExpectedMaxTol 7.98
\ No newline at end of file
diff --git a/tests/offset/simple/B06 b/tests/offset/simple/B06
new file mode 100644 (file)
index 0000000..e0847cd
--- /dev/null
@@ -0,0 +1,9 @@
+# Test data:
+puts "USER GUID: N/A"
+restore [locate_data_file bug26663_test_offset_L4.brep] s
+
+set OffsetValue 80.0
+
+# Reference data.
+set ExpectedMass 2.82262e+007
+set ExpectedMaxTol 0.1681
\ No newline at end of file
diff --git a/tests/offset/simple/B07 b/tests/offset/simple/B07
new file mode 100644 (file)
index 0000000..26b27f5
--- /dev/null
@@ -0,0 +1,9 @@
+# Test data:
+puts "USER GUID: N/A"
+restore [locate_data_file bug26663_test_offset_L6.brep] s
+
+set OffsetValue 80.0
+
+# Reference data.
+set ExpectedMass 1.93426e+007
+set ExpectedMaxTol 1.339
\ No newline at end of file
diff --git a/tests/offset/simple/B08 b/tests/offset/simple/B08
new file mode 100644 (file)
index 0000000..665200c
--- /dev/null
@@ -0,0 +1,9 @@
+# Test data:
+puts "USER GUID: N/A"
+restore [locate_data_file bug26663_test_offset_L7.brep] s
+
+set OffsetValue 80.0
+
+# Reference data.
+set ExpectedMass 1.2251e+007
+set ExpectedMaxTol 2.412
\ No newline at end of file
diff --git a/tests/offset/simple/B09 b/tests/offset/simple/B09
new file mode 100644 (file)
index 0000000..e7bb52f
--- /dev/null
@@ -0,0 +1,9 @@
+# Test data:
+puts "USER GUID: N/A"
+restore [locate_data_file bug26663_test_offset_L8.brep] s
+
+set OffsetValue 80.0
+
+# Reference data.
+set ExpectedMass 1.93227e+007
+set ExpectedMaxTol 1.179
\ No newline at end of file
diff --git a/tests/offset/simple/B10 b/tests/offset/simple/B10
new file mode 100644 (file)
index 0000000..ac8e883
--- /dev/null
@@ -0,0 +1,9 @@
+# Test data:
+puts "USER GUID: N/A"
+restore [locate_data_file bug26663_test_offset_M9.brep] s
+
+set OffsetValue 80.0
+
+# Reference data.
+set ExpectedMass 2.82486e+007
+set ExpectedMaxTol 1.573
\ No newline at end of file
diff --git a/tests/offset/simple/B11 b/tests/offset/simple/B11
new file mode 100644 (file)
index 0000000..30a41bf
--- /dev/null
@@ -0,0 +1,9 @@
+# Test data:
+puts "USER GUID: N/A"
+restore [locate_data_file bug26663_test_offset_L9.brep] s
+
+set OffsetValue 80.0
+
+# Reference data.
+set ExpectedMass 2.00982e+007
+set ExpectedMaxTol 7.98
\ No newline at end of file
diff --git a/tests/offset/simple/B12 b/tests/offset/simple/B12
new file mode 100644 (file)
index 0000000..1b1ac4a
--- /dev/null
@@ -0,0 +1,9 @@
+# Test data:
+puts "USER GUID: N/A"
+restore [locate_data_file bug26663_test_offset_M1.brep] s
+
+set OffsetValue 80.0
+
+# Reference data.
+set ExpectedMass 3.45168e+007
+set ExpectedMaxTol 1.141
\ No newline at end of file
diff --git a/tests/offset/simple/B13 b/tests/offset/simple/B13
new file mode 100644 (file)
index 0000000..8cebb17
--- /dev/null
@@ -0,0 +1,9 @@
+# Test data:
+puts "USER GUID: N/A"
+restore [locate_data_file bug26663_test_offset_M6.brep] s
+
+set OffsetValue 80.0
+
+# Reference data.
+set ExpectedMass 2.06441e+006
+set ExpectedMaxTol 2.81
\ No newline at end of file
diff --git a/tests/offset/simple/B14 b/tests/offset/simple/B14
new file mode 100644 (file)
index 0000000..ac8e883
--- /dev/null
@@ -0,0 +1,9 @@
+# Test data:
+puts "USER GUID: N/A"
+restore [locate_data_file bug26663_test_offset_M9.brep] s
+
+set OffsetValue 80.0
+
+# Reference data.
+set ExpectedMass 2.82486e+007
+set ExpectedMaxTol 1.573
\ No newline at end of file
diff --git a/tests/offset/simple/B15 b/tests/offset/simple/B15
new file mode 100644 (file)
index 0000000..d9d843a
--- /dev/null
@@ -0,0 +1,9 @@
+# Test data:
+puts "USER GUID: N/A"
+restore [locate_data_file bug26663_test_offset_N7.brep] s
+
+set OffsetValue 80.0
+
+# Reference data.
+set ExpectedMass 2.12726e+007
+set ExpectedMaxTol 1.621
\ No newline at end of file
diff --git a/tests/offset/simple/C01 b/tests/offset/simple/C01
new file mode 100644 (file)
index 0000000..a5e23df
--- /dev/null
@@ -0,0 +1,9 @@
+# Test data:
+puts "USER GUID: N/A"
+restore [locate_data_file bug26663_test_offset_M8.brep] s
+
+set OffsetValue 100.0
+
+# Reference data.
+set ExpectedMass 1.26285e+007
+set ExpectedMaxTol 1.862
diff --git a/tests/offset/simple/C02 b/tests/offset/simple/C02
new file mode 100644 (file)
index 0000000..0b2ed9c
--- /dev/null
@@ -0,0 +1,9 @@
+# Test data:
+puts "USER GUID: N/A"
+restore [locate_data_file bug26578_test_offset_plate2.brep] s
+
+set OffsetValue -30.0
+
+# Reference data.
+set ExpectedMass 6.3874e+006
+set ExpectedMaxTol 26.338
\ No newline at end of file
diff --git a/tests/offset/simple/C03 b/tests/offset/simple/C03
new file mode 100644 (file)
index 0000000..90aedfc
--- /dev/null
@@ -0,0 +1,9 @@
+# Test data:
+puts "USER GUID: N/A"
+restore [locate_data_file bug26663_test_offset_C4.brep] s
+
+set OffsetValue 4.0
+
+# Reference data.
+set ExpectedMass 2.98155e+007
+set ExpectedMaxTol 1.636
diff --git a/tests/offset/simple/C04 b/tests/offset/simple/C04
new file mode 100644 (file)
index 0000000..525bb32
--- /dev/null
@@ -0,0 +1,9 @@
+# Test data:
+puts "USER GUID: N/A"
+restore [locate_data_file bug26663_test_offset_G4.brep] s
+
+set OffsetValue 2.0
+
+# Reference data.
+set ExpectedMass 2.3543e+006
+set ExpectedMaxTol 0.883
diff --git a/tests/offset/simple/C05 b/tests/offset/simple/C05
new file mode 100644 (file)
index 0000000..a5b6292
--- /dev/null
@@ -0,0 +1,9 @@
+# Test data:
+puts "USER GUID: N/A"
+restore [locate_data_file bug26663_test_offset_I5.brep] s
+
+set OffsetValue 2.0
+
+# Reference data.
+set ExpectedMass 3.91552e+007
+set ExpectedMaxTol 0.808
diff --git a/tests/offset/simple/C06 b/tests/offset/simple/C06
new file mode 100644 (file)
index 0000000..d90e17f
--- /dev/null
@@ -0,0 +1,9 @@
+# Test data:
+puts "USER GUID: N/A"
+restore [locate_data_file bug26578_test_offset_plate6.brep] s
+
+set OffsetValue 60.0
+
+# Reference data.
+set ExpectedMass 2.31634e+007
+set ExpectedMaxTol 2.351
diff --git a/tests/offset/simple/C07 b/tests/offset/simple/C07
new file mode 100644 (file)
index 0000000..eccbd28
--- /dev/null
@@ -0,0 +1,9 @@
+# Test data:
+puts "USER GUID: N/A"
+restore [locate_data_file bug26663_test_offset_L3.brep] s
+
+set OffsetValue 20.0
+
+# Reference data.
+set ExpectedMass 2.02449e+007
+set ExpectedMaxTol 1.994
\ No newline at end of file
diff --git a/tests/offset/simple/C08 b/tests/offset/simple/C08
new file mode 100644 (file)
index 0000000..6bb3d41
--- /dev/null
@@ -0,0 +1,9 @@
+# Test data:
+puts "USER GUID: N/A"
+restore [locate_data_file bug26663_test_offset_L9.brep] s
+
+set OffsetValue 20.0
+
+# Reference data.
+set ExpectedMass 2.02449e+007
+set ExpectedMaxTol 1.994
\ No newline at end of file
diff --git a/tests/offset/simple/C09 b/tests/offset/simple/C09
new file mode 100644 (file)
index 0000000..3d4a34c
--- /dev/null
@@ -0,0 +1,9 @@
+# Test data:
+puts "USER GUID: N/A"
+restore [locate_data_file bug26663_test_offset_J9.brep] s
+
+set OffsetValue 80.0
+
+# Reference data.
+set ExpectedMass 3.54341e+006
+set ExpectedMaxTol 86.160
\ No newline at end of file
diff --git a/tests/offset/simple/C10 b/tests/offset/simple/C10
new file mode 100644 (file)
index 0000000..e219acc
--- /dev/null
@@ -0,0 +1,9 @@
+# Test data:
+puts "USER GUID: N/A"
+restore [locate_data_file bug26663_test_offset_K8.brep] s
+
+set OffsetValue 80.0
+
+# Reference data.
+set ExpectedMass 1.63567e+006
+set ExpectedMaxTol 6.937
\ No newline at end of file
diff --git a/tests/offset/simple/C11 b/tests/offset/simple/C11
new file mode 100644 (file)
index 0000000..e82d739
--- /dev/null
@@ -0,0 +1,9 @@
+# Test data:
+puts "USER GUID: N/A"
+restore [locate_data_file bug26663_test_offset_L1.brep] s
+
+set OffsetValue 80.0
+
+# Reference data.
+set ExpectedMass 1.26556e+007
+set ExpectedMaxTol 1.490
\ No newline at end of file
diff --git a/tests/offset/simple/C12 b/tests/offset/simple/C12
new file mode 100644 (file)
index 0000000..1730013
--- /dev/null
@@ -0,0 +1,9 @@
+# Test data:
+puts "USER GUID: N/A"
+restore [locate_data_file bug26663_test_offset_M3.brep] s
+
+set OffsetValue 80.0
+
+# Reference data.
+set ExpectedMass 3.15379e+006
+set ExpectedMaxTol 1.519
\ No newline at end of file
diff --git a/tests/offset/simple/C13 b/tests/offset/simple/C13
new file mode 100644 (file)
index 0000000..c9d1053
--- /dev/null
@@ -0,0 +1,9 @@
+# Test data:
+puts "USER GUID: N/A"
+restore [locate_data_file bug26663_test_offset_M5.brep] s
+
+set OffsetValue 80.0
+
+# Reference data.
+set ExpectedMass 8.64266e+006
+set ExpectedMaxTol 3.569
\ No newline at end of file
diff --git a/tests/offset/simple/C14 b/tests/offset/simple/C14
new file mode 100644 (file)
index 0000000..e8a2a52
--- /dev/null
@@ -0,0 +1,9 @@
+# Test data:
+puts "USER GUID: N/A"
+restore [locate_data_file bug26663_test_offset_M8.brep] s
+
+set OffsetValue 80.0
+
+# Reference data.
+set ExpectedMass 1.26552e+007
+set ExpectedMaxTol 1.490
\ No newline at end of file
diff --git a/tests/offset/simple/C15 b/tests/offset/simple/C15
new file mode 100644 (file)
index 0000000..992aa87
--- /dev/null
@@ -0,0 +1,9 @@
+# Test data:
+puts "USER GUID: N/A"
+restore [locate_data_file bug26663_test_offset_N1.brep] s
+
+set OffsetValue 80.0
+
+# Reference data.
+set ExpectedMass 2.27708e+007
+set ExpectedMaxTol 3.143
\ No newline at end of file
diff --git a/tests/offset/simple/D01 b/tests/offset/simple/D01
new file mode 100644 (file)
index 0000000..83b10b7
--- /dev/null
@@ -0,0 +1,9 @@
+# Test data:
+puts "USER GUID: N/A"
+restore [locate_data_file bug26587_plate.brep] s
+
+set OffsetValue 50.0
+
+# Reference data.
+set ExpectedMass 984797
+set ExpectedMaxTol 32.317
diff --git a/tests/offset/simple/D02 b/tests/offset/simple/D02
new file mode 100644 (file)
index 0000000..15cdd99
--- /dev/null
@@ -0,0 +1,9 @@
+# Test data:
+puts "USER GUID: HA-1901"
+restore [locate_data_file bug27907_2.brep] s
+
+set OffsetValue 10.0
+
+# Reference data.
+set ExpectedMass 1.5967e+007
+set ExpectedMaxTol 0.10549
diff --git a/tests/offset/simple/D03 b/tests/offset/simple/D03
new file mode 100644 (file)
index 0000000..be241e1
--- /dev/null
@@ -0,0 +1,9 @@
+# Test data:
+puts "USER GUID: A88BBB2B-89EE-496B-8C35-5B2AB9808EBD"
+restore [locate_data_file bug27908.brep] s
+
+set OffsetValue 10.0
+
+# Reference data.
+set ExpectedMass 178976
+set ExpectedMaxTol 0.479111
diff --git a/tests/offset/simple/D04 b/tests/offset/simple/D04
new file mode 100644 (file)
index 0000000..480f391
--- /dev/null
@@ -0,0 +1,9 @@
+# Test data:
+puts "USER GUID: BDC7375D-EFDD-48A4-942B-2B5ECA4E48DB"
+restore [locate_data_file bug27909.brep] s
+
+set OffsetValue 10.0
+
+# Reference data.
+set ExpectedMass 368902
+set ExpectedMaxTol 0.49793
diff --git a/tests/offset/simple/D05 b/tests/offset/simple/D05
new file mode 100644 (file)
index 0000000..11aef39
--- /dev/null
@@ -0,0 +1,9 @@
+# Test data:
+puts "USER GUID: C779BA35-596C-4E12-96DF-53D4F6CD32D2"
+restore [locate_data_file bug27910.brep] s
+
+set OffsetValue 10.0
+
+# Reference data.
+set ExpectedMass 386834
+set ExpectedMaxTol 0.037686
diff --git a/tests/offset/simple/D06 b/tests/offset/simple/D06
new file mode 100644 (file)
index 0000000..1ec90c2
--- /dev/null
@@ -0,0 +1,9 @@
+# Test data:
+puts "USER GUID: E45BCDC8-7222-4751-A15D-C2865BE26158"
+restore [locate_data_file bug27911.brep] s
+
+set OffsetValue 10.0
+
+# Reference data.
+set ExpectedMass 109689
+set ExpectedMaxTol 0.043343
diff --git a/tests/offset/simple/D07 b/tests/offset/simple/D07
new file mode 100644 (file)
index 0000000..209c0aa
--- /dev/null
@@ -0,0 +1,9 @@
+# Test data:
+puts "USER GUID: HA-2023"
+restore [locate_data_file bug27913.brep] s
+
+set OffsetValue 10.0
+
+# Reference data.
+set ExpectedMass 5.28198e+006
+set ExpectedMaxTol 2.6431
diff --git a/tests/offset/simple/E01 b/tests/offset/simple/E01
new file mode 100644 (file)
index 0000000..94aba71
--- /dev/null
@@ -0,0 +1,9 @@
+# Test data:
+puts "USER GUID: 28561742-E228-487D-9D66-C602A2065885"
+restore [locate_data_file bug27954_E01.brep] s
+
+set OffsetValue 10.0
+
+# Reference data.
+set ExpectedMass 6.25923e+006
+set ExpectedMaxTol 0.05005
diff --git a/tests/offset/simple/E02 b/tests/offset/simple/E02
new file mode 100644 (file)
index 0000000..3628ae5
--- /dev/null
@@ -0,0 +1,9 @@
+# Test data:
+puts "USER GUID: 4831349C-7F37-4177-9ACD-14A12115B2EF"
+restore [locate_data_file bug27954_E02.brep] s
+
+set OffsetValue 10.0
+
+# Reference data.
+set ExpectedMass 1.79498e+006
+set ExpectedMaxTol 0.01254
diff --git a/tests/offset/simple/E03 b/tests/offset/simple/E03
new file mode 100644 (file)
index 0000000..f47cbde
--- /dev/null
@@ -0,0 +1,9 @@
+# Test data:
+puts "USER GUID: A01DD63B-C1FD-439D-9BF5-11905AF9C009"
+restore [locate_data_file bug27954_E03.brep] s
+
+set OffsetValue 10.0
+
+# Reference data.
+set ExpectedMass 1.89284e+006
+set ExpectedMaxTol 0.052422
diff --git a/tests/offset/simple/E04 b/tests/offset/simple/E04
new file mode 100644 (file)
index 0000000..2ba9db9
--- /dev/null
@@ -0,0 +1,9 @@
+# Test data:
+puts "USER GUID: BDCB0224-144F-4392-9229-19029AEBF346"
+restore [locate_data_file bug27954_E04.brep] s
+
+set OffsetValue 10.0
+
+# Reference data.
+set ExpectedMass 2.55458e+006
+set ExpectedMaxTol 6.47469
diff --git a/tests/offset/simple/E05 b/tests/offset/simple/E05
new file mode 100644 (file)
index 0000000..23910fd
--- /dev/null
@@ -0,0 +1,9 @@
+# Test data:
+puts "USER GUID: F6C5F855-E079-4024-A864-3DB9332003DB"
+restore [locate_data_file bug27954_E05.brep] s
+
+set OffsetValue 10.0
+
+# Reference data.
+set ExpectedMass 1.10984e+006
+set ExpectedMaxTol 0.05005
diff --git a/tests/offset/simple/E06 b/tests/offset/simple/E06
new file mode 100644 (file)
index 0000000..0937eab
--- /dev/null
@@ -0,0 +1,9 @@
+# Test data:
+puts "USER GUID: 04A16521-038C-4639-851C-A7933BDDE511"
+restore [locate_data_file bug27954_E06.brep] s
+
+set OffsetValue 10.0
+
+# Reference data.
+set ExpectedMass 2.59283e+006
+set ExpectedMaxTol 1.0801
\ No newline at end of file
diff --git a/tests/offset/simple/E07 b/tests/offset/simple/E07
new file mode 100644 (file)
index 0000000..1c7505d
--- /dev/null
@@ -0,0 +1,9 @@
+# Test data:
+puts "USER GUID: 38F3B4F3-7482-4FD9-9082-78EE260ECB9C"
+restore [locate_data_file bug27954_E07.brep] s
+
+set OffsetValue 10.0
+
+# Reference data.
+set ExpectedMass 2.20979e+007
+set ExpectedMaxTol 0.14277
diff --git a/tests/offset/simple/E08 b/tests/offset/simple/E08
new file mode 100644 (file)
index 0000000..d748348
--- /dev/null
@@ -0,0 +1,9 @@
+# Test data:
+puts "USER GUID: 20E0D114-29C3-46E1-9D69-35289E0C8C9D"
+restore [locate_data_file bug27954_E08.brep] s
+
+set OffsetValue 10.0
+
+# Reference data.
+set ExpectedMass 6.78711e+006
+set ExpectedMaxTol 9.6347
diff --git a/tests/offset/simple/E09 b/tests/offset/simple/E09
new file mode 100644 (file)
index 0000000..955e5a6
--- /dev/null
@@ -0,0 +1,9 @@
+# Test data:
+puts "USER GUID: 4147D9F2-0F3C-47D7-A877-738703334311"
+restore [locate_data_file bug27954_E09.brep] s
+
+set OffsetValue 10.0
+
+# Reference data.
+set ExpectedMass 3.09695e+006
+set ExpectedMaxTol 10.1039
diff --git a/tests/offset/simple/E10 b/tests/offset/simple/E10
new file mode 100644 (file)
index 0000000..bf09a51
--- /dev/null
@@ -0,0 +1,9 @@
+# Test data:
+puts "USER GUID: DEAB5074-6068-490B-9CE9-9EA0145004E6"
+restore [locate_data_file bug27954_E10.brep] s
+
+set OffsetValue 12.0
+
+# Reference data.
+set ExpectedMass 3.14161e+006
+set ExpectedMaxTol 9.7758551227229384e-005
diff --git a/tests/offset/simple/E11 b/tests/offset/simple/E11
new file mode 100644 (file)
index 0000000..86311eb
--- /dev/null
@@ -0,0 +1,9 @@
+# Test data:
+puts "USER GUID: EF75D6C4-4A1F-4A2C-A705-D645503B71FF"
+restore [locate_data_file bug27954_E11.brep] s
+
+set OffsetValue 12.0
+
+# Reference data.
+set ExpectedMass 502659
+set ExpectedMaxTol 9.7753906249999995e-005
diff --git a/tests/offset/simple/E12 b/tests/offset/simple/E12
new file mode 100644 (file)
index 0000000..cf6ad3c
--- /dev/null
@@ -0,0 +1,9 @@
+# Test data:
+puts "USER GUID: 3DAF015F-C558-453C-ABD9-2D27F4202C54"
+restore [locate_data_file bug27954_E12.brep] s
+
+set OffsetValue 15.0
+
+# Reference data.
+set ExpectedMass 3.30002e+006
+set ExpectedMaxTol 6.688170
diff --git a/tests/offset/simple/E13 b/tests/offset/simple/E13
new file mode 100644 (file)
index 0000000..af6c619
--- /dev/null
@@ -0,0 +1,9 @@
+# Test data:
+puts "USER GUID: 26033800-3BA7-4E42-8EBE-7ABF24F5B8CD"
+restore [locate_data_file bug27954_E13.brep] s
+
+set OffsetValue 15.0
+
+# Reference data.
+set ExpectedMass 6.97008e+006
+set ExpectedMaxTol 0.05445
diff --git a/tests/offset/simple/E14 b/tests/offset/simple/E14
new file mode 100644 (file)
index 0000000..8dfeadf
--- /dev/null
@@ -0,0 +1,9 @@
+# Test data:
+puts "USER GUID: D9640BFE-FE1D-4CE6-8099-792B3576EE2B"
+restore [locate_data_file bug27954_E14.brep] s
+
+set OffsetValue 10.5
+
+# Reference data.
+set ExpectedMass 3.15565e+006
+set ExpectedMaxTol 4.72124
diff --git a/tests/offset/simple/E15 b/tests/offset/simple/E15
new file mode 100644 (file)
index 0000000..549e461
--- /dev/null
@@ -0,0 +1,9 @@
+# Test data:
+puts "USER GUID: 1F354708-BED2-49BE-9EFC-CFB80F35B632"
+restore [locate_data_file bug27954_E15.brep] s
+
+set OffsetValue 15.0
+
+# Reference data.
+set ExpectedMass 5.62613e+006
+set ExpectedMaxTol 13.7670
diff --git a/tests/offset/simple/E16 b/tests/offset/simple/E16
new file mode 100644 (file)
index 0000000..69e3ee0
--- /dev/null
@@ -0,0 +1,9 @@
+# Test data:
+puts "USER GUID: 17FD83B1-187D-4BAE-95CC-18F4286BC305"
+restore [locate_data_file bug27954_E16.brep] s
+
+set OffsetValue 15.0
+
+# Reference data.
+set ExpectedMass 3.02779e+006
+set ExpectedMaxTol 14.1629
diff --git a/tests/offset/simple/E17 b/tests/offset/simple/E17
new file mode 100644 (file)
index 0000000..6485f17
--- /dev/null
@@ -0,0 +1,9 @@
+# Test data:
+puts "USER GUID: 4272E662-E79A-4109-898A-ACDFF729A027"
+restore [locate_data_file bug27954_E17.brep] s
+
+set OffsetValue 15.0
+
+# Reference data.
+set ExpectedMass 1.07145e+006
+set ExpectedMaxTol 14.103
diff --git a/tests/offset/simple/E18 b/tests/offset/simple/E18
new file mode 100644 (file)
index 0000000..2bdb3c6
--- /dev/null
@@ -0,0 +1,9 @@
+# Test data:
+puts "USER GUID: AA9E9570-12E5-46C5-B949-C012D3CC0648"
+restore [locate_data_file bug27954_E18.brep] s
+
+set OffsetValue 15.0
+
+# Reference data.
+set ExpectedMass 1.5982e+007
+set ExpectedMaxTol 13.7670
diff --git a/tests/offset/simple/E19 b/tests/offset/simple/E19
new file mode 100644 (file)
index 0000000..dfe0411
--- /dev/null
@@ -0,0 +1,9 @@
+# Test data:
+puts "USER GUID: HA-2498"
+restore [locate_data_file bug27954_E19.brep] s
+
+set OffsetValue 15.0
+
+# Reference data.
+set ExpectedMass 3.65525e+007
+set ExpectedMaxTol 0.105926
diff --git a/tests/offset/simple/E20 b/tests/offset/simple/E20
new file mode 100644 (file)
index 0000000..a3ec142
--- /dev/null
@@ -0,0 +1,9 @@
+# Test data:
+puts "USER GUID: HA-2502"
+restore [locate_data_file bug27954_E20.brep] s
+
+set OffsetValue 15.0
+
+# Reference data.
+set ExpectedMass 7.35034e+006
+set ExpectedMaxTol 35.6647
diff --git a/tests/offset/simple/begin b/tests/offset/simple/begin
new file mode 100644 (file)
index 0000000..fd3b5f7
--- /dev/null
@@ -0,0 +1,8 @@
+pload MODELING VISUALIZATION
+cpulimit 100
+
+# "A" letter 26528
+# "B" letter 26577
+# "C" letter 26578
+# "D" letter 26587, 27907, 27908, 27909, 27910, 27911, 27912, 27913
+# "E" letter SPE 2016_Oct pack
\ No newline at end of file
diff --git a/tests/offset/simple/end b/tests/offset/simple/end
new file mode 100644 (file)
index 0000000..4bd90b9
--- /dev/null
@@ -0,0 +1,20 @@
+# Compute offset.
+offsetshapesimple result s $OffsetValue
+
+# 1% relative tolerance
+set TolRel 1.0e-2
+
+# Check result validity.
+checkshape result
+
+# Check result area.
+checkprops result -s $ExpectedMass -eps $TolRel
+
+# Check maximal tolerance
+checkmaxtol result -ref $ExpectedMaxTol
+
+# Make screenshot.
+smallview
+don result
+fit
+checkview -screenshot -2d -path ${imagedir}/${test_image}.png
\ No newline at end of file