Loading files
// 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 <cmath>
#include <Adaptor3d_CurveOnSurface.hxx>
#include <Geom2dAdaptor_Curve.hxx>
#include <Geom2d_Ellipse.hxx>
#include <Geom2d_Line.hxx>
#include <GeomAdaptor_Curve.hxx>
#include <GeomAdaptor_Surface.hxx>
#include <GeomLib_CheckCurveOnSurface.hxx>
#include <Geom_Circle.hxx>
#include <Geom_CylindricalSurface.hxx>
#include <Geom_Line.hxx>
#include <Geom_Plane.hxx>
#include <Geom_ToroidalSurface.hxx>
#include <Precision.hxx>
#include <gp_Ax2.hxx>
#include <gp_Ax2d.hxx>
#include <gp_Ax3.hxx>
#include <gp_Dir.hxx>
#include <gp_Dir2d.hxx>
#include <gp_Pnt.hxx>
#include <gp_Pnt2d.hxx>
namespace
{
// Circle of radius theRadius at height theHeight on a cylinder of radius
// theCylRadius around OZ; the pcurve is the corresponding iso line in UV.
GeomLib_CheckCurveOnSurface makeCircleOnCylinderCheck(const double theCircRadius,
const double theCylRadius,
const double theHeight)
{
const double aFirst = 0.0, aLast = 2.0 * M_PI;
const occ::handle<Geom_Circle> aCirc = new Geom_Circle(
gp_Ax2(gp_Pnt(0.0, 0.0, theHeight), gp_Dir(0.0, 0.0, 1.0), gp_Dir(1.0, 0.0, 0.0)),
theCircRadius);
const occ::handle<GeomAdaptor_Curve> aC3d = new GeomAdaptor_Curve(aCirc, aFirst, aLast);
const occ::handle<Geom_CylindricalSurface> aCyl = new Geom_CylindricalSurface(
gp_Ax3(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(0.0, 0.0, 1.0), gp_Dir(1.0, 0.0, 0.0)),
theCylRadius);
const occ::handle<Geom2d_Line> aPLine =
new Geom2d_Line(gp_Pnt2d(0.0, theHeight), gp_Dir2d(1.0, 0.0));
const occ::handle<Geom2dAdaptor_Curve> aC2d = new Geom2dAdaptor_Curve(aPLine, aFirst, aLast);
const occ::handle<GeomAdaptor_Surface> aSurf = new GeomAdaptor_Surface(aCyl);
const occ::handle<Adaptor3d_CurveOnSurface> aCoS = new Adaptor3d_CurveOnSurface(aC2d, aSurf);
GeomLib_CheckCurveOnSurface aCheck;
aCheck.Init(aC3d, Precision::PConfusion());
aCheck.Perform(aCoS);
return aCheck;
}
GeomLib_CheckCurveOnSurface makeLineOnPlaneCheck(const gp_Dir& theCurveDirection,
const gp_Dir2d& thePCurveDirection,
const double theFirst,
const double theLast)
{
const occ::handle<Geom_Line> aLine = new Geom_Line(gp_Pnt(0.0, 0.0, 0.0), theCurveDirection);
const occ::handle<GeomAdaptor_Curve> aC3d = new GeomAdaptor_Curve(aLine, theFirst, theLast);
const occ::handle<Geom_Plane> aPlane =
new Geom_Plane(gp_Ax3(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(0.0, 0.0, 1.0), gp_Dir(1.0, 0.0, 0.0)));
const occ::handle<Geom2d_Line> aPLine = new Geom2d_Line(gp_Pnt2d(0.0, 0.0), thePCurveDirection);
const occ::handle<Geom2dAdaptor_Curve> aC2d = new Geom2dAdaptor_Curve(aPLine, theFirst, theLast);
const occ::handle<GeomAdaptor_Surface> aSurf = new GeomAdaptor_Surface(aPlane);
const occ::handle<Adaptor3d_CurveOnSurface> aCoS = new Adaptor3d_CurveOnSurface(aC2d, aSurf);
GeomLib_CheckCurveOnSurface aCheck;
aCheck.Init(aC3d, Precision::PConfusion());
aCheck.Perform(aCoS);
return aCheck;
}
GeomLib_CheckCurveOnSurface makeCircleAndEllipseCheck(const double theMajorRadius,
const double theMinorRadius,
const double theFirst,
const double theLast)
{
const occ::handle<Geom_Circle> aCircle =
new Geom_Circle(gp_Ax2(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(0.0, 0.0, 1.0), gp_Dir(1.0, 0.0, 0.0)),
2.0);
const occ::handle<GeomAdaptor_Curve> aC3d = new GeomAdaptor_Curve(aCircle, theFirst, theLast);
const occ::handle<Geom2d_Ellipse> anEllipse =
new Geom2d_Ellipse(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)),
theMajorRadius,
theMinorRadius);
const occ::handle<Geom2dAdaptor_Curve> aC2d =
new Geom2dAdaptor_Curve(anEllipse, theFirst, theLast);
const occ::handle<Geom_Plane> aPlane =
new Geom_Plane(gp_Ax3(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(0.0, 0.0, 1.0), gp_Dir(1.0, 0.0, 0.0)));
const occ::handle<GeomAdaptor_Surface> aSurf = new GeomAdaptor_Surface(aPlane);
const occ::handle<Adaptor3d_CurveOnSurface> aCoS = new Adaptor3d_CurveOnSurface(aC2d, aSurf);
GeomLib_CheckCurveOnSurface aCheck;
aCheck.Init(aC3d, Precision::PConfusion());
aCheck.Perform(aCoS);
return aCheck;
}
} // namespace
TEST(GeomLib_CheckCurveOnSurfaceTest, AnalyticCoincident_ReportsZeroDeviation)
{
const GeomLib_CheckCurveOnSurface aCheck = makeCircleOnCylinderCheck(2.0, 2.0, 5.0);
EXPECT_TRUE(aCheck.IsDone());
EXPECT_LE(aCheck.MaxDistance(), Precision::Confusion());
}
TEST(GeomLib_CheckCurveOnSurfaceTest, AnalyticDeviating_ReportsActualDeviation)
{
// The 3D circle is 0.05 smaller than the cylinder carrying the pcurve: the
// deviation is constant and equal to the radius difference. This guards the
// constant-distance shortcut against swallowing real deviations.
const GeomLib_CheckCurveOnSurface aCheck = makeCircleOnCylinderCheck(1.95, 2.0, 5.0);
EXPECT_TRUE(aCheck.IsDone());
EXPECT_NEAR(aCheck.MaxDistance(), 0.05, 1.0e-9);
}
TEST(GeomLib_CheckCurveOnSurfaceTest, LineOnPlane_ReportsZeroDeviation)
{
const GeomLib_CheckCurveOnSurface aCheck =
makeLineOnPlaneCheck(gp_Dir(1.0, 0.0, 0.0), gp_Dir2d(1.0, 0.0), -10.0, 10.0);
EXPECT_TRUE(aCheck.IsDone());
EXPECT_LE(aCheck.MaxDistance(), Precision::Confusion());
}
TEST(GeomLib_CheckCurveOnSurfaceTest, DeviatingLines_ReportsEndpointMaximum)
{
const GeomLib_CheckCurveOnSurface aCheck =
makeLineOnPlaneCheck(gp_Dir(1.0, 0.0, 0.0), gp_Dir2d(0.0, 1.0), -2.0, 3.0);
ASSERT_TRUE(aCheck.IsDone());
EXPECT_NEAR(aCheck.MaxDistance(), std::sqrt(18.0), Precision::Confusion());
EXPECT_DOUBLE_EQ(aCheck.MaxParameter(), 3.0);
}
TEST(GeomLib_CheckCurveOnSurfaceTest, CircleAndEllipse_ReportsAnalyticMaximum)
{
const GeomLib_CheckCurveOnSurface aCheck = makeCircleAndEllipseCheck(4.0, 1.0, 0.0, 2.0 * M_PI);
ASSERT_TRUE(aCheck.IsDone());
EXPECT_NEAR(aCheck.MaxDistance(), 2.0, Precision::Confusion());
}
TEST(GeomLib_CheckCurveOnSurfaceTest, NegativeTrim_ReportsInteriorMaximum)
{
const GeomLib_CheckCurveOnSurface aCheck = makeCircleAndEllipseCheck(2.0, 1.0, -2.0, -1.0);
ASSERT_TRUE(aCheck.IsDone());
EXPECT_NEAR(aCheck.MaxDistance(), 1.0, Precision::Confusion());
EXPECT_NEAR(aCheck.MaxParameter(), -0.5 * M_PI, Precision::PConfusion());
}
TEST(GeomLib_CheckCurveOnSurfaceTest, AnalyticAliasing_ReportsActualDeviation)
{
const double aFirst = 0.0, aLast = 80.0 * M_PI;
const occ::handle<Geom_Circle> aCircle =
new Geom_Circle(gp_Ax2(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(0.0, 0.0, 1.0), gp_Dir(1.0, 0.0, 0.0)),
4.0);
const occ::handle<GeomAdaptor_Curve> aC3d = new GeomAdaptor_Curve(aCircle, aFirst, aLast);
const occ::handle<Geom_ToroidalSurface> aTorus = new Geom_ToroidalSurface(
gp_Ax3(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(0.0, 0.0, 1.0), gp_Dir(1.0, 0.0, 0.0)),
3.0,
1.0);
const occ::handle<Geom2d_Line> aPLine = new Geom2d_Line(gp_Pnt2d(0.0, 0.0), gp_Dir2d(3.0, 4.0));
const occ::handle<Geom2dAdaptor_Curve> aC2d = new Geom2dAdaptor_Curve(aPLine, aFirst, aLast);
const occ::handle<GeomAdaptor_Surface> aSurf = new GeomAdaptor_Surface(aTorus);
const occ::handle<Adaptor3d_CurveOnSurface> aCoS = new Adaptor3d_CurveOnSurface(aC2d, aSurf);
GeomLib_CheckCurveOnSurface aCheck;
aCheck.Init(aC3d, Precision::PConfusion());
aCheck.Perform(aCoS);
ASSERT_TRUE(aCheck.IsDone());
EXPECT_NEAR(aCheck.MaxDistance(), 8.0, Precision::Confusion());
}
3d097a032This file is pinned to the selected release. Download the original to open it in your design tool.