1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-08-14 13:30:48 +03:00

Initial implementation of the new offset algorithm.

Initial implementation of the solid creation mode for the new offset creation algorithm.
This commit is contained in:
aml
2016-11-01 13:54:05 +03:00
parent 3b5f0ca372
commit f99f17ab1d
6 changed files with 1399 additions and 0 deletions

View File

@@ -0,0 +1,587 @@
// 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(const TopoDS_Shape& theInputShape,
const Standard_Real theOffsetValue)
: myInputShape(theInputShape),
myOffsetValue(theOffsetValue),
myIsBuildSolid(Standard_False),
myMaxAngle(0.0),
myError(BRepOffsetSimple_OK),
myIsDone(Standard_False)
{
}
//=============================================================================
//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();
}
//=============================================================================
//function : GetSafeOffset
//purpose :
//=============================================================================
Standard_Real BRepOffset_MakeSimpleOffset::GetSafeOffset(const Standard_Real theExpectedToler)
{
// Compute max angle in faces junctions.
if (myMaxAngle == 0.0) // Non-initialized.
ComputeMaxAngle();
const Standard_Real anExpOffset = theExpectedToler / (2.0 * myMaxAngle);
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();
Handle(BRepOffset_SimpleOffset) aBuilder = new BRepOffset_SimpleOffset(myInputShape, myOffsetValue);
BRepTools_Modifier aModifier(myInputShape, aBuilder);
if (!aModifier.IsDone())
{
myError = BRepOffsetSimple_ErrorOffsetComputation;
return;
}
myResShape = aModifier.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(aModifier.ModifiedShape(aCurrEdge));
aBB.Degenerated(anEdge, Standard_True);
}
// Restore walls for solid.
if (myIsBuildSolid && !BuildMissingWalls(aModifier))
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);
Handle(BRepAdaptor_HCurve2d) HC2d1 = new BRepAdaptor_HCurve2d();
HC2d1->ChangeCurve2d().Initialize(E,F1);
if(couture) E.Orientation(TopAbs_REVERSED);
Handle(BRepAdaptor_HCurve2d) HC2d2 = new BRepAdaptor_HCurve2d();
HC2d2->ChangeCurve2d().Initialize(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
HC2d1->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();
HC2d2->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(const BRepTools_Modifier& theModifier)
{
// Internal list of new faces.
NCollection_List<TopoDS_Face> aListOfNewFaces;
BRep_Builder aBB;
// 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(theModifier, aCurEdge);
if (aNewFace.IsNull())
{
myError = BRepOffsetSimple_ErrorWallFaceComputation;
return Standard_False;
}
aListOfNewFaces.Append(aNewFace);
}
}
// Update result to be compound.
TopoDS_Compound aResCompound;
aBB.MakeCompound(aResCompound);
// Add old faces.
TopExp_Explorer anExpSF(myInputShape, TopAbs_FACE);
for ( ; anExpSF.More() ; anExpSF.Next())
aBB.Add(aResCompound, anExpSF.Current());
// Add new faces.
anExpSF.Init(myResShape, TopAbs_FACE);
for ( ; anExpSF.More() ; anExpSF.Next())
aBB.Add(aResCompound, anExpSF.Current());
// Add wall faces.
NCollection_List<TopoDS_Face>::Iterator anIterF(aListOfNewFaces);
for ( ; anIterF.More() ; anIterF.Next())
{
const TopoDS_Face& aF = anIterF.Value();
aBB.Add(aResCompound, aF);
}
// 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 BRepTools_Modifier& theModifier,
const TopoDS_Edge& theOrigEdge)
{
TopoDS_Face aResFace;
// Get offset edge. offset edge is revered to create correct wire.
TopoDS_Edge aNewEdge = TopoDS::Edge(theModifier.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);
}
// Fix same parameter and same range flags.
ShapeFix_Edge aSFE;
TopExp_Explorer anExpFE(aF, TopAbs_EDGE);
for ( ; anExpFE.More() ; anExpFE.Next())
{
const TopoDS_Edge& aCurrEdge = TopoDS::Edge(anExpFE.Current());
aSFE.FixSameParameter(aCurrEdge);
//aSFE.FixSameParameter(aCurrEdge, aF);
}
return aF;
}

View File

@@ -0,0 +1,143 @@
// 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 <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>
class BRepTools_Modifier;
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.
class BRepOffset_MakeSimpleOffset
{
public:
//! Constructor.
Standard_EXPORT BRepOffset_MakeSimpleOffset(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.
const BRepOffsetSimple_Status GetError() const { return myError; }
// Inline methods.
//! Gets solid building flag.
const Standard_Boolean GetBuildSolidFlag() const { return myIsBuildSolid; }
//! Sets solid building flag.
void SetBuildSolidFlag(const Standard_Boolean theBuildFlag) { myIsBuildSolid = theBuildFlag; }
//! Gets offset value.
const Standard_Real GetOffsetValue() const { return myOffsetValue; }
//! Sets offset value.
void SetOffsetValue(const Standard_Real theOffsetValue) { myOffsetValue = theOffsetValue; }
//! Gets done state.
const 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);
protected:
//! Computes max angle in faces junction.
void ComputeMaxAngle();
//! Clears previous result.
void Clear();
private:
//! Builds face on specified wall.
TopoDS_Face BuildWallFace(const BRepTools_Modifier& theModifier,
const TopoDS_Edge& theOrigEdge);
//! Builds missing walls.
Standard_Boolean BuildMissingWalls(const BRepTools_Modifier& theModifier);
// 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;
// Output data.
//! Result shape.
TopoDS_Shape myResShape;
};
#endif // _BRepOffset_MakeSimpleOffset_HeaderFile

