Modeling Algorithms - Enhance fillet and chamfer handling. Part 2 (#1449)

- Detect complete coincidence between fillet and chamfer intersection curves.
- Preserve orientation relationships between equivalent intersection curves.
- Reuse existing restriction edges instead of constructing duplicate topology.
- Merge coincident curve endpoints into shared topological vertices.
- Exclude fully consumed faces and their obsolete boundary edges during reconstruction.
- Mark edges collapsed to a single vertex as degenerated during construction.
- Accept tangential contacts while rejecting transversal intersections.
- Preserve generated and modified shape history in the resulting topology.
- Add GTests for convex, concave, opposing-edge, chamfer, and history cases.
This commit is contained in:
Pasukhin Dmitry
2026-08-09 15:16:27 +01:00
committed by GitHub
parent cbca11e975
commit f713b1305f
27 changed files with 1523 additions and 81 deletions
@@ -6,4 +6,5 @@ set(OCCT_TKBool_GTests_FILES
BRepAlgoAPI_Fuse_Test.cxx
BRepAlgoAPI_Section_Test.cxx
BRepFill_PipeShell_Test.cxx
TopOpeBRepDS_BuildTool_Test.cxx
)
@@ -0,0 +1,43 @@
// Copyright (c) 2026 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 <gtest/gtest.h>
#include <BRepBuilderAPI_MakeEdge.hxx>
#include <BRep_Tool.hxx>
#include <Geom_Circle.hxx>
#include <Precision.hxx>
#include <TopOpeBRepDS_BuildTool.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Edge.hxx>
#include <TopExp_Explorer.hxx>
TEST(TopOpeBRepDS_BuildToolTest, CopyReversedPeriodicEdgePreservesRange)
{
const occ::handle<Geom_Circle> aCircle = new Geom_Circle(gp_Ax2(), 1.0);
TopoDS_Edge aSource = BRepBuilderAPI_MakeEdge(aCircle);
aSource.Reverse();
TopOpeBRepDS_BuildTool aBuildTool;
TopoDS_Shape aCopy;
aBuildTool.CopyEdge(aSource, aCopy);
for (TopExp_Explorer aVertexIt(aSource, TopAbs_VERTEX); aVertexIt.More(); aVertexIt.Next())
{
aBuildTool.AddEdgeVertex(aSource, aCopy, aVertexIt.Current());
}
double aFirst, aLast;
BRep_Tool::Range(TopoDS::Edge(aCopy), aFirst, aLast);
EXPECT_NEAR(aFirst, aCircle->FirstParameter(), Precision::PConfusion());
EXPECT_NEAR(aLast, aCircle->LastParameter(), Precision::PConfusion());
}
@@ -15,9 +15,15 @@
// commercial license or contractual agreement.
#include <Standard_Integer.hxx>
#include <Geom2dAdaptor_Curve.hxx>
#include <Geom2dInt_GInter.hxx>
#include <IntRes2d_IntersectionSegment.hxx>
#include <NCollection_Array1.hxx>
#include <NCollection_HArray1.hxx>
#include <NCollection_LinearVector.hxx>
#include <Precision.hxx>
#include <TopoDS.hxx>
#include <TopExp_Explorer.hxx>
#include <TopoDS_Shape.hxx>
#include <TopOpeBRepBuild_define.hxx>
#include <TopOpeBRepBuild_EdgeBuilder.hxx>
@@ -29,10 +35,121 @@
#include <TopOpeBRepDS_HDataStructure.hxx>
#include <TopOpeBRepDS_PointIterator.hxx>
#include <algorithm>
#include <cmath>
#ifdef OCCT_DEBUG
extern bool TopOpeBRepBuild_GettraceCU();
#endif
namespace
{
struct TopOpeBRepBuild_SurfaceCurve
{
int Index;
occ::handle<Geom2d_Curve> PCurve;
double FirstParameter;
double LastParameter;
};
bool TopOpeBRepBuild_CurveRange(const TopOpeBRepDS_Curve& theCurve,
const occ::handle<Geom2d_Curve>& thePCurve,
double& theFirst,
double& theLast)
{
const auto isValidRange = [](const double theRangeFirst, const double theRangeLast) {
return theRangeFirst < theRangeLast && !Precision::IsInfinite(theRangeFirst)
&& !Precision::IsInfinite(theRangeLast);
};
if (theCurve.Range(theFirst, theLast) && isValidRange(theFirst, theLast))
{
return true;
}
if (!thePCurve.IsNull())
{
theFirst = thePCurve->FirstParameter();
theLast = thePCurve->LastParameter();
if (isValidRange(theFirst, theLast))
{
return true;
}
}
const occ::handle<Geom_Curve>& aCurve3d = theCurve.Curve();
if (!aCurve3d.IsNull())
{
theFirst = aCurve3d->FirstParameter();
theLast = aCurve3d->LastParameter();
return isValidRange(theFirst, theLast);
}
return false;
}
bool TopOpeBRepBuild_HasCompleteCoincidence(const Geom2dInt_GInter& theIntersector,
const Geom2dAdaptor_Curve& theFirstCurve,
const Geom2dAdaptor_Curve& theSecondCurve,
bool& theIsReversed)
{
if (theIntersector.NbSegments() != 1)
{
return false;
}
const IntRes2d_IntersectionSegment& aSegment = theIntersector.Segment(1);
if (!aSegment.HasFirstPoint() || !aSegment.HasLastPoint())
{
return false;
}
const double aFirstOnFirst = aSegment.FirstPoint().ParamOnFirst();
const double aLastOnFirst = aSegment.LastPoint().ParamOnFirst();
const double aFirstOnSecond = aSegment.FirstPoint().ParamOnSecond();
const double aLastOnSecond = aSegment.LastPoint().ParamOnSecond();
const double aTolerance = Precision::PConfusion();
const bool isComplete =
std::abs(std::min(aFirstOnFirst, aLastOnFirst) - theFirstCurve.FirstParameter()) <= aTolerance
&& std::abs(std::max(aFirstOnFirst, aLastOnFirst) - theFirstCurve.LastParameter()) <= aTolerance
&& std::abs(std::min(aFirstOnSecond, aLastOnSecond) - theSecondCurve.FirstParameter())
<= aTolerance
&& std::abs(std::max(aFirstOnSecond, aLastOnSecond) - theSecondCurve.LastParameter())
<= aTolerance;
if (isComplete)
{
theIsReversed = (aLastOnFirst - aFirstOnFirst) * (aLastOnSecond - aFirstOnSecond) < 0.0;
}
return isComplete;
}
bool TopOpeBRepBuild_FindCurveEnd(const occ::handle<TopOpeBRepDS_HDataStructure>& theHDS,
const int theCurveIndex,
const bool theCurveStart,
int& theGeometryIndex,
bool& theIsPoint)
{
double aFirst, aLast;
if (!TopOpeBRepBuild_CurveRange(theHDS->Curve(theCurveIndex), nullptr, aFirst, aLast))
{
return false;
}
const double aParameter = theCurveStart ? aFirst : aLast;
double aBestDistance = RealLast();
for (TopOpeBRepDS_PointIterator aPointIt(theHDS->CurvePoints(theCurveIndex)); aPointIt.More();
aPointIt.Next())
{
const double aDistance = std::abs(aPointIt.Parameter() - aParameter);
if (aDistance < aBestDistance)
{
aBestDistance = aDistance;
theGeometryIndex = aPointIt.Current();
theIsPoint = aPointIt.IsPoint();
}
}
return aBestDistance <= Precision::PConfusion();
}
} // namespace
//=================================================================================================
void TopOpeBRepBuild_Builder::BuildEdges(const int iC,
@@ -52,6 +169,36 @@ void TopOpeBRepBuild_Builder::BuildEdges(const int
return;
}
if (C.EquivalentCurve() > 0 && C.EquivalentCurve() != iC)
{
const int aReferenceCurve = C.EquivalentCurve();
if (NewEdges(aReferenceCurve).IsEmpty())
{
BuildEdges(aReferenceCurve, HDS);
}
ChangeNewEdges(iC) = NewEdges(aReferenceCurve);
return;
}
if (!C.ExistingEdge().IsNull())
{
if (!myCoincidentEdges.IsBound(C.ExistingEdge()))
{
TopoDS_Shape aCopiedEdge;
myBuildTool.CopyEdge(C.ExistingEdge(), aCopiedEdge);
for (TopExp_Explorer aVertexIt(C.ExistingEdge(), TopAbs_VERTEX); aVertexIt.More();
aVertexIt.Next())
{
myBuildTool.AddEdgeVertex(C.ExistingEdge(), aCopiedEdge, aVertexIt.Current());
}
myCoincidentEdges.Bind(C.ExistingEdge(), aCopiedEdge);
}
TopoDS_Shape anEdge = myCoincidentEdges(C.ExistingEdge());
anEdge.Orientation(TopAbs_FORWARD);
ChangeNewEdges(iC).Append(anEdge);
return;
}
TopoDS_Shape anEdge;
const TopOpeBRepDS_Curve& curC = HDS->Curve(iC);
myBuildTool.MakeEdge(anEdge, curC, HDS->DS());
@@ -106,8 +253,168 @@ void TopOpeBRepBuild_Builder::BuildEdges(const occ::handle<TopOpeBRepDS_HDataStr
TopOpeBRepDS_DataStructure& BDS = HDS->ChangeDS();
myNewEdges.Clear();
myCoincidentEdges.Clear();
TopOpeBRepDS_CurveExplorer cex;
NCollection_LinearVector<TopOpeBRepBuild_SurfaceCurve> aSurfaceCurves;
for (int aSurfaceIndex = 1; aSurfaceIndex <= HDS->NbSurfaces(); ++aSurfaceIndex)
{
aSurfaceCurves.Clear();
for (TopOpeBRepDS_CurveIterator aCurveIt(HDS->SurfaceCurves(aSurfaceIndex)); aCurveIt.More();
aCurveIt.Next())
{
const occ::handle<Geom2d_Curve>& aPCurve = aCurveIt.PCurve();
const TopOpeBRepDS_Curve& aCurve = HDS->Curve(aCurveIt.Current());
if (aPCurve.IsNull() || aCurve.Curve().IsNull())
{
continue;
}
double aFirst, aLast;
if (TopOpeBRepBuild_CurveRange(aCurve, aPCurve, aFirst, aLast))
{
aSurfaceCurves.Append({aCurveIt.Current(), aPCurve, aFirst, aLast});
}
}
for (size_t aFirstIndex = 0; aFirstIndex < aSurfaceCurves.Size(); ++aFirstIndex)
{
for (size_t aSecondIndex = aFirstIndex + 1; aSecondIndex < aSurfaceCurves.Size();
++aSecondIndex)
{
const TopOpeBRepBuild_SurfaceCurve& aFirst = aSurfaceCurves[aFirstIndex];
const TopOpeBRepBuild_SurfaceCurve& aSecond = aSurfaceCurves[aSecondIndex];
Geom2dAdaptor_Curve aFirstCurve(aFirst.PCurve, aFirst.FirstParameter, aFirst.LastParameter);
Geom2dAdaptor_Curve aSecondCurve(aSecond.PCurve,
aSecond.FirstParameter,
aSecond.LastParameter);
Geom2dInt_GInter anIntersector(aFirstCurve,
aSecondCurve,
Precision::PConfusion(),
Precision::PConfusion());
bool isReversed = false;
if (TopOpeBRepBuild_HasCompleteCoincidence(anIntersector,
aFirstCurve,
aSecondCurve,
isReversed))
{
BDS.MergeEquivalentCurves(aFirst.Index, aSecond.Index, isReversed);
}
}
}
}
for (cex.Init(BDS, false); cex.More(); cex.Next())
{
const int aCurveIndex = cex.Index();
if (cex.Curve().EquivalentCurve() <= 0)
{
continue;
}
bool isReversed = false;
const int aRoot = BDS.FindEquivalentCurve(aCurveIndex, isReversed);
BDS.ChangeCurve(aCurveIndex).SetEquivalentCurve(aRoot, isReversed);
}
NCollection_DataMap<int, TopoDS_Shape> anEquivalentPointVertices;
for (cex.Init(BDS, false); cex.More(); cex.Next())
{
const int aCurveIndex = cex.Index();
for (int anEnd = 0; anEnd < 2; ++anEnd)
{
const bool isCurveStart = (anEnd == 0);
bool isReferenceStart = false;
const int aReferenceCurve =
BDS.FindEquivalentCurvePoint(aCurveIndex, isCurveStart, isReferenceStart);
if (aReferenceCurve == aCurveIndex && isReferenceStart == isCurveStart)
{
continue;
}
const int aReference = 2 * aReferenceCurve + (isReferenceStart ? 0 : 1);
if (anEquivalentPointVertices.IsBound(aReference))
{
continue;
}
int aGeometryIndex = 0;
bool isPoint = false;
if (TopOpeBRepBuild_FindCurveEnd(HDS,
aReferenceCurve,
isReferenceStart,
aGeometryIndex,
isPoint))
{
anEquivalentPointVertices.Bind(aReference,
isPoint ? NewVertex(aGeometryIndex)
: HDS->Shape(aGeometryIndex));
}
}
}
for (cex.Init(BDS, false); cex.More(); cex.Next())
{
const int aCurveIndex = cex.Index();
for (int anEnd = 0; anEnd < 2; ++anEnd)
{
const bool isCurveStart = (anEnd == 0);
bool isReferenceStart = false;
const int aReferenceCurve =
BDS.FindEquivalentCurvePoint(aCurveIndex, isCurveStart, isReferenceStart);
const int aReference = 2 * aReferenceCurve + (isReferenceStart ? 0 : 1);
if (!anEquivalentPointVertices.IsBound(aReference))
{
continue;
}
int aGeometryIndex = 0;
bool isPoint = false;
if (TopOpeBRepBuild_FindCurveEnd(HDS, aCurveIndex, isCurveStart, aGeometryIndex, isPoint)
&& isPoint)
{
ChangeNewVertex(aGeometryIndex) = anEquivalentPointVertices(aReference);
}
}
}
for (cex.Init(BDS, false); cex.More(); cex.Next())
{
const int aCurveIndex = cex.Index();
const int aReferenceCurve = cex.Curve().EquivalentCurve();
if (aReferenceCurve <= 0 || aReferenceCurve == aCurveIndex)
{
continue;
}
for (TopOpeBRepDS_PointIterator aPointIt(HDS->CurvePoints(aCurveIndex)); aPointIt.More();
aPointIt.Next())
{
if (!aPointIt.IsPoint())
{
continue;
}
const int aPointIndex = aPointIt.Current();
const TopOpeBRepDS_Point& aPoint = HDS->Point(aPointIndex);
for (TopOpeBRepDS_PointIterator aReferencePointIt(HDS->CurvePoints(aReferenceCurve));
aReferencePointIt.More();
aReferencePointIt.Next())
{
if (!aReferencePointIt.IsPoint())
{
continue;
}
const int aReferencePointIndex = aReferencePointIt.Current();
const TopOpeBRepDS_Point& aReferencePoint = HDS->Point(aReferencePointIndex);
const double aTolerance = std::max(aPoint.Tolerance(), aReferencePoint.Tolerance());
if (aPoint.Point().Distance(aReferencePoint.Point()) <= aTolerance)
{
ChangeNewVertex(aPointIndex) = NewVertex(aReferencePointIndex);
break;
}
}
}
}
int ick = 0;
for (cex.Init(BDS, false); cex.More(); cex.Next())
{
@@ -16,6 +16,8 @@
#include <BRep_Builder.hxx>
#include <BRep_Tool.hxx>
#include <NCollection_FlatDataMap.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Shape.hxx>
#include <TopOpeBRepBuild_define.hxx>
#include <TopOpeBRepBuild_FaceBuilder.hxx>
@@ -53,7 +55,41 @@ void TopOpeBRepBuild_Builder::BuildFaces(const int
// myBuildTool.MakeFace(aFace,HDS->Surface(iS));
// modified by NIZNHY-PKV Mon Dec 13 10:01:03 2010t
//
TopOpeBRepBuild_WireEdgeSet WES(aFace, this);
TopOpeBRepBuild_WireEdgeSet WES(aFace, this);
NCollection_FlatDataMap<int, int> anEquivalentCurveOrientations;
for (TopOpeBRepDS_CurveIterator aCurveIt(HDS->SurfaceCurves(iS)); aCurveIt.More();
aCurveIt.Next())
{
const TopOpeBRepDS_Curve& aCurve = HDS->Curve(aCurveIt.Current());
const int aReferenceCurve = aCurve.EquivalentCurve();
if (aReferenceCurve > 0)
{
TopAbs_Orientation anOrientation = aCurveIt.Orientation(TopAbs_IN);
if (aCurve.IsEquivalentCurveReversed())
{
anOrientation = TopAbs::Reverse(anOrientation);
}
int anOrientationMask = anEquivalentCurveOrientations.IsBound(aReferenceCurve)
? anEquivalentCurveOrientations(aReferenceCurve)
: 0;
if (anOrientation == TopAbs_FORWARD)
{
anOrientationMask |= 1;
}
else if (anOrientation == TopAbs_REVERSED)
{
anOrientationMask |= 2;
}
if (anEquivalentCurveOrientations.IsBound(aReferenceCurve))
{
anEquivalentCurveOrientations.ChangeFind(aReferenceCurve) = anOrientationMask;
}
else
{
anEquivalentCurveOrientations.Bind(aReferenceCurve, anOrientationMask);
}
}
}
//
#ifdef OCCT_DEBUG
bool tSE = TopOpeBRepBuild_GettraceSPF();
@@ -62,8 +98,14 @@ void TopOpeBRepBuild_Builder::BuildFaces(const int
TopOpeBRepDS_CurveIterator SCurves(HDS->SurfaceCurves(iS));
for (; SCurves.More(); SCurves.Next())
{
int iC = SCurves.Current();
const TopOpeBRepDS_Curve& CDS = HDS->Curve(iC);
int iC = SCurves.Current();
const TopOpeBRepDS_Curve& CDS = HDS->Curve(iC);
const int aReferenceCurve = CDS.EquivalentCurve();
if (aReferenceCurve > 0 && anEquivalentCurveOrientations.IsBound(aReferenceCurve)
&& anEquivalentCurveOrientations(aReferenceCurve) == 3)
{
continue;
}
#ifdef OCCT_DEBUG
if (tSE)
std::cout << std::endl << "BuildFaces : C " << iC << " on S " << iS << std::endl;
@@ -82,6 +124,10 @@ void TopOpeBRepBuild_Builder::BuildFaces(const int
}
// modified by NIZNHY-PKV Mon Dec 13 10:09:43 2010f
TopAbs_Orientation ori = SCurves.Orientation(TopAbs_IN);
if (CDS.IsEquivalentCurveReversed())
{
ori = TopAbs::Reverse(ori);
}
myBuildTool.Orientation(anEdge, ori);
const occ::handle<Geom2d_Curve>& PC = SCurves.PCurve();
myBuildTool.PCurve(aFace, anEdge, CDS, PC);
@@ -22,6 +22,7 @@
#include <TopExp.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Edge.hxx>
#include <TopoDS_Iterator.hxx>
#include <TopoDS_Shape.hxx>
#include <TopoDS_Vertex.hxx>
#include <TopOpeBRepBuild_Builder.hxx>
@@ -36,10 +37,12 @@
#include <TopOpeBRepBuild_WireEdgeSet.hxx>
#include <TopOpeBRepDS_BuildTool.hxx>
#include <TopOpeBRepDS_Config.hxx>
#include <TopOpeBRepDS_CurveExplorer.hxx>
#include <TopOpeBRepDS_CurveIterator.hxx>
#include <TopOpeBRepDS_ListOfShapeOn1State.hxx>
#include <TopTools_ShapeMapHasher.hxx>
#include <NCollection_DataMap.hxx>
#include <NCollection_FlatDataMap.hxx>
#include <TopOpeBRepDS_Filter.hxx>
#include <TopOpeBRepDS_HDataStructure.hxx>
#include <TopOpeBRepDS_PointIterator.hxx>
@@ -75,6 +78,49 @@ static thread_local int STATIC_SOLIDINDEX = 0;
//=================================================================================================
static TopoDS_Shape SubstituteCoincidentEdges(
const TopoDS_Shape& theShape,
const NCollection_DataMap<TopoDS_Shape, TopoDS_Shape, TopTools_ShapeMapHasher>& theEdges,
const TopOpeBRepDS_BuildTool& theBuildTool)
{
if (theShape.ShapeType() != TopAbs_FACE && theShape.ShapeType() != TopAbs_WIRE)
{
return theShape;
}
TopoDS_Shape aCopy = theShape.EmptyCopied();
bool isModified = false;
for (TopoDS_Iterator anIt(theShape, false, false); anIt.More(); anIt.Next())
{
TopoDS_Shape aSubShape = anIt.Value();
if (aSubShape.ShapeType() == TopAbs_EDGE && theEdges.IsBound(aSubShape))
{
const TopAbs_Orientation anOrientation = aSubShape.Orientation();
aSubShape = theEdges(aSubShape);
aSubShape.Orientation(anOrientation);
isModified = true;
}
else if (aSubShape.ShapeType() == TopAbs_WIRE)
{
TopoDS_Shape aNewWire = SubstituteCoincidentEdges(aSubShape, theEdges, theBuildTool);
isModified = isModified || !aNewWire.IsSame(aSubShape);
aSubShape = aNewWire;
}
if (theShape.ShapeType() == TopAbs_FACE)
{
theBuildTool.AddFaceWire(aCopy, aSubShape);
}
else
{
theBuildTool.AddWireEdge(aCopy, aSubShape);
}
}
return isModified ? aCopy : theShape;
}
//=================================================================================================
TopOpeBRepBuild_Builder::TopOpeBRepBuild_Builder(const TopOpeBRepDS_BuildTool& BT)
: myBuildTool(BT),
mySectionDone(false),
@@ -114,6 +160,95 @@ occ::handle<TopOpeBRepDS_HDataStructure> TopOpeBRepBuild_Builder::DataStructure(
//=================================================================================================
static void FillEquivalentCurveOrientationMasks(
const TopoDS_Shape& theFace,
const TopAbs_State theState,
const bool theReverse,
const occ::handle<TopOpeBRepDS_HDataStructure>& theDataStructure,
NCollection_FlatDataMap<int, int>& theOrientationMasks)
{
for (TopOpeBRepDS_CurveIterator aCurveIt(theDataStructure->FaceCurves(theFace)); aCurveIt.More();
aCurveIt.Next())
{
const int aReferenceCurve = theDataStructure->Curve(aCurveIt.Current()).EquivalentCurve();
if (aReferenceCurve <= 0)
{
continue;
}
TopAbs_Orientation anOrientation =
TopOpeBRepBuild_Builder::Orient(aCurveIt.Orientation(theState), theReverse);
if (theDataStructure->Curve(aCurveIt.Current()).IsEquivalentCurveReversed())
{
anOrientation = TopAbs::Reverse(anOrientation);
}
int anOrientationMask =
theOrientationMasks.IsBound(aReferenceCurve) ? theOrientationMasks(aReferenceCurve) : 0;
if (anOrientation == TopAbs_FORWARD)
{
anOrientationMask |= 1;
}
else if (anOrientation == TopAbs_REVERSED)
{
anOrientationMask |= 2;
}
if (theOrientationMasks.IsBound(aReferenceCurve))
{
theOrientationMasks.ChangeFind(aReferenceCurve) = anOrientationMask;
}
else
{
theOrientationMasks.Bind(aReferenceCurve, anOrientationMask);
}
}
}
//=================================================================================================
static bool IsConsumedByCoincidentCurves(
const TopoDS_Shape& theFace,
const occ::handle<TopOpeBRepDS_HDataStructure>& theDataStructure)
{
for (int aStateIndex = 0; aStateIndex < 2; ++aStateIndex)
{
const TopAbs_State aState = aStateIndex == 0 ? TopAbs_IN : TopAbs_OUT;
NCollection_FlatDataMap<int, int> anOrientationMasks;
FillEquivalentCurveOrientationMasks(theFace,
aState,
false,
theDataStructure,
anOrientationMasks);
for (NCollection_FlatDataMap<int, int>::Iterator anIt(anOrientationMasks); anIt.More();
anIt.Next())
{
if (anIt.Value() == 3)
{
return true;
}
}
}
return false;
}
//=================================================================================================
static void RegisterConsumedFaceEdges(
const TopoDS_Shape& theFace,
const NCollection_DataMap<TopoDS_Shape, bool, TopTools_ShapeMapHasher>& theRestrictions,
NCollection_DataMap<TopoDS_Shape, bool, TopTools_ShapeMapHasher>& theConsumedEdges)
{
for (TopExp_Explorer anEdgeIt(theFace, TopAbs_EDGE); anEdgeIt.More(); anEdgeIt.Next())
{
const TopoDS_Shape& anEdge = anEdgeIt.Current();
if (!theRestrictions.IsBound(anEdge) && !theConsumedEdges.IsBound(anEdge))
{
theConsumedEdges.Bind(anEdge, true);
}
}
}
//=================================================================================================
void TopOpeBRepBuild_Builder::Perform(const occ::handle<TopOpeBRepDS_HDataStructure>& HDS)
{
#ifdef OCCT_DEBUG
@@ -124,6 +259,28 @@ void TopOpeBRepBuild_Builder::Perform(const occ::handle<TopOpeBRepDS_HDataStruct
BuildVertices(HDS);
SplitEvisoONperiodicF();
BuildEdges(HDS);
myConsumedFaces.Clear();
myConsumedFaceEdges.Clear();
NCollection_DataMap<TopoDS_Shape, bool, TopTools_ShapeMapHasher> aReusedRestrictionEdges;
TopOpeBRepDS_CurveExplorer aCurveIt;
for (aCurveIt.Init(HDS->DS(), false); aCurveIt.More(); aCurveIt.Next())
{
const TopoDS_Edge& aRestriction = aCurveIt.Curve().ExistingEdge();
if (!aRestriction.IsNull() && !aReusedRestrictionEdges.IsBound(aRestriction))
{
aReusedRestrictionEdges.Bind(aRestriction, true);
}
}
for (int aShapeIndex = 1; aShapeIndex <= HDS->NbShapes(); ++aShapeIndex)
{
const TopoDS_Shape& aShape = HDS->Shape(aShapeIndex, false);
if (!aShape.IsNull() && aShape.ShapeType() == TopAbs_FACE
&& IsConsumedByCoincidentCurves(aShape, HDS))
{
myConsumedFaces.Bind(aShape, true);
RegisterConsumedFaceEdges(aShape, aReusedRestrictionEdges, myConsumedFaceEdges);
}
}
BuildFaces(HDS);
myIsKPart = 0;
InitSection();
@@ -153,6 +310,13 @@ void TopOpeBRepBuild_Builder::AddIntersectionEdges(TopoDS_Shape& aFa
const bool RevOri1,
TopOpeBRepBuild_ShapeSet& WES) const
{
NCollection_FlatDataMap<int, int> aConsumedCurveGroups;
FillEquivalentCurveOrientationMasks(aFace,
ToBuild1,
RevOri1,
myDataStructure,
aConsumedCurveGroups);
TopoDS_Shape anEdge;
TopOpeBRepDS_CurveIterator FCurves = myDataStructure->FaceCurves(aFace);
for (; FCurves.More(); FCurves.Next())
@@ -162,8 +326,33 @@ void TopOpeBRepBuild_Builder::AddIntersectionEdges(TopoDS_Shape& aFa
for (NCollection_List<TopoDS_Shape>::Iterator Iti(LnewE); Iti.More(); Iti.Next())
{
anEdge = Iti.Value();
const int aReferenceCurve = myDataStructure->Curve(iC).EquivalentCurve();
if (aReferenceCurve > 0 && aConsumedCurveGroups.IsBound(aReferenceCurve)
&& aConsumedCurveGroups(aReferenceCurve) == 3)
{
continue;
}
const TopoDS_Edge& anExistingEdge = myDataStructure->Curve(iC).ExistingEdge();
bool isBoundaryEdge = false;
for (TopExp_Explorer anEdgeIt(aFace, TopAbs_EDGE); anEdgeIt.More(); anEdgeIt.Next())
{
if (anEdge.IsSame(anEdgeIt.Current())
|| (!anExistingEdge.IsNull() && anExistingEdge.IsSame(anEdgeIt.Current())))
{
isBoundaryEdge = true;
break;
}
}
if (isBoundaryEdge)
{
continue;
}
TopAbs_Orientation ori = FCurves.Orientation(ToBuild1);
TopAbs_Orientation newori = Orient(ori, RevOri1);
if (myDataStructure->Curve(iC).IsEquivalentCurveReversed())
{
newori = TopAbs::Reverse(newori);
}
if (newori == TopAbs_EXTERNAL)
{
@@ -172,7 +361,7 @@ void TopOpeBRepBuild_Builder::AddIntersectionEdges(TopoDS_Shape& aFa
myBuildTool.Orientation(anEdge, newori);
const occ::handle<Geom2d_Curve>& PC = FCurves.PCurve();
myBuildTool.PCurve(aFace, anEdge, PC);
myBuildTool.PCurve(aFace, anEdge, myDataStructure->Curve(iC), PC);
WES.AddStartElement(anEdge);
}
}
@@ -1270,7 +1459,10 @@ void TopOpeBRepBuild_Builder::SplitFace1(const TopoDS_Shape& Foriented,
// Build the new faces
// -------------------
NCollection_List<TopoDS_Shape>& FaceList = ChangeMerged(Fforward, ToBuild1);
MakeFaces(Fforward, FBU, FaceList);
if (!myConsumedFaces.IsBound(Fforward))
{
MakeFaces(Fforward, FBU, FaceList);
}
// connect new faces as faces built <ToBuild1> on LF1 faces
// --------------------------------------------------------
@@ -1447,7 +1639,10 @@ void TopOpeBRepBuild_Builder::SplitFace2(const TopoDS_Shape& Foriented,
// Build the new faces
// -------------------
NCollection_List<TopoDS_Shape>& FaceList1 = ChangeMerged(Fforward, ToBuild1);
MakeFaces(Fforward, FBU1, FaceList1);
if (!myConsumedFaces.IsBound(Fforward))
{
MakeFaces(Fforward, FBU1, FaceList1);
}
// connect new faces as faces built <ToBuild1> on LF1 faces
// --------------------------------------------------------
@@ -1514,7 +1709,10 @@ void TopOpeBRepBuild_Builder::SplitFace2(const TopoDS_Shape& Foriented,
// Build the new faces
// -------------------
NCollection_List<TopoDS_Shape>& FaceList2 = ChangeMerged(Fforward, ToBuild2);
MakeFaces(Fforward, FBU2, FaceList2);
if (!myConsumedFaces.IsBound(Fforward))
{
MakeFaces(Fforward, FBU2, FaceList2);
}
// connect new faces as faces built <ToBuild2> on LF2 faces
// --------------------------------------------------------
@@ -1723,6 +1921,8 @@ void TopOpeBRepBuild_Builder::SplitShapes(TopOpeBRepTool_ShapeExplorer& Ex,
for (; Ex.More(); Ex.Next())
{
aShape = Ex.Current();
const bool isConsumedFaceEdge =
aShape.ShapeType() == TopAbs_EDGE && myConsumedFaceEdges.IsBound(aShape);
// compute new orientation <newori> to give to the new shapes
newori = Orient(myBuildTool.Orientation(aShape), RevOri);
@@ -1768,7 +1968,12 @@ void TopOpeBRepBuild_Builder::SplitShapes(TopOpeBRepTool_ShapeExplorer& Ex,
//----------------------- IFV
for (; It.More(); It.Next())
{
if (isConsumedFaceEdge)
{
continue;
}
newShape = It.Value();
newShape = SubstituteCoincidentEdges(newShape, myCoincidentEdges, myBuildTool);
myBuildTool.Orientation(newShape, newori);
#ifdef OCCT_DEBUG
// TopAbs_ShapeEnum tns = TopType(newShape);
@@ -1861,8 +2066,9 @@ void TopOpeBRepBuild_Builder::SplitShapes(TopOpeBRepTool_ShapeExplorer& Ex,
}
}
}
if (add)
if (add && !isConsumedFaceEdge)
{
aShape = SubstituteCoincidentEdges(aShape, myCoincidentEdges, myBuildTool);
myBuildTool.Orientation(aShape, newori);
aSet.AddElement(aShape);
}
@@ -1932,7 +2138,8 @@ void TopOpeBRepBuild_Builder::FillShape(const TopoDS_Shape& S1
bool keep = KeepShape(aSubShape, LS2, ToBuild1);
if (keep)
{
newori = Orient(myBuildTool.Orientation(aSubShape), RevOri);
newori = Orient(myBuildTool.Orientation(aSubShape), RevOri);
aSubShape = SubstituteCoincidentEdges(aSubShape, myCoincidentEdges, myBuildTool);
myBuildTool.Orientation(aSubShape, newori);
aSet.AddShape(aSubShape);
}
@@ -857,15 +857,18 @@ protected:
const NCollection_DataMap<TopoDS_Shape, TopoDS_Shape, TopTools_ShapeMapHasher>& mlf,
const TopAbs_State state);
TopAbs_State myState1;
TopAbs_State myState2;
TopoDS_Shape myShape1;
TopoDS_Shape myShape2;
occ::handle<TopOpeBRepDS_HDataStructure> myDataStructure;
TopOpeBRepDS_BuildTool myBuildTool;
occ::handle<NCollection_HArray1<TopoDS_Shape>> myNewVertices;
NCollection_DataMap<int, NCollection_List<TopoDS_Shape>> myNewEdges;
occ::handle<NCollection_HArray1<NCollection_List<TopoDS_Shape>>> myNewFaces;
TopAbs_State myState1;
TopAbs_State myState2;
TopoDS_Shape myShape1;
TopoDS_Shape myShape2;
occ::handle<TopOpeBRepDS_HDataStructure> myDataStructure;
TopOpeBRepDS_BuildTool myBuildTool;
occ::handle<NCollection_HArray1<TopoDS_Shape>> myNewVertices;
NCollection_DataMap<int, NCollection_List<TopoDS_Shape>> myNewEdges;
NCollection_DataMap<TopoDS_Shape, TopoDS_Shape, TopTools_ShapeMapHasher> myCoincidentEdges;
NCollection_DataMap<TopoDS_Shape, bool, TopTools_ShapeMapHasher> myConsumedFaces;
NCollection_DataMap<TopoDS_Shape, bool, TopTools_ShapeMapHasher> myConsumedFaceEdges;
occ::handle<NCollection_HArray1<NCollection_List<TopoDS_Shape>>> myNewFaces;
NCollection_DataMap<TopoDS_Shape, TopOpeBRepDS_ListOfShapeOn1State, TopTools_ShapeMapHasher>
mySplitIN;
NCollection_DataMap<TopoDS_Shape, TopOpeBRepDS_ListOfShapeOn1State, TopTools_ShapeMapHasher>
@@ -17,6 +17,7 @@
#include <BRepCheck.hxx>
#include <BRepCheck_Analyzer.hxx>
#include <BRepCheck_Status.hxx>
#include <BRep_Builder.hxx>
#include <NCollection_List.hxx>
#include <NCollection_Shared.hxx>
#include <BRepCheck_Result.hxx>
@@ -36,6 +37,9 @@
#include <TopOpeBRepTool_ShapeExplorer.hxx>
#include <TopTools_ShapeMapHasher.hxx>
#include <NCollection_IndexedDataMap.hxx>
#include <Precision.hxx>
#include <cmath>
// #include <DBRep.hxx>
#ifdef OCCT_DEBUG
@@ -540,7 +544,13 @@ void TopOpeBRepBuild_Builder::MakeEdges(const TopoDS_Shape& anEdge,
myBuildTool.CopyEdge(anEdge, newEdge);
bool hasvertex = false;
bool hasvertex = false;
bool hasForwardVertex = false;
bool hasReversedVertex = false;
double aForwardParameter = 0.0;
double aReversedParameter = 0.0;
TopoDS_Shape aForwardVertex;
TopoDS_Shape aReversedVertex;
for (EDBU.InitVertex(); EDBU.MoreVertex(); EDBU.NextVertex())
{
TopoDS_Shape V = EDBU.Vertex();
@@ -593,6 +603,18 @@ void TopOpeBRepBuild_Builder::MakeEdges(const TopoDS_Shape& anEdge,
{
hasvertex = true;
double parV = EDBU.Parameter();
if (Vori == TopAbs_FORWARD)
{
hasForwardVertex = true;
aForwardVertex = V;
aForwardParameter = parV;
}
else if (Vori == TopAbs_REVERSED)
{
hasReversedVertex = true;
aReversedVertex = V;
aReversedParameter = parV;
}
myBuildTool.AddEdgeVertex(newEdge, V);
myBuildTool.Parameter(newEdge, V, parV);
}
@@ -616,6 +638,12 @@ void TopOpeBRepBuild_Builder::MakeEdges(const TopoDS_Shape& anEdge,
if (hasvertex)
{
if (hasForwardVertex && hasReversedVertex && aForwardVertex.IsSame(aReversedVertex)
&& std::abs(aForwardParameter - aReversedParameter) <= Precision::PConfusion())
{
BRep_Builder aBuilder;
aBuilder.Degenerated(TopoDS::Edge(newEdge), true);
}
L.Append(newEdge);
}
} // loop on EDBU edges
@@ -14,6 +14,7 @@
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
#include <TopExp_Explorer.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Shape.hxx>
#include <TopOpeBRepBuild_define.hxx>
@@ -21,6 +22,7 @@
#include <TopOpeBRepBuild_WireEdgeSet.hxx>
#include <TopOpeBRepDS.hxx>
#include <TopOpeBRepDS_BuildTool.hxx>
#include <TopOpeBRepDS_Curve.hxx>
#include <TopOpeBRepDS_CurveIterator.hxx>
#include <TopOpeBRepDS_EXPORT.hxx>
#include <TopOpeBRepDS_HDataStructure.hxx>
@@ -196,7 +198,23 @@ void TopOpeBRepBuild_Builder::GFillCurveTopologyWES(const TopOpeBRepDS_CurveIter
return;
}
int iG = FCit.Current();
int iG = FCit.Current();
if (myDataStructure->Curve(iG).IsEquivalentCurveReversed())
{
neworiE = TopAbs::Reverse(neworiE);
}
const int anEquivalentCurve = myDataStructure->Curve(iG).EquivalentCurve();
const TopoDS_Edge& aRestrictionEdge = myDataStructure->Curve(iG).ExistingEdge();
if (!aRestrictionEdge.IsNull())
{
for (TopExp_Explorer anEdgeIt(WESF, TopAbs_EDGE); anEdgeIt.More(); anEdgeIt.Next())
{
if (aRestrictionEdge.IsSame(anEdgeIt.Current()))
{
return;
}
}
}
const NCollection_List<TopoDS_Shape>& LnewE = NewEdges(iG);
NCollection_List<TopoDS_Shape>::Iterator Iti(LnewE);
for (; Iti.More(); Iti.Next())
@@ -204,6 +222,24 @@ void TopOpeBRepBuild_Builder::GFillCurveTopologyWES(const TopOpeBRepDS_CurveIter
TopoDS_Shape EE = Iti.Value();
TopoDS_Edge& E = TopoDS::Edge(EE);
if (anEquivalentCurve > 0)
{
bool isAlreadyAdded = false;
for (NCollection_List<TopoDS_Shape>::Iterator aStartIt(WES.StartElements()); aStartIt.More();
aStartIt.Next())
{
if (E.IsSame(aStartIt.Value()))
{
isAlreadyAdded = true;
break;
}
}
if (isAlreadyAdded)
{
continue;
}
}
// modified by NIZHNY-MZV Fri Mar 17 12:51:03 2000
if (BRep_Tool::Degenerated(E))
{
@@ -221,7 +257,7 @@ void TopOpeBRepBuild_Builder::GFillCurveTopologyWES(const TopOpeBRepDS_CurveIter
// modified by NIZHNY-MZV Mon Mar 27 15:24:39 2000
if (!EhasPConFTF)
{
myBuildTool.PCurve(FTF, E, PC);
myBuildTool.PCurve(FTF, E, myDataStructure->Curve(iG), PC);
}
bool EhasPConWESF = FC2D_HasCurveOnSurface(E, WESF);
@@ -15,6 +15,8 @@
// commercial license or contractual agreement.
#include <TopExp.hxx>
#include <BRep_Builder.hxx>
#include <Precision.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Shape.hxx>
#include <TopOpeBRepBuild_define.hxx>
@@ -27,6 +29,8 @@
#include <TopOpeBRepTool_ShapeExplorer.hxx>
#include <TopOpeBRepTool_TOOL.hxx>
#include <cmath>
#ifdef OCCT_DEBUG
extern void debfillp(const int i);
@@ -117,7 +121,9 @@ void TopOpeBRepBuild_Builder::GEDBUMakeEdges(const TopoDS_Shape& EF,
myBuildTool.CopyEdge(EF, newEdge);
int nVF = 0, nVR = 0; // nb vertex FORWARD,REVERSED
int nVF = 0, nVR = 0; // nb vertex FORWARD,REVERSED
double aForwardParameter = 0.0;
double aReversedParameter = 0.0;
TopoDS_Shape VF, VR; // gestion du bit Closed
VF.Nullify();
@@ -180,7 +186,8 @@ void TopOpeBRepBuild_Builder::GEDBUMakeEdges(const TopoDS_Shape& EF,
nVF++;
if (nVF == 1)
{
VF = V;
VF = V;
aForwardParameter = EDBU.Parameter();
}
}
if (Vori == TopAbs_REVERSED)
@@ -188,7 +195,8 @@ void TopOpeBRepBuild_Builder::GEDBUMakeEdges(const TopoDS_Shape& EF,
nVR++;
if (nVR == 1)
{
VR = V;
VR = V;
aReversedParameter = EDBU.Parameter();
}
}
if (oriV == TopAbs_INTERNAL)
@@ -205,6 +213,12 @@ void TopOpeBRepBuild_Builder::GEDBUMakeEdges(const TopoDS_Shape& EF,
bool addedge = (nVF == 1 && nVR == 1);
if (addedge)
{
if (VF.IsSame(VR)
&& std::abs(aForwardParameter - aReversedParameter) <= Precision::PConfusion())
{
BRep_Builder aBuilder;
aBuilder.Degenerated(TopoDS::Edge(newEdge), true);
}
if (tosplit)
{
NCollection_List<TopoDS_Shape> loe;
@@ -24,6 +24,7 @@
#include <Geom2d_Curve.hxx>
#include <Geom2d_Line.hxx>
#include <Geom2d_OffsetCurve.hxx>
#include <Geom2d_TrimmedCurve.hxx>
#include <Geom_BSplineCurve.hxx>
#include <Geom_Curve.hxx>
#include <Geom_Plane.hxx>
@@ -32,6 +33,7 @@
#include <Geom_TrimmedCurve.hxx>
#include <GeomAPI_ProjectPointOnCurve.hxx>
#include <GeomAPI_ProjectPointOnSurf.hxx>
#include <GeomLib.hxx>
#include <gp.hxx>
#include <gp_Pnt.hxx>
#include <gp_Pnt2d.hxx>
@@ -903,10 +905,16 @@ void TopOpeBRepDS_BuildTool::AddEdgeVertex(const TopoDS_Shape& Ein,
TopoDS_Shape& Eou,
const TopoDS_Shape& V) const
{
myBuilder.Add(Eou, V);
TopoDS_Edge e1 = TopoDS::Edge(Ein);
TopoDS_Edge e2 = TopoDS::Edge(Eou);
TopoDS_Vertex v1 = TopoDS::Vertex(V);
if (e1.Orientation() == TopAbs_REVERSED)
{
v1.Reverse();
}
e1.Orientation(TopAbs_FORWARD);
e2.Orientation(TopAbs_FORWARD);
myBuilder.Add(e2, v1);
myBuilder.Transfert(e1, e2, v1, v1);
}
@@ -1250,9 +1258,9 @@ void TopOpeBRepDS_BuildTool::PCurve(TopoDS_Shape& F,
TopoDS_Face FF = TopoDS::Face(F);
TopoDS_Edge EE = TopoDS::Edge(E);
const occ::handle<Geom2d_Curve>& PCT = PC;
double CDSmin, CDSmax;
bool rangedef = CDS.Range(CDSmin, CDSmax);
occ::handle<Geom2d_Curve> PCT = PC;
double CDSmin, CDSmax;
bool rangedef = CDS.Range(CDSmin, CDSmax);
TopLoc_Location L;
double Cf, Cl;
@@ -1260,27 +1268,43 @@ void TopOpeBRepDS_BuildTool::PCurve(TopoDS_Shape& F,
if (!C.IsNull())
{
bool deca = (std::abs(Cf - CDSmin) > Precision::PConfusion());
occ::handle<Geom2d_Line> line2d = occ::down_cast<Geom2d_Line>(PCT);
bool isline2d = !line2d.IsNull();
bool tran = (rangedef && deca && C->IsPeriodic() && isline2d);
if (tran)
if (rangedef && (CDS.IsExistingEdgeReversed() || CDS.IsEquivalentCurveReversed()))
{
TopLoc_Location Loc;
const occ::handle<Geom_Surface> Surf = BRep_Tool::Surface(FF, Loc);
bool isUperio = Surf->IsUPeriodic();
bool isVperio = Surf->IsVPeriodic();
gp_Dir2d dir2d = line2d->Direction();
double delta;
if (isUperio && dir2d.IsParallel(gp::DX2d(), Precision::Angular()))
occ::handle<Geom2d_TrimmedCurve> aReversedPCurve =
new Geom2d_TrimmedCurve(PCT, CDSmin, CDSmax);
aReversedPCurve->Reverse();
GeomLib::SameRange(Precision::PConfusion(),
aReversedPCurve,
aReversedPCurve->FirstParameter(),
aReversedPCurve->LastParameter(),
Cf,
Cl,
PCT);
}
else
{
bool deca = (std::abs(Cf - CDSmin) > Precision::PConfusion());
occ::handle<Geom2d_Line> line2d = occ::down_cast<Geom2d_Line>(PCT);
bool isline2d = !line2d.IsNull();
bool tran = (rangedef && deca && C->IsPeriodic() && isline2d);
if (tran)
{
delta = (CDSmin - Cf) * dir2d.X();
PCT->Translate(gp_Vec2d(delta, 0.));
}
else if (isVperio && dir2d.IsParallel(gp::DY2d(), Precision::Angular()))
{
delta = (CDSmin - Cf) * dir2d.Y();
PCT->Translate(gp_Vec2d(0., delta));
TopLoc_Location Loc;
const occ::handle<Geom_Surface> Surf = BRep_Tool::Surface(FF, Loc);
bool isUperio = Surf->IsUPeriodic();
bool isVperio = Surf->IsVPeriodic();
gp_Dir2d dir2d = line2d->Direction();
double delta;
if (isUperio && dir2d.IsParallel(gp::DX2d(), Precision::Angular()))
{
delta = (CDSmin - Cf) * dir2d.X();
PCT->Translate(gp_Vec2d(delta, 0.));
}
else if (isVperio && dir2d.IsParallel(gp::DY2d(), Precision::Angular()))
{
delta = (CDSmin - Cf) * dir2d.Y();
PCT->Translate(gp_Vec2d(0., delta));
}
}
}
}
@@ -147,6 +147,50 @@ TopoDS_Shape& TopOpeBRepDS_Curve::ChangeShape2()
//=================================================================================================
void TopOpeBRepDS_Curve::SetExistingEdge(const TopoDS_Edge& theEdge, const bool theIsReversed)
{
myExistingEdge = theEdge;
myIsExistingEdgeReversed = theIsReversed;
}
//=================================================================================================
const TopoDS_Edge& TopOpeBRepDS_Curve::ExistingEdge() const
{
return myExistingEdge;
}
//=================================================================================================
bool TopOpeBRepDS_Curve::IsExistingEdgeReversed() const
{
return myIsExistingEdgeReversed;
}
//=================================================================================================
void TopOpeBRepDS_Curve::SetEquivalentCurve(const int theCurveIndex, const bool theIsReversed)
{
myEquivalentCurve = theCurveIndex;
myIsEquivalentCurveReversed = theIsReversed;
}
//=================================================================================================
int TopOpeBRepDS_Curve::EquivalentCurve() const
{
return myEquivalentCurve;
}
//=================================================================================================
bool TopOpeBRepDS_Curve::IsEquivalentCurveReversed() const
{
return myIsEquivalentCurveReversed;
}
//=================================================================================================
occ::handle<Geom_Curve>& TopOpeBRepDS_Curve::ChangeCurve()
{
return myCurve;
@@ -22,6 +22,7 @@
#include <Standard_Handle.hxx>
#include <TopoDS_Shape.hxx>
#include <TopoDS_Edge.hxx>
#include <Standard_Integer.hxx>
class Geom_Curve;
class TopOpeBRepDS_Interference;
@@ -111,6 +112,28 @@ public:
Standard_EXPORT void ChangeDSIndex(const int I);
//! Associates this intersection curve with an existing full edge.
//! The topology builder uses the edge instead of constructing a duplicate.
//! @param[in] theEdge existing edge representing this curve
//! @param[in] theIsReversed true if edge parameters run opposite to this curve
Standard_EXPORT void SetExistingEdge(const TopoDS_Edge& theEdge,
const bool theIsReversed = false);
Standard_EXPORT const TopoDS_Edge& ExistingEdge() const;
//! Returns true when the existing edge has the opposite parameter direction to this curve.
Standard_EXPORT bool IsExistingEdgeReversed() const;
//! Sets another intersection curve that represents the same complete boundary.
Standard_EXPORT void SetEquivalentCurve(const int theCurveIndex,
const bool theIsReversed = false);
//! Returns the index of an equivalent intersection curve, or zero if there is none.
Standard_EXPORT int EquivalentCurve() const;
//! Returns true when this curve has the opposite parameter direction to its equivalent curve.
Standard_EXPORT bool IsEquivalentCurveReversed() const;
private:
occ::handle<Geom_Curve> myCurve;
double myFirst;
@@ -125,6 +148,10 @@ private:
bool myKeep;
int myMother;
int myDSIndex;
TopoDS_Edge myExistingEdge;
bool myIsExistingEdgeReversed = false;
int myEquivalentCurve = 0;
bool myIsEquivalentCurveReversed = false;
};
#endif // _TopOpeBRepDS_Curve_HeaderFile
@@ -28,6 +28,8 @@
#include <TopOpeBRepDS_SurfaceData.hxx>
#include <TopOpeBRepTool_ShapeTool.hxx>
#include <algorithm>
//=================================================================================================
TopOpeBRepDS_DataStructure::TopOpeBRepDS_DataStructure()
@@ -48,6 +50,7 @@ void TopOpeBRepDS_DataStructure::Init()
myNbPoints = 0;
mySurfaces.Clear();
myCurves.Clear();
myEquivalentCurvePoints.Clear();
myPoints.Clear();
myShapes.Clear();
// Begin modified by NIZHNY-MZV Tue Apr 18 16:33:26 2000
@@ -184,6 +187,61 @@ void TopOpeBRepDS_DataStructure::ChangeKeepCurve(TopOpeBRepDS_Curve& C, const bo
//=================================================================================================
int TopOpeBRepDS_DataStructure::FindEquivalentCurvePoint(const int theCurve,
const bool theCurveStart,
bool& theRepresentativeStart) const
{
int aPoint = 2 * theCurve + (theCurveStart ? 0 : 1);
while (myEquivalentCurvePoints.IsBound(aPoint) && myEquivalentCurvePoints(aPoint) != aPoint)
{
aPoint = myEquivalentCurvePoints(aPoint);
}
theRepresentativeStart = (aPoint % 2 == 0);
return aPoint / 2;
}
//=================================================================================================
void TopOpeBRepDS_DataStructure::MergeEquivalentCurvePoints(const int theFirstCurve,
const bool theFirstCurveStart,
const int theSecondCurve,
const bool theSecondCurveStart)
{
bool isFirstRootStart = false;
bool isSecondRootStart = false;
const int aFirstRootCurve =
FindEquivalentCurvePoint(theFirstCurve, theFirstCurveStart, isFirstRootStart);
const int aSecondRootCurve =
FindEquivalentCurvePoint(theSecondCurve, theSecondCurveStart, isSecondRootStart);
const int aFirstRoot = 2 * aFirstRootCurve + (isFirstRootStart ? 0 : 1);
const int aSecondRoot = 2 * aSecondRootCurve + (isSecondRootStart ? 0 : 1);
if (aFirstRoot == aSecondRoot)
{
return;
}
const int aRoot = std::min(aFirstRoot, aSecondRoot);
const int aChild = std::max(aFirstRoot, aSecondRoot);
if (myEquivalentCurvePoints.IsBound(aRoot))
{
myEquivalentCurvePoints.ChangeFind(aRoot) = aRoot;
}
else
{
myEquivalentCurvePoints.Bind(aRoot, aRoot);
}
if (myEquivalentCurvePoints.IsBound(aChild))
{
myEquivalentCurvePoints.ChangeFind(aChild) = aRoot;
}
else
{
myEquivalentCurvePoints.Bind(aChild, aRoot);
}
}
//=================================================================================================
int TopOpeBRepDS_DataStructure::AddPoint(const TopOpeBRepDS_Point& PDS)
{
myNbPoints++;
@@ -1106,6 +1164,42 @@ TopOpeBRepDS_Curve& TopOpeBRepDS_DataStructure::ChangeCurve(const int I)
//=================================================================================================
int TopOpeBRepDS_DataStructure::FindEquivalentCurve(const int I, bool& theIsReversed) const
{
int aRoot = I;
theIsReversed = false;
while (Curve(aRoot).EquivalentCurve() > 0 && Curve(aRoot).EquivalentCurve() != aRoot)
{
theIsReversed ^= Curve(aRoot).IsEquivalentCurveReversed();
aRoot = Curve(aRoot).EquivalentCurve();
}
return aRoot;
}
//=================================================================================================
void TopOpeBRepDS_DataStructure::MergeEquivalentCurves(const int theFirst,
const int theSecond,
const bool theIsReversed)
{
bool isFirstReversed = false;
bool isSecondReversed = false;
const int aFirstRoot = FindEquivalentCurve(theFirst, isFirstReversed);
const int aSecondRoot = FindEquivalentCurve(theSecond, isSecondReversed);
if (aFirstRoot == aSecondRoot)
{
return;
}
const int aReference = aFirstRoot < aSecondRoot ? aFirstRoot : aSecondRoot;
const int anEquivalent = aFirstRoot < aSecondRoot ? aSecondRoot : aFirstRoot;
const bool isRootReversed = isFirstReversed ^ isSecondReversed ^ theIsReversed;
ChangeCurve(aReference).SetEquivalentCurve(aReference, false);
ChangeCurve(anEquivalent).SetEquivalentCurve(aReference, isRootReversed);
}
//=================================================================================================
const TopOpeBRepDS_Point& TopOpeBRepDS_DataStructure::Point(const int I) const
{
if (I < 1 || I > myNbPoints)
@@ -24,6 +24,7 @@
#include <Standard_Integer.hxx>
#include <TopOpeBRepDS_SurfaceData.hxx>
#include <NCollection_DataMap.hxx>
#include <NCollection_FlatDataMap.hxx>
#include <TopOpeBRepDS_CurveData.hxx>
#include <TopOpeBRepDS_PointData.hxx>
#include <TopoDS_Shape.hxx>
@@ -85,6 +86,19 @@ public:
Standard_EXPORT void ChangeKeepCurve(TopOpeBRepDS_Curve& C, const bool FindKeep);
//! Records that the specified ends of two intersection curves represent
//! the same topological point.
Standard_EXPORT void MergeEquivalentCurvePoints(const int theFirstCurve,
const bool theFirstCurveStart,
const int theSecondCurve,
const bool theSecondCurveStart);
//! Returns the representative curve end for the specified curve end.
//! The returned curve index is equal to theCurve when no equivalence is recorded.
Standard_EXPORT int FindEquivalentCurvePoint(const int theCurve,
const bool theCurveStart,
bool& theRepresentativeStart) const;
//! Insert a new point. Returns the index.
Standard_EXPORT int AddPoint(const TopOpeBRepDS_Point& PDS);
@@ -243,6 +257,15 @@ public:
//! Returns the Curve of index <I>.
Standard_EXPORT TopOpeBRepDS_Curve& ChangeCurve(const int I);
//! Returns the representative of an equivalent-curve group and reports whether
//! the curve parameter direction is reversed relative to that representative.
Standard_EXPORT int FindEquivalentCurve(const int I, bool& theIsReversed) const;
//! Joins two complete coincident curves into one oriented topological boundary.
Standard_EXPORT void MergeEquivalentCurves(const int theFirst,
const int theSecond,
const bool theIsReversed);
//! Returns the point of index <I>.
Standard_EXPORT const TopOpeBRepDS_Point& Point(const int I) const;
@@ -321,6 +344,7 @@ private:
NCollection_DataMap<int, TopOpeBRepDS_SurfaceData> mySurfaces;
int myNbCurves;
NCollection_DataMap<int, TopOpeBRepDS_CurveData> myCurves;
NCollection_FlatDataMap<int, int> myEquivalentCurvePoints;
int myNbPoints;
NCollection_DataMap<int, TopOpeBRepDS_PointData> myPoints;
NCollection_IndexedDataMap<TopoDS_Shape, TopOpeBRepDS_ShapeData, TopTools_ShapeMapHasher>