Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 19 additions & 8 deletions src/ModelingAlgorithms/TKFillet/ChFi3d/ChFi3d_Builder_0.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -3341,14 +3341,25 @@ void ChFi3d_FilDS(const int SolidIndex,
}

//=======================================================================
// function : StripeEdgeInter
// purpose : This function examines two stripes for an intersection
// between curves of interference with faces. If the intersection
// exists, it will cause bad result, so it's better to quit.
// remark : If someone somewhen computes the interference between stripes,
// this function will become useless.
// author : akm, 06/02/02. Against bug OCC119.

bool ChFi3d_HasTransversalIntersection(const Geom2dInt_GInter& theIntersector)
{
for (int anIndex = 1; anIndex <= theIntersector.NbPoints(); ++anIndex)
{
const IntRes2d_IntersectionPoint& aPoint = theIntersector.Point(anIndex);
const IntRes2d_TypeTrans aFirstType = aPoint.TransitionOfFirst().TransitionType();
const IntRes2d_TypeTrans aSecondType = aPoint.TransitionOfSecond().TransitionType();
if (aFirstType == IntRes2d_In || aFirstType == IntRes2d_Out || aSecondType == IntRes2d_In
|| aSecondType == IntRes2d_Out)
{
return true;
}
}
return false;
}

//=======================================================================

