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
5 changes: 3 additions & 2 deletions src/ModelingAlgorithms/TKGeomAlgo/GTests/FILES.cmake
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# Test source files for TKGeomAlgo
set(OCCT_TKGeomAlgo_GTests_FILES_LOCATION "${CMAKE_CURRENT_LIST_DIR}")

set(OCCT_TKGeomAlgo_GTests_FILES
)
GeomFill_CorrectedFrenet_Test.cxx
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
// Copyright (c) 2025 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 <GeomFill_CorrectedFrenet.hxx>
#include <Geom_BSplineCurve.hxx>
#include <Geom_Curve.hxx>
#include <GeomAdaptor_Curve.hxx>
#include <BRepAdaptor_CompCurve.hxx>
#include <BRepBuilderAPI_MakeEdge.hxx>
#include <GC_MakeSegment.hxx>
#include <ShapeExtend_WireData.hxx>
#include <TopoDS_Edge.hxx>
#include <TColgp_Array1OfPnt.hxx>
#include <TColStd_Array1OfReal.hxx>
#include <TColStd_Array1OfInteger.hxx>
#include <gp_Pnt.hxx>
#include <Standard_Real.hxx>

#include <gtest/gtest.h>

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

TEST(GeomFill_CorrectedFrenet, EndlessLoopPrevention)
{
TColgp_Array1OfPnt aPoles(1, 4);
aPoles(1) = gp_Pnt(0.0, 0.0, 0.0);
aPoles(2) = gp_Pnt(1.0, 0.0, 0.0);
aPoles(3) = gp_Pnt(1.0, 1.0, 0.0);
aPoles(4) = gp_Pnt(0.0, 1.0, 0.0);

TColStd_Array1OfReal aKnots(1, 2);
aKnots(1) = 0.0;
aKnots(2) = 1.0;

TColStd_Array1OfInteger aMults(1, 2);
aMults(1) = 4;
aMults(2) = 4;

Handle(Geom_BSplineCurve) aCurve = new Geom_BSplineCurve(aPoles, aKnots, aMults, 3);
Handle(GeomAdaptor_Curve) anAdaptor = new GeomAdaptor_Curve(aCurve);

GeomFill_CorrectedFrenet aCorrectedFrenet(Standard_False);
aCorrectedFrenet.SetCurve(anAdaptor);

Standard_Real aParam1 = 0.0;
Standard_Real aParam2 = 1.0;

gp_Vec aTangent1, aNormal1, aBinormal1;
gp_Vec aTangent2, aNormal2, aBinormal2;

EXPECT_NO_THROW({
aCorrectedFrenet.D0(aParam1, aTangent1, aNormal1, aBinormal1);
aCorrectedFrenet.D0(aParam2, aTangent2, aNormal2, aBinormal2);
});

EXPECT_GT(aTangent1.Magnitude(), 1e-10);
EXPECT_GT(aNormal1.Magnitude(), 1e-10);
EXPECT_GT(aBinormal1.Magnitude(), 1e-10);

EXPECT_GT(aTangent2.Magnitude(), 1e-10);
EXPECT_GT(aNormal2.Magnitude(), 1e-10);
EXPECT_GT(aBinormal2.Magnitude(), 1e-10);
}

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

TEST(GeomFill_CorrectedFrenet, SmallStepHandling)
{
TColgp_Array1OfPnt aPoles(1, 2);
aPoles(1) = gp_Pnt(0.0, 0.0, 0.0);
aPoles(2) = gp_Pnt(1e-10, 0.0, 0.0);

TColStd_Array1OfReal aKnots(1, 2);
aKnots(1) = 0.0;
aKnots(2) = 1.0;

TColStd_Array1OfInteger aMults(1, 2);
aMults(1) = 2;
aMults(2) = 2;

Handle(Geom_BSplineCurve) aCurve = new Geom_BSplineCurve(aPoles, aKnots, aMults, 1);
Handle(GeomAdaptor_Curve) anAdaptor = new GeomAdaptor_Curve(aCurve);

GeomFill_CorrectedFrenet aCorrectedFrenet(Standard_False);
aCorrectedFrenet.SetCurve(anAdaptor);

gp_Vec aTangent, aNormal, aBinormal;

EXPECT_NO_THROW({ aCorrectedFrenet.D0(0.5, aTangent, aNormal, aBinormal); });
}

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