View File

@@ -0,0 +1,438 @@
// 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>
#include <TopTools_ListIteratorOfListOfShape.hxx>
static const Standard_Integer NCONTROL=22;
IMPLEMENT_STANDARD_RTTIEXT(BRepOffset_SimpleOffset, BRepTools_Modification)
//=============================================================================
//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(TopoDS::Face(F.Oriented(TopAbs_FORWARD))) &&
!myFaceInfo.IsBound(TopoDS::Face(F.Oriented(TopAbs_REVERSED))))
return Standard_False;
NewFaceData aNFD;
if (myFaceInfo.IsBound(TopoDS::Face(F.Oriented(TopAbs_FORWARD))))
aNFD = myFaceInfo.Find(TopoDS::Face(F.Oriented(TopAbs_FORWARD)));
if (myFaceInfo.IsBound(TopoDS::Face(F.Oriented(TopAbs_REVERSED))))
aNFD = myFaceInfo.Find(TopoDS::Face(F.Oriented(TopAbs_REVERSED)));
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(TopoDS::Edge(E.Oriented(TopAbs_FORWARD))) &&
!myEdgeInfo.IsBound(TopoDS::Edge(E.Oriented(TopAbs_REVERSED))))
return Standard_False;
NewEdgeData aNED;
if (myEdgeInfo.IsBound(TopoDS::Edge(E.Oriented(TopAbs_FORWARD))))
aNED = myEdgeInfo.Find(TopoDS::Edge(E.Oriented(TopAbs_FORWARD)));
if (myEdgeInfo.IsBound(TopoDS::Edge(E.Oriented(TopAbs_REVERSED))))
aNED = myEdgeInfo.Find(TopoDS::Edge(E.Oriented(TopAbs_REVERSED)));
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(TopoDS::Vertex(V.Oriented(TopAbs_FORWARD))) &&
!myVertexInfo.IsBound(TopoDS::Vertex(V.Oriented(TopAbs_REVERSED))))
return Standard_False;
NewVertexData aNVD;
if (myVertexInfo.IsBound(TopoDS::Vertex(V.Oriented(TopAbs_FORWARD))))
aNVD = myVertexInfo.Find(TopoDS::Vertex(V.Oriented(TopAbs_FORWARD)));
if (myVertexInfo.IsBound(TopoDS::Vertex(V.Oriented(TopAbs_REVERSED))))
aNVD = myVertexInfo.Find(TopoDS::Vertex(V.Oriented(TopAbs_REVERSED)));
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.Extent(); ++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.Extent(); ++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.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;
aNFD.myRevFace = Standard_False;
if (theFace.Orientation() == TopAbs_REVERSED)
{
aNFD.myRevFace = Standard_True;
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.Extent() == 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.
TopoDS_Vertex aV1, aV2;
TopExp::Vertices(theEdge, aV1, aV2);
Standard_Real aTol = Max(BRep_Tool::Tolerance(aV1),
BRep_Tool::Tolerance(aV2));
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_ListIteratorOfListOfShape 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.Extent() == 0)
return; // Free vertices are skipped.
// Array to store offset points.
NCollection_Vector<gp_Pnt> anOffsetPointVec;
Standard_Real aMaxEdgeTol = 0.0;
// Iterate over adjacent edges.
TopTools_ListIteratorOfListOfShape 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 tolerance problems.
NewVertexData aNVD;
aNVD.myP = aCenter;
aNVD.myTol = aResTol * aMultCoeff;
// Save computed vertex info.
myVertexInfo.Bind(theVertex, aNVD);
}

View File

@@ -0,0 +1,177 @@
// 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 without intersection.
class BRepOffset_SimpleOffset : public BRepTools_Modification
{
public:
DEFINE_STANDARD_RTTI(BRepOffset_SimpleOffset)
//! 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 contsructor 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;
//! Ofsset value.
Standard_Real myOffsetValue;
};
#endif // _BRepOffset_SimpleOffset_HeaderFile

4
src/BRepOffset/FILES Normal file
View File

@@ -0,0 +1,4 @@
BRepOffset_MakeSimpleOffset.cxx
BRepOffset_MakeSimpleOffset.hxx
BRepOffset_SimpleOffset.cxx
BRepOffset_SimpleOffset.hxx

View File

@@ -54,6 +54,7 @@
#include <LocOpe_FindEdges.hxx>
#include <LocOpe_FindEdgesInFace.hxx>
#include <BRepOffset_MakeSimpleOffset.hxx>
#include <BRepOffsetAPI_MakeOffsetShape.hxx>
#include <BRepOffsetAPI_MakeThickSolid.hxx>
#include <BRep_Tool.hxx>
@@ -2241,6 +2242,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)
{
theCommands << "offsetshapesimple result shape offsetvalue \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
@@ -2393,4 +2440,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);
}