mirror of
https://github.com/Open-Cascade-SAS/OCCT.git
synced 2026-09-04 11:47:53 +08:00
Testing - Migration QADraw tests to GTests (#1235)
- Removed multiple legacy DRAW test scripts and several QABugs DRAW command implementations. - Added new GTest suites covering the migrated regressions in ModelingData/ModelingAlgorithms/FoundationClasses/DataExchange/ApplicationFramework. - Updated multiple `FILES.cmake` lists to compile/link the new tests; introduced an additional `STEPControl_Writer::SetShapeFixParameters()` overload.
This commit is contained in:
@@ -13,12 +13,24 @@
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <BRep_Tool.hxx>
|
||||
#include <BRepAdaptor_CompCurve.hxx>
|
||||
#include <BRepBuilderAPI_MakeEdge.hxx>
|
||||
#include <BRepBuilderAPI_MakeWire.hxx>
|
||||
#include <GC_MakeArcOfCircle.hxx>
|
||||
#include <Geom_Circle.hxx>
|
||||
#include <Geom_TrimmedCurve.hxx>
|
||||
#include <gp_Ax2.hxx>
|
||||
#include <gp_Circ.hxx>
|
||||
#include <gp_Pnt.hxx>
|
||||
#include <gp_Vec.hxx>
|
||||
#include <NCollection_List.hxx>
|
||||
#include <TopAbs_Orientation.hxx>
|
||||
#include <TopoDS.hxx>
|
||||
#include <TopoDS_Edge.hxx>
|
||||
#include <TopoDS_Vertex.hxx>
|
||||
#include <TopoDS_Wire.hxx>
|
||||
#include <TopExp_Explorer.hxx>
|
||||
|
||||
// Test OCC5696: BRepAdaptor_CompCurve::Edge() method
|
||||
// Migrated from QABugs_5.cxx
|
||||
@@ -57,3 +69,111 @@ TEST(BRepAdaptor_CompCurve_Test, OCC5696_EdgeMethod)
|
||||
// The parameter should be approximately half of the edge length
|
||||
EXPECT_NEAR(1.0, aParEdge, 0.01) << "Edge parameter should be approximately 1.0";
|
||||
}
|
||||
|
||||
// Test OCC29430: BRepAdaptor_CompCurve::Value() at boundary parameters matches wire vertices.
|
||||
// The bug was that evaluating a composite curve at its First/LastParameter
|
||||
// did not return the correct endpoint.
|
||||
TEST(BRepAdaptor_CompCurve_Test, OCC29430_ArcBoundaryPoints)
|
||||
{
|
||||
const double r45 = M_PI / 4.0, r225 = 3.0 * M_PI / 4.0;
|
||||
|
||||
GC_MakeArcOfCircle arcMaker(
|
||||
gp_Circ(gp_Ax2(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(gp_Dir::D::Z), gp_Dir(gp_Dir::D::X)), 1.0),
|
||||
r45,
|
||||
r225,
|
||||
true);
|
||||
BRepBuilderAPI_MakeEdge edgeMaker(arcMaker.Value());
|
||||
BRepBuilderAPI_MakeWire wireMaker(edgeMaker.Edge());
|
||||
const TopoDS_Wire aWire = wireMaker.Wire();
|
||||
|
||||
BRepAdaptor_CompCurve aCurve(aWire);
|
||||
const gp_Pnt aStartPt = aCurve.Value(aCurve.FirstParameter());
|
||||
const gp_Pnt anEndPt = aCurve.Value(aCurve.LastParameter());
|
||||
|
||||
// Collect wire vertices
|
||||
NCollection_List<gp_Pnt> aVertices;
|
||||
for (TopExp_Explorer anExp(aWire, TopAbs_VERTEX); anExp.More(); anExp.Next())
|
||||
{
|
||||
aVertices.Append(BRep_Tool::Pnt(TopoDS::Vertex(anExp.Current())));
|
||||
}
|
||||
ASSERT_GE(aVertices.Size(), 1);
|
||||
|
||||
// Start point should match one of the wire vertices (within 1e-7 tolerance)
|
||||
bool aStartMatchesAnyVertex = false;
|
||||
bool anEndMatchesAnyVertex = false;
|
||||
for (const gp_Pnt& aV : aVertices)
|
||||
{
|
||||
if (aStartPt.Distance(aV) < 1.0e-7)
|
||||
aStartMatchesAnyVertex = true;
|
||||
if (anEndPt.Distance(aV) < 1.0e-7)
|
||||
anEndMatchesAnyVertex = true;
|
||||
}
|
||||
EXPECT_TRUE(aStartMatchesAnyVertex) << "Start point does not match any wire vertex";
|
||||
EXPECT_TRUE(anEndMatchesAnyVertex) << "End point does not match any wire vertex";
|
||||
EXPECT_GT(aStartPt.Distance(anEndPt), 1.0e-7) << "Start and end points should be different";
|
||||
}
|
||||
|
||||
// Test OCC30869: BRepAdaptor_CompCurve D1 at boundary parameters of a wire with reversed edge.
|
||||
// The bug was that a wire with a single reversed-orientation trimmed-circle edge returned
|
||||
// incorrect boundary point coordinates and tangent directions.
|
||||
// Migrated from QABugs_20.cxx OCC30869
|
||||
TEST(BRepAdaptor_CompCurve_Test, OCC30869_ReversedEdgeBoundaryPoints)
|
||||
{
|
||||
// Build a circle: center(1,0,0), Z-axis(0,-1,0), X-axis(0,0,-1), radius=1
|
||||
const gp_Ax2 anAx2(gp_Pnt(1., 0., 0.), gp_Dir(0., -1., 0.), gp_Dir(0., 0., -1.));
|
||||
Handle(Geom_Circle) aCircle = new Geom_Circle(anAx2, 1.0);
|
||||
|
||||
const double t1 = M_PI / 2.0; // 1.5707963267949
|
||||
const double t2 = 3.0 * M_PI / 2.0; // 4.71238898038469
|
||||
|
||||
Handle(Geom_TrimmedCurve) aTrimmed = new Geom_TrimmedCurve(aCircle, t1, t2);
|
||||
TopoDS_Edge anEdge = BRepBuilderAPI_MakeEdge(aTrimmed).Edge();
|
||||
|
||||
// Reverse the edge, then wrap it in a wire
|
||||
anEdge.Orientation(TopAbs_REVERSED);
|
||||
TopoDS_Wire aWire = BRepBuilderAPI_MakeWire(anEdge).Wire();
|
||||
|
||||
BRepAdaptor_CompCurve aBACC(aWire);
|
||||
const double aFirst = aBACC.FirstParameter();
|
||||
const double aLast = aBACC.LastParameter();
|
||||
|
||||
gp_Pnt aPFirst, aPLast;
|
||||
gp_Vec aVFirst, aVLast;
|
||||
aBACC.D1(aFirst, aPFirst, aVFirst);
|
||||
aBACC.D1(aLast, aPLast, aVLast);
|
||||
|
||||
if (aVFirst.SquareMagnitude() > gp::Resolution())
|
||||
aVFirst.Normalize();
|
||||
if (aVLast.SquareMagnitude() > gp::Resolution())
|
||||
aVLast.Normalize();
|
||||
|
||||
// Reference: inverse circle (normal = (0,1,0)), evaluated at the same parameters
|
||||
const gp_Ax2 anAx2Ref(gp_Pnt(1., 0., 0.), gp_Dir(0., 1., 0.), gp_Dir(0., 0., -1.));
|
||||
Handle(Geom_Circle) aCircleRef = new Geom_Circle(anAx2Ref, 1.0);
|
||||
|
||||
gp_Pnt aRefP1, aRefP2;
|
||||
gp_Vec aRefV1, aRefV2;
|
||||
aCircleRef->D1(t1, aRefP1, aRefV1);
|
||||
aCircleRef->D1(t2, aRefP2, aRefV2);
|
||||
if (aRefV1.SquareMagnitude() > gp::Resolution())
|
||||
aRefV1.Normalize();
|
||||
if (aRefV2.SquareMagnitude() > gp::Resolution())
|
||||
aRefV2.Normalize();
|
||||
|
||||
const double aTol = 1.e-7;
|
||||
EXPECT_NEAR(aPFirst.X(), aRefP1.X(), aTol) << "First point X";
|
||||
EXPECT_NEAR(aPFirst.Y(), aRefP1.Y(), aTol) << "First point Y";
|
||||
EXPECT_NEAR(aPFirst.Z(), aRefP1.Z(), aTol) << "First point Z";
|
||||
|
||||
EXPECT_NEAR(aVFirst.X(), aRefV1.X(), aTol) << "First tangent X";
|
||||
EXPECT_NEAR(aVFirst.Y(), aRefV1.Y(), aTol) << "First tangent Y";
|
||||
EXPECT_NEAR(aVFirst.Z(), aRefV1.Z(), aTol) << "First tangent Z";
|
||||
|
||||
EXPECT_NEAR(aPLast.X(), aRefP2.X(), aTol) << "Last point X";
|
||||
EXPECT_NEAR(aPLast.Y(), aRefP2.Y(), aTol) << "Last point Y";
|
||||
EXPECT_NEAR(aPLast.Z(), aRefP2.Z(), aTol) << "Last point Z";
|
||||
|
||||
EXPECT_NEAR(aVLast.X(), aRefV2.X(), aTol) << "Last tangent X";
|
||||
EXPECT_NEAR(aVLast.Y(), aRefV2.Y(), aTol) << "Last tangent Y";
|
||||
EXPECT_NEAR(aVLast.Z(), aRefV2.Z(), aTol) << "Last tangent Z";
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
#include <Geom_BSplineCurve.hxx>
|
||||
#include <Geom_BSplineSurface.hxx>
|
||||
#include <GeomAdaptor_Surface.hxx>
|
||||
#include <gp_Pnt.hxx>
|
||||
#include <gp_Vec.hxx>
|
||||
#include <gp_Trsf.hxx>
|
||||
@@ -932,3 +933,95 @@ TEST_F(Geom_BSplineSurface_Test, WeightsArray_Rational_ReturnsOwning)
|
||||
EXPECT_DOUBLE_EQ(aWeights(1, 1), 1.0);
|
||||
EXPECT_EQ(&aWeights, &aRational->WeightsArray());
|
||||
}
|
||||
|
||||
// OCC30990: Foundation Classes - unexpected change in numerical results on bsplines after 0029769
|
||||
// Verify that evaluating a B-Spline surface at a knot gives consistent results regardless of
|
||||
// which span was evaluated beforehand (i.e., the cache is updated correctly).
|
||||
TEST_F(Geom_BSplineSurface_Test, OCC30990_CacheConsistencyAtKnots)
|
||||
{
|
||||
// Build a degree-3 B-Spline surface with 3 interior knots in U (4 spans) and 2 in V (3 spans).
|
||||
// Poles: 7 x 5
|
||||
const int aNbU = 7;
|
||||
const int aNbV = 5;
|
||||
NCollection_Array2<gp_Pnt> aPoles(1, aNbU, 1, aNbV);
|
||||
for (int i = 1; i <= aNbU; ++i)
|
||||
for (int j = 1; j <= aNbV; ++j)
|
||||
aPoles(i, j) =
|
||||
gp_Pnt(static_cast<double>(i - 1),
|
||||
static_cast<double>(j - 1),
|
||||
std::sin(static_cast<double>(i) * 0.5) * std::cos(static_cast<double>(j) * 0.7));
|
||||
|
||||
// Knot vector in U: [0, 0.25, 0.5, 0.75, 1] with multiplicities [4, 1, 1, 1, 4]
|
||||
NCollection_Array1<double> aUKnots(1, 5);
|
||||
aUKnots(1) = 0.0;
|
||||
aUKnots(2) = 0.25;
|
||||
aUKnots(3) = 0.5;
|
||||
aUKnots(4) = 0.75;
|
||||
aUKnots(5) = 1.0;
|
||||
NCollection_Array1<int> aUMults(1, 5);
|
||||
aUMults(1) = 4;
|
||||
aUMults(2) = 1;
|
||||
aUMults(3) = 1;
|
||||
aUMults(4) = 1;
|
||||
aUMults(5) = 4;
|
||||
|
||||
// Knot vector in V: [0, 0.5, 1] with multiplicities [4, 1, 4]
|
||||
NCollection_Array1<double> aVKnots(1, 3);
|
||||
aVKnots(1) = 0.0;
|
||||
aVKnots(2) = 0.5;
|
||||
aVKnots(3) = 1.0;
|
||||
NCollection_Array1<int> aVMults(1, 3);
|
||||
aVMults(1) = 4;
|
||||
aVMults(2) = 1;
|
||||
aVMults(3) = 4;
|
||||
|
||||
const occ::handle<Geom_BSplineSurface> aSurf =
|
||||
new Geom_BSplineSurface(aPoles, aUKnots, aVKnots, aUMults, aVMults, 3, 3);
|
||||
ASSERT_FALSE(aSurf.IsNull());
|
||||
|
||||
GeomAdaptor_Surface aAdaptor(aSurf);
|
||||
|
||||
// For each interior U knot, verify that evaluation at the knot is consistent
|
||||
// regardless of whether the previous evaluation was in the span before or after.
|
||||
int aNbErr = 0;
|
||||
for (int i = 2; i < aSurf->NbUKnots(); ++i)
|
||||
{
|
||||
const double aUknot = aSurf->UKnot(i);
|
||||
const double aUprev = 0.5 * (aUknot + aSurf->UKnot(i - 1));
|
||||
const double aUnext = 0.5 * (aUknot + aSurf->UKnot(i + 1));
|
||||
|
||||
for (int j = 1; j < aSurf->NbVKnots(); ++j)
|
||||
{
|
||||
const double aV = 0.5 * (aSurf->VKnot(j) + aSurf->VKnot(j + 1));
|
||||
aAdaptor.Value(aUprev, aV); // populate cache from span before
|
||||
const gp_Pnt aP1 = aAdaptor.Value(aUknot, aV);
|
||||
aAdaptor.Value(aUnext, aV); // populate cache from span after
|
||||
const gp_Pnt aP2 = aAdaptor.Value(aUknot, aV);
|
||||
|
||||
if (aP1.X() != aP2.X() || aP1.Y() != aP2.Y() || aP1.Z() != aP2.Z())
|
||||
++aNbErr;
|
||||
}
|
||||
}
|
||||
|
||||
// Same check for interior V knots
|
||||
for (int j = 2; j < aSurf->NbVKnots(); ++j)
|
||||
{
|
||||
const double aVknot = aSurf->VKnot(j);
|
||||
const double aVprev = 0.5 * (aVknot + aSurf->VKnot(j - 1));
|
||||
const double aVnext = 0.5 * (aVknot + aSurf->VKnot(j + 1));
|
||||
|
||||
for (int i = 1; i < aSurf->NbUKnots(); ++i)
|
||||
{
|
||||
const double aU = 0.5 * (aSurf->UKnot(i) + aSurf->UKnot(i + 1));
|
||||
aAdaptor.Value(aU, aVprev);
|
||||
const gp_Pnt aP1 = aAdaptor.Value(aU, aVknot);
|
||||
aAdaptor.Value(aU, aVnext);
|
||||
const gp_Pnt aP2 = aAdaptor.Value(aU, aVknot);
|
||||
|
||||
if (aP1.X() != aP2.X() || aP1.Y() != aP2.Y() || aP1.Z() != aP2.Z())
|
||||
++aNbErr;
|
||||
}
|
||||
}
|
||||
|
||||
EXPECT_EQ(0, aNbErr) << "BSpline surface cache is inconsistent at span knots";
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include <gp_Trsf.hxx>
|
||||
#include <NCollection_Array1.hxx>
|
||||
#include <Precision.hxx>
|
||||
#include <Standard_Failure.hxx>
|
||||
|
||||
class Geom_BezierCurve_Test : public ::testing::Test
|
||||
{
|
||||
@@ -524,3 +525,29 @@ TEST_F(Geom_BezierCurve_Test, WeightsArray_Rational_ReturnsOwning)
|
||||
EXPECT_DOUBLE_EQ(aWeights(3), 1.0);
|
||||
EXPECT_EQ(&aWeights, &aRational->WeightsArray());
|
||||
}
|
||||
|
||||
// Test OCC2569: Geom_BezierCurve degree equals NbPoles - 1.
|
||||
// Migrated from QABugs_17.cxx OCC2569
|
||||
TEST(Geom_BezierCurveTest, OCC2569_DegreeEqualsNbPolesMinusOne)
|
||||
{
|
||||
const int aNbPoles = 26;
|
||||
NCollection_Array1<gp_Pnt> aPoles(1, aNbPoles);
|
||||
for (int i = 1; i <= aNbPoles; ++i)
|
||||
aPoles.SetValue(i, gp_Pnt(i + 10, i * 2 + 20, i * 3 + 45));
|
||||
|
||||
Handle(Geom_BezierCurve) aCurve = new Geom_BezierCurve(aPoles);
|
||||
ASSERT_FALSE(aCurve.IsNull());
|
||||
EXPECT_EQ(aCurve->Degree(), aNbPoles - 1);
|
||||
}
|
||||
|
||||
// Test OCC2569: Geom_BezierCurve throws when NbPoles exceeds maximum allowed.
|
||||
// Migrated from QABugs_17.cxx OCC2569 (bug2569_2)
|
||||
TEST(Geom_BezierCurveTest, OCC2569_ThrowsForTooManyPoles)
|
||||
{
|
||||
const int aNbPoles = 29;
|
||||
NCollection_Array1<gp_Pnt> aPoles(1, aNbPoles);
|
||||
for (int i = 1; i <= aNbPoles; ++i)
|
||||
aPoles.SetValue(i, gp_Pnt(i + 10, i * 2 + 20, i * 3 + 45));
|
||||
|
||||
EXPECT_THROW(new Geom_BezierCurve(aPoles), Standard_Failure);
|
||||
}
|
||||
|
||||
@@ -35,9 +35,11 @@ set(OCCT_TKGeomBase_GTests_FILES
|
||||
GC_MakeCircle2d_Test.cxx
|
||||
GC_MakeConicalSurface_Test.cxx
|
||||
GC_MakePlane_Test.cxx
|
||||
GC_MakeParabola2d_Test.cxx
|
||||
GC_MakeSegment2d_Test.cxx
|
||||
GCPnts_AbscissaPoint_Test.cxx
|
||||
GeomConvert_CompCurveToBSplineCurve_Test.cxx
|
||||
Geom2dConvert_CompCurveToBSplineCurve_Test.cxx
|
||||
GeomConvert_Test.cxx
|
||||
Hermit_Test.cxx
|
||||
IntAna_IntQuadQuad_Test.cxx
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
// 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 <GC_MakeParabola2d.hxx>
|
||||
#include <gp_Ax2d.hxx>
|
||||
#include <gp_Dir2d.hxx>
|
||||
#include <gp_Parab2d.hxx>
|
||||
#include <gp_Pnt2d.hxx>
|
||||
|
||||
namespace
|
||||
{
|
||||
// Helper: verify a parabola built from directrix+focus against expected values.
|
||||
void CheckParabola2d(const gp_Ax2d& theAxes,
|
||||
const gp_Pnt2d& theFocus,
|
||||
bool theSense,
|
||||
double theExpectedFocal,
|
||||
double theExpectedVertX,
|
||||
double theExpectedVertY,
|
||||
double theExpectedParam,
|
||||
const double theExpectedCoeffs[6])
|
||||
{
|
||||
const double aCompareTol = 1.0e-12;
|
||||
|
||||
GC_MakeParabola2d aPrb(theAxes, theFocus, theSense);
|
||||
ASSERT_FALSE(aPrb.Value().IsNull()) << "GC_MakeParabola2d should produce a non-null result";
|
||||
|
||||
const gp_Parab2d& aParab = aPrb.Value()->Parab2d();
|
||||
const gp_Pnt2d aVert(aParab.Location());
|
||||
|
||||
EXPECT_NEAR(aParab.Focal(), theExpectedFocal, aCompareTol) << "Wrong focal length";
|
||||
EXPECT_NEAR(aVert.X(), theExpectedVertX, aCompareTol) << "Wrong vertex X";
|
||||
EXPECT_NEAR(aVert.Y(), theExpectedVertY, aCompareTol) << "Wrong vertex Y";
|
||||
EXPECT_NEAR(aParab.Parameter(), theExpectedParam, aCompareTol) << "Wrong parameter";
|
||||
|
||||
double aF[6];
|
||||
aParab.Coefficients(aF[0], aF[1], aF[2], aF[3], aF[4], aF[5]);
|
||||
for (int i = 0; i < 6; ++i)
|
||||
{
|
||||
EXPECT_NEAR(aF[i], theExpectedCoeffs[i], aCompareTol)
|
||||
<< "Wrong coefficient [" << i << "]: got " << aF[i] << ", expected " << theExpectedCoeffs[i];
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
// Test OCC26747 (case 1): parabola with vertex at (0.5, 3.0) opening in +X direction.
|
||||
// Directrix Y-axis at x=0, y=3; focus at (1.0, 3.0); sense=true.
|
||||
// Equation: (y-3)^2 = 2*(x-0.5), i.e. 1*Y^2 + 2*(-1)*X + 2*(-3)*Y + 10 = 0.
|
||||
TEST(GC_MakeParabola2d_Test, OCC26747_1_ParabolaOpeningRight)
|
||||
{
|
||||
const gp_Ax2d anAxes(gp_Pnt2d(0.0, 3.0), gp_Dir2d(gp_Dir2d::D::Y));
|
||||
const gp_Pnt2d aFocus(1.0, 3.0);
|
||||
const double aCoeffs[6] = {0.0, 1.0, 0.0, -1.0, -3.0, 10.0};
|
||||
CheckParabola2d(anAxes, aFocus, true, 0.5, 0.5, 3.0, 1.0, aCoeffs);
|
||||
}
|
||||
|
||||
// Test OCC26747 (case 2): parabola with vertex at (-0.5, 3.0) opening in -X direction.
|
||||
// Directrix Y-axis at origin; focus at (-1.0, 3.0); sense=false.
|
||||
// Equation (WCS): (y-3)^2 = 2*(-x-0.5), i.e. 1*Y^2 + 2*1*X + 2*(-3)*Y + 10 = 0.
|
||||
TEST(GC_MakeParabola2d_Test, OCC26747_2_ParabolaOpeningLeft)
|
||||
{
|
||||
const gp_Ax2d anAxes(gp_Pnt2d(0.0, 0.0), gp_Dir2d(gp_Dir2d::D::Y));
|
||||
const gp_Pnt2d aFocus(-1.0, 3.0);
|
||||
const double aCoeffs[6] = {0.0, 1.0, 0.0, 1.0, -3.0, 10.0};
|
||||
CheckParabola2d(anAxes, aFocus, false, 0.5, -0.5, 3.0, 1.0, aCoeffs);
|
||||
}
|
||||
|
||||
// Test OCC26747 (case 3): degenerate parabola where focus coincides with vertex.
|
||||
// Directrix Y-axis at origin; focus at (0.0, 3.0); sense=false.
|
||||
// Focal length = 0, parameter = 0. Equation: Y^2 + 2*(-3)*Y + 9 = 0 (line y=3).
|
||||
TEST(GC_MakeParabola2d_Test, OCC26747_3_DegenerateParabola)
|
||||
{
|
||||
const gp_Ax2d anAxes(gp_Pnt2d(0.0, 0.0), gp_Dir2d(gp_Dir2d::D::Y));
|
||||
const gp_Pnt2d aFocus(0.0, 3.0);
|
||||
const double aCoeffs[6] = {0.0, 1.0, 0.0, 0.0, -3.0, 9.0};
|
||||
CheckParabola2d(anAxes, aFocus, false, 0.0, 0.0, 3.0, 0.0, aCoeffs);
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
// 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 <GC_MakeCircle2d.hxx>
|
||||
#include <Geom2d_BSplineCurve.hxx>
|
||||
#include <Geom2d_Circle.hxx>
|
||||
#include <Geom2d_TrimmedCurve.hxx>
|
||||
#include <Geom2dConvert_CompCurveToBSplineCurve.hxx>
|
||||
#include <Precision.hxx>
|
||||
#include <Standard_Handle.hxx>
|
||||
#include <gp_Pnt2d.hxx>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
TEST(Geom2dConvert_CompCurveToBSplineCurveTest, OCC30747_ClosedContourFromCircleArcs)
|
||||
{
|
||||
// OCC30747: 2d Curves concatenator must properly handle closed contours.
|
||||
// Split a full circle into 10 arcs and assemble them into a closed BSpline.
|
||||
const occ::handle<Geom2d_Circle> aCirc = GC_MakeCircle2d(gp_Pnt2d(0, 0), 50);
|
||||
ASSERT_FALSE(aCirc.IsNull());
|
||||
|
||||
const double aF = aCirc->FirstParameter();
|
||||
const double aL = aCirc->LastParameter();
|
||||
const int aNb = 10;
|
||||
const double aDelta = (aF + aL) / aNb;
|
||||
|
||||
occ::handle<Geom2d_TrimmedCurve> aFTrim = new Geom2d_TrimmedCurve(aCirc, aF, aDelta);
|
||||
Geom2dConvert_CompCurveToBSplineCurve aRes(aFTrim);
|
||||
|
||||
for (int anId = 1; anId < aNb; anId++)
|
||||
{
|
||||
occ::handle<Geom2d_TrimmedCurve> aLTrim;
|
||||
if (anId == (aNb - 1))
|
||||
{
|
||||
aLTrim = new Geom2d_TrimmedCurve(aCirc, anId * aDelta, aF);
|
||||
}
|
||||
else
|
||||
{
|
||||
aLTrim = new Geom2d_TrimmedCurve(aCirc, anId * aDelta, (anId + 1) * aDelta);
|
||||
}
|
||||
aRes.Add(aLTrim, Precision::PConfusion());
|
||||
}
|
||||
|
||||
const occ::handle<Geom2d_BSplineCurve> aBSpline = aRes.BSplineCurve();
|
||||
ASSERT_FALSE(aBSpline.IsNull());
|
||||
EXPECT_TRUE(aBSpline->IsClosed())
|
||||
<< "Assembled BSpline curve from closed circle arcs must be closed";
|
||||
}
|
||||
Reference in New Issue
Block a user