TEST(GeomFill_CorrectedFrenet, ParameterProgressionGuarantee)
{
TColgp_Array1OfPnt aPoles(1, 3);
aPoles(1) = gp_Pnt(0.0, 0.0, 0.0);
aPoles(2) = gp_Pnt(0.5, 0.5, 0.0);
aPoles(3) = gp_Pnt(1.0, 0.0, 0.0);

TColStd_Array1OfReal aKnots(1, 2);
aKnots(1) = 0.0;
aKnots(2) = 1.0;

TColStd_Array1OfInteger aMults(1, 2);
aMults(1) = 3;
aMults(2) = 3;

Handle(Geom_BSplineCurve) aCurve = new Geom_BSplineCurve(aPoles, aKnots, aMults, 2);
Handle(GeomAdaptor_Curve) anAdaptor = new GeomAdaptor_Curve(aCurve);

GeomFill_CorrectedFrenet aCorrectedFrenet(Standard_False);
aCorrectedFrenet.SetCurve(anAdaptor);

for (Standard_Real aParam = 0.1; aParam <= 0.9; aParam += 0.1)
{
gp_Vec aTangent, aNormal, aBinormal;

EXPECT_NO_THROW({ aCorrectedFrenet.D0(aParam, aTangent, aNormal, aBinormal); });

EXPECT_GT(aTangent.Magnitude(), 1e-12);
EXPECT_GT(aNormal.Magnitude(), 1e-12);
EXPECT_GT(aBinormal.Magnitude(), 1e-12);
}
}

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

TEST(GeomFill_CorrectedFrenet, ActualReproducerCase)
{
TColgp_Array1OfPnt aPoints(1, 4);
aPoints(1) = gp_Pnt(-1, -1, 0);
aPoints(2) = gp_Pnt(0, -2, 0);
aPoints(3) = gp_Pnt(0, -2, -1);
aPoints(4) = gp_Pnt(0, -1, -1);

ShapeExtend_WireData anExtend;
for (Standard_Integer i = 2; i <= aPoints.Length(); i++)
{
Handle(Geom_Curve) aCurve = GC_MakeSegment(aPoints(i - 1), aPoints(i)).Value();
TopoDS_Edge anEdge = BRepBuilderAPI_MakeEdge(aCurve).Edge();
anExtend.Add(anEdge);
}

BRepAdaptor_CompCurve anAdaptor(anExtend.WireAPIMake());

GeomFill_CorrectedFrenet aCorrectedFrenet(Standard_False);

// This SetCurve call should not hang (was causing infinite loops)
EXPECT_NO_THROW({ aCorrectedFrenet.SetCurve(anAdaptor.ShallowCopy()); });

// Verify we can evaluate the trihedron at various parameters
gp_Vec aTangent, aNormal, aBinormal;

EXPECT_NO_THROW({ aCorrectedFrenet.D0(0.0, aTangent, aNormal, aBinormal); });

EXPECT_NO_THROW({ aCorrectedFrenet.D0(0.5, aTangent, aNormal, aBinormal); });

EXPECT_NO_THROW({ aCorrectedFrenet.D0(1.0, aTangent, aNormal, aBinormal); });
}
Original file line number Diff line number Diff line change
Expand Up @@ -506,44 +506,53 @@ Standard_Boolean GeomFill_CorrectedFrenet::InitInterval(const Standard_Real
TColgp_SequenceOfVec& SeqTangent,
TColgp_SequenceOfVec& SeqNormal) const
{
Bnd_Box Boite;
gp_Vec Tangent, Normal, BN, cross;
TColStd_SequenceOfReal parameters;
TColStd_SequenceOfReal EvolAT;
Standard_Real Param = First, LengthMin, L, norm;
Standard_Real Param = First;
Standard_Boolean isZero = Standard_True, isConst = Standard_True;
Standard_Integer i;
gp_Pnt PonC;
gp_Vec D1;

frenet->SetInterval(First, Last); // To have right evaluation at bounds
GeomFill_SnglrFunc CS(myCurve);
BndLib_Add3dCurve::Add(CS, First, Last, 1.e-2, Boite);
LengthMin = Boite.GetGap() * 1.e-4;
Bnd_Box aCurveBoundBox;
BndLib_Add3dCurve::Add(CS, First, Last, 1.e-2, aCurveBoundBox);
const Standard_Real LengthMin = aCurveBoundBox.GetGap() * 1.e-4;

aT = gp_Vec(0, 0, 0);
aN = gp_Vec(0, 0, 0);

Standard_Real angleAT = 0., currParam, currStep = Step;
Standard_Real angleAT = 0.;
Standard_Real currStep = Step;

Handle(Geom_Plane) aPlane;
Standard_Boolean isPlanar = Standard_False;
if (!myForEvaluation)
{
isPlanar = FindPlane(myCurve, aPlane);
}

i = 1;
currParam = Param;
Standard_Real DLast = Last - Precision::PConfusion();
Standard_Integer i = 1;
Standard_Real currParam = Param;
const Standard_Real DLast = Last - Precision::PConfusion();

while (Param < Last)
{
if (currParam > DLast)
{
if (Abs(DLast - Param) < Precision::SquareConfusion())
{
Param = currParam;
Comment thread
dpasukhi marked this conversation as resolved.
}

currStep = DLast - Param;
currParam = Last;
}
if (isPlanar)
{
currParam = Last;
}

frenet->D0(currParam, Tangent, Normal, BN);
if (prevTangent.Angle(Tangent) < M_PI / 3 || i == 1)
Expand Down Expand Up @@ -577,18 +586,22 @@ Standard_Boolean GeomFill_CorrectedFrenet::InitInterval(const Standard_Real

// Evaluate the Next step
CS.D1(Param, PonC, D1);
L = Max(PonC.XYZ().Modulus() / 2, LengthMin);
norm = D1.Magnitude();
Standard_Real L = Max(PonC.XYZ().Modulus() / 2, LengthMin);
Standard_Real norm = D1.Magnitude();
if (norm < Precision::Confusion())
{
norm = Precision::Confusion();
}
currStep = L / norm;
if (currStep > Step)
{
currStep = Step; // default value
}
}
else
{
currStep /= 2; // Step too long !
}

currParam = Param + currStep;
}
Expand All @@ -613,24 +626,12 @@ Standard_Boolean GeomFill_CorrectedFrenet::InitInterval(const Standard_Real
Handle(TColStd_HArray1OfReal) pararr = new TColStd_HArray1OfReal(1, Length);
Handle(TColStd_HArray1OfReal) angleATarr = new TColStd_HArray1OfReal(1, Length);

for (i = 1; i <= Length; i++)
for (Standard_Integer aParamIndex = 1; aParamIndex <= Length; ++aParamIndex)
{
pararr->ChangeValue(i) = parameters(i);
angleATarr->ChangeValue(i) = EvolAT(i);
pararr->ChangeValue(aParamIndex) = parameters(aParamIndex);
angleATarr->ChangeValue(aParamIndex) = EvolAT(aParamIndex);
}

#ifdef OCCT_DEBUG
if (Affich)
{
std::cout << "NormalEvolution" << std::endl;
for (i = 1; i <= Length; i++)
{
std::cout << "(" << pararr->Value(i) << ", " << angleATarr->Value(i) << ")" << std::endl;
}
std::cout << std::endl;
}
#endif

Law_Interpolate lawAT(angleATarr, pararr, Standard_False, Precision::PConfusion());
lawAT.Perform();
Handle(Law_BSpline) BS = lawAT.Curve();
Expand Down
Loading