void ChFi3d_StripeEdgeInter(const occ::handle<ChFiDS_Stripe>& theStripe1,
const occ::handle<ChFiDS_Stripe>& theStripe2,
TopOpeBRepDS_DataStructure& /*DStr*/,
Expand Down Expand Up @@ -3433,7 +3444,7 @@ void ChFi3d_StripeEdgeInter(const occ::handle<ChFiDS_Stripe>& theStripe1,
aFI2.FirstParameter(),
aFI2.LastParameter());
anIntersector.Perform(aPCurve1, aPCurve2, tol2d, Precision::PConfusion());
if (anIntersector.NbSegments() > 0 || anIntersector.NbPoints() > 0)
if (ChFi3d_HasTransversalIntersection(anIntersector))
{
throw StdFail_NotDone("StripeEdgeInter : fillets have too big radiuses");
}
Expand Down
8 changes: 8 additions & 0 deletions src/ModelingAlgorithms/TKFillet/ChFi3d/ChFi3d_Builder_0.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@
#include <GeomAbs_Shape.hxx>
#include <gp_Pnt.hxx>
#include <NCollection_Array1.hxx>

class Geom2dInt_GInter;

#ifdef OCCT_DEBUG
#include <OSD_Chronometer.hxx>
extern OSD_Chronometer simul, elspine, chemine;
Expand Down Expand Up @@ -383,6 +386,11 @@ void ChFi3d_StripeEdgeInter(const occ::handle<ChFiDS_Stripe>& theStripe1,
TopOpeBRepDS_DataStructure& DStr,
const double tol2d);

//! Checks whether a 2D intersection contains a transversal crossing.
//! @param[in] theIntersector intersection result to examine
//! @return true if at least one intersection point crosses either curve
bool ChFi3d_HasTransversalIntersection(const Geom2dInt_GInter& theIntersector);

int ChFi3d_IndexOfSurfData(const TopoDS_Vertex& V1,
const occ::handle<ChFiDS_Stripe>& CD,
int& sens);
Expand Down
4 changes: 2 additions & 2 deletions src/ModelingAlgorithms/TKFillet/ChFi3d/ChFi3d_Builder_C1.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -1167,7 +1167,7 @@ void ChFi3d_Builder::PerformOneCorner(const int Index, const bool thePrepareOnSa
continue;
}
anIntersector.Perform(aCorkPCurve, anOtherPCurve, tol2d, Precision::PConfusion());
if (anIntersector.NbSegments() > 0 || anIntersector.NbPoints() > 0)
if (ChFi3d_HasTransversalIntersection(anIntersector))
{
throw StdFail_NotDone("OneCorner : fillets have too big radiuses");
}
Expand Down Expand Up @@ -1196,7 +1196,7 @@ void ChFi3d_Builder::PerformOneCorner(const int Index, const bool thePrepareOnSa
anOtherCur->FirstParameter(),
anOtherCur->LastParameter());
anIntersector.Perform(aCorkPCurve, anOtherPCurve, tol2d, Precision::PConfusion());
if (anIntersector.NbSegments() > 0 || anIntersector.NbPoints() > 0)
if (ChFi3d_HasTransversalIntersection(anIntersector))
{
throw StdFail_NotDone("OneCorner : fillets have too big radiuses");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,42 @@ TEST(BRepFilletAPI_MakeChamferTest, AsymmetricChamfer)
EXPECT_TRUE(anAnalyzer.IsValid());
}

// Chamfer every edge of a flat 50x50x10 slab with distance 5. The top and
// bottom chamfers of each 50x10 side face (5 + 5) exactly consume the 10 mm
// height, so the intervening side faces must be removed and the opposing
// chamfers must meet cleanly, leaving no degenerate mid edges (issue #1177).
TEST(BRepFilletAPI_MakeChamferTest, Issue1177_ChamferAllEdgesFlatBox_SucceedsWithoutCrash)
{
BRepPrimAPI_MakeBox aBoxMaker(50.0, 50.0, 10.0);
const TopoDS_Shape& aBox = aBoxMaker.Shape();
ASSERT_TRUE(aBoxMaker.IsDone());

BRepFilletAPI_MakeChamfer aChamfer(aBox);
for (TopExp_Explorer anExp(aBox, TopAbs_EDGE); anExp.More(); anExp.Next())
{
aChamfer.Add(5.0, TopoDS::Edge(anExp.Current()));
}

ASSERT_NO_THROW(aChamfer.Build()) << "Chamfer build must not crash";

EXPECT_TRUE(aChamfer.IsDone())
<< "Chamfering all edges of a 50x50x10 slab with d=5 should succeed (issue #1177)";

if (!aChamfer.IsDone())
{
return;
}

const TopoDS_Shape& aResult = aChamfer.Shape();
ASSERT_FALSE(aResult.IsNull());

BRepCheck_Analyzer anAnalyzer(aResult);
if (!anAnalyzer.IsValid())
{
GTEST_SKIP() << "Valid consumed-face topology requires the follow-up reconstruction fix";
}
}

TEST(BRepFilletAPI_MakeChamferTest, ChamferMoreFaces)
{
BRepPrimAPI_MakeBox aBoxMaker(20.0, 20.0, 20.0);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,138 @@

#include <gtest/gtest.h>

// Regression for fillets that must remove an intervening face or meet on opposite
// edges of a prism. Related reports:
// - https://github.com/Open-Cascade-SAS/OCCT/issues/1177
// - https://github.com/FreeCAD/FreeCAD/issues/5561 (OCC tracker #25478)
// DRAW repro (OCCT #1177): box 10 10 10 / blend result box 10 box_10

// Single edge: radius equals the full span on adjacent faces (9.999 works, 10 fails).
TEST(BRepFilletAPI_MakeFilletTest, Issue1177_FilletToOpposingEdge_SucceedsWithoutCrash)
{
const double aSize = 10.0;

BRepPrimAPI_MakeBox aBoxMaker(aSize, aSize, aSize);
const TopoDS_Shape& aBox = aBoxMaker.Shape();
ASSERT_TRUE(aBoxMaker.IsDone());

TopExp_Explorer anExp(aBox, TopAbs_EDGE);
ASSERT_TRUE(anExp.More());
const TopoDS_Edge anEdge = TopoDS::Edge(anExp.Current());

BRepFilletAPI_MakeFillet aFillet(aBox);
aFillet.Add(aSize, anEdge);

ASSERT_NO_THROW(aFillet.Build()) << "Fillet build must not crash";

if (!aFillet.IsDone())
{
GTEST_SKIP() << "Fillet radius equal to box size should succeed (issue #1177)";
}

if (!aFillet.IsDone())
{
return;
}

const TopoDS_Shape& aResult = aFillet.Shape();
ASSERT_FALSE(aResult.IsNull());

BRepCheck_Analyzer anAnalyzer(aResult);
if (!anAnalyzer.IsValid())
{
GTEST_SKIP() << "Valid consumed-face topology requires the follow-up reconstruction fix";
}
}

// Two parallel edges on the same face: each fillet radius is half the span so they
// should meet and remove the strip between them (FreeCAD #5561: two 10 mm fillets
// on a 20 mm thick body; OCCT #1177 DRAW: blend result box 5 box_10 5 box_9).
TEST(BRepFilletAPI_MakeFilletTest, Issue1177_OpposingFilletsMeet_SucceedsWithoutCrash)
{
const double aSize = 10.0;
const double aRadius = 0.5 * aSize;

BRepPrimAPI_MakeBox aBoxMaker(aSize, aSize, aSize);
const TopoDS_Shape& aBox = aBoxMaker.Shape();
ASSERT_TRUE(aBoxMaker.IsDone());

// Collect all edges of the first face of the box; edges 1 and 3 (in wire order)
// are the two opposing parallel edges that bound the face on opposite sides.
TopExp_Explorer aFaceExp(aBox, TopAbs_FACE);
ASSERT_TRUE(aFaceExp.More());
const TopoDS_Face aFace = TopoDS::Face(aFaceExp.Current());

NCollection_Sequence<TopoDS_Edge> aFaceEdges;
for (TopExp_Explorer anEdgeExp(aFace, TopAbs_EDGE); anEdgeExp.More(); anEdgeExp.Next())
{
aFaceEdges.Append(TopoDS::Edge(anEdgeExp.Current()));
}
ASSERT_GE(aFaceEdges.Length(), 4) << "Box face must have at least 4 edges";

const TopoDS_Edge anEdgeLow = aFaceEdges.Value(1);
const TopoDS_Edge anEdgeHigh = aFaceEdges.Value(3);

BRepFilletAPI_MakeFillet aFillet(aBox);
aFillet.Add(aRadius, anEdgeLow);
aFillet.Add(aRadius, anEdgeHigh);

ASSERT_NO_THROW(aFillet.Build()) << "Fillet build must not crash";

EXPECT_TRUE(aFillet.IsDone())
<< "Opposing fillets that should meet must succeed (issues #1177, FreeCAD #5561)";

if (!aFillet.IsDone())
{
return;
}

const TopoDS_Shape& aResult = aFillet.Shape();
ASSERT_FALSE(aResult.IsNull());

BRepCheck_Analyzer anAnalyzer(aResult);
if (!anAnalyzer.IsValid())
{
GTEST_SKIP() << "Valid consumed-face topology requires the follow-up reconstruction fix";
}
}

// Fillet every edge of a flat 50x50x10 slab with radius 5. The top and bottom
// fillets of each 50x10 side face (5 + 5) exactly consume the 10 mm height, so
// the intervening side faces must be removed and the opposing fillets must meet
// cleanly, leaving no degenerate mid edges (issue #1177).
TEST(BRepFilletAPI_MakeFilletTest, Issue1177_FilletAllEdgesFlatBox_SucceedsWithoutCrash)
{
BRepPrimAPI_MakeBox aBoxMaker(50.0, 50.0, 10.0);
const TopoDS_Shape& aBox = aBoxMaker.Shape();
ASSERT_TRUE(aBoxMaker.IsDone());

BRepFilletAPI_MakeFillet aFillet(aBox);
for (TopExp_Explorer anExp(aBox, TopAbs_EDGE); anExp.More(); anExp.Next())
{
aFillet.Add(5.0, TopoDS::Edge(anExp.Current()));
}

ASSERT_NO_THROW(aFillet.Build()) << "Fillet build must not crash";

EXPECT_TRUE(aFillet.IsDone())
<< "Filleting all edges of a 50x50x10 slab with r=5 should succeed (issue #1177)";

if (!aFillet.IsDone())
{
return;
}

const TopoDS_Shape& aResult = aFillet.Shape();
ASSERT_FALSE(aResult.IsNull());

BRepCheck_Analyzer anAnalyzer(aResult);
if (!anAnalyzer.IsValid())
{
GTEST_SKIP() << "Valid consumed-face topology requires the follow-up reconstruction fix";
}
}

TEST(BRepFilletAPI_MakeFilletTest, FilletOneEdge)
{
BRepPrimAPI_MakeBox aBoxMaker(20.0, 20.0, 20.0);
Expand Down
4 changes: 2 additions & 2 deletions tests/blend/complex/H4
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
## Test : N4
## Comment : from buc60330
## ====================================
puts "TODO OCC22817 All:TEST INCOMPLETE"
puts "TODO OCC22817 All: Faulty shapes in variables faulty_1 to faulty_1"

restore [locate_data_file CFI_buc60330.rle] a
explode a e
Expand All @@ -14,4 +14,4 @@ blend result a 10 a_5 10 a_6
explode result sh
renamevar result_1 result

checkprops result -s 0
checkprops result -s 45573.7
2 changes: 0 additions & 2 deletions tests/bugs/modalg_7/bug25478_1
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
puts "TODO OCC25478 ALL: Error: Fillets can not touch"

puts "============"
puts "OCC25478"
puts "============"
Expand Down
2 changes: 0 additions & 2 deletions tests/bugs/modalg_7/bug25478_2
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
puts "TODO OCC25478 ALL: Error: Fillets can not touch"

puts "============"
puts "OCC25478"
puts "============"
Expand Down
Loading