From c4715e0e72c698a0e1c1f8c81fdfd3e07769a8f1 Mon Sep 17 00:00:00 2001 From: Pasukhin Dmitry Date: Mon, 9 Mar 2026 21:03:18 +0000 Subject: [PATCH] Modeling - Remove GeomProp modules (#1154) - Deleted GeomProp_Surface, GeomProp_SurfaceAnalysisTools, GeomProp_SurfaceOfExtrusion, GeomProp_SurfaceOfRevolution, and GeomProp_Torus classes along with their implementation files. - Removed references to the GeomProp module from the CMake package configuration. --- .../TKBRep/BRepProp/BRepProp_Curve.cxx | 258 --- .../TKBRep/BRepProp/BRepProp_Curve.hxx | 139 -- .../TKBRep/BRepProp/BRepProp_Surface.cxx | 115 -- .../TKBRep/BRepProp/BRepProp_Surface.hxx | 119 -- src/ModelingData/TKBRep/BRepProp/FILES.cmake | 9 - .../TKBRep/GTests/BRepProp_Test.cxx | 290 --- .../GTests/BRepProp_VsBRepLProp_Test.cxx | 329 ---- src/ModelingData/TKBRep/GTests/FILES.cmake | 2 - src/ModelingData/TKBRep/PACKAGES.cmake | 1 - src/ModelingData/TKG2d/GTests/FILES.cmake | 12 - .../GTests/Geom2dProp_BSplineCurve_Test.cxx | 588 ------ .../GTests/Geom2dProp_BezierCurve_Test.cxx | 534 ------ .../TKG2d/GTests/Geom2dProp_Circle_Test.cxx | 444 ----- .../TKG2d/GTests/Geom2dProp_Ellipse_Test.cxx | 496 ------ .../GTests/Geom2dProp_Hyperbola_Test.cxx | 481 ----- .../TKG2d/GTests/Geom2dProp_Line_Test.cxx | 400 ----- .../GTests/Geom2dProp_OffsetCurve_Test.cxx | 525 ------ .../GTests/Geom2dProp_OtherCurve_Test.cxx | 516 ------ .../TKG2d/GTests/Geom2dProp_Parabola_Test.cxx | 482 ----- .../TKG2d/GTests/Geom2dProp_Test.cxx | 1586 ----------------- .../GTests/Geom2dProp_VsCLProps2d_Test.cxx | 580 ------ .../TKG2d/GTests/Geom2dProp_VsLProp_Test.cxx | 660 ------- src/ModelingData/TKG2d/Geom2dProp/FILES.cmake | 26 - .../TKG2d/Geom2dProp/Geom2dProp.cxx | 164 -- .../TKG2d/Geom2dProp/Geom2dProp.hxx | 201 --- .../Geom2dProp/Geom2dProp_BSplineCurve.cxx | 125 -- .../Geom2dProp/Geom2dProp_BSplineCurve.hxx | 109 -- .../Geom2dProp/Geom2dProp_BezierCurve.cxx | 124 -- .../Geom2dProp/Geom2dProp_BezierCurve.hxx | 105 -- .../TKG2d/Geom2dProp/Geom2dProp_Circle.hxx | 164 -- .../TKG2d/Geom2dProp/Geom2dProp_Curve.cxx | 551 ------ .../TKG2d/Geom2dProp/Geom2dProp_Curve.hxx | 199 --- .../Geom2dProp_CurveAnalysisTools.pxx | 785 -------- .../TKG2d/Geom2dProp/Geom2dProp_Ellipse.cxx | 165 -- .../TKG2d/Geom2dProp/Geom2dProp_Ellipse.hxx | 104 -- .../TKG2d/Geom2dProp/Geom2dProp_Hyperbola.cxx | 141 -- .../TKG2d/Geom2dProp/Geom2dProp_Hyperbola.hxx | 105 -- .../TKG2d/Geom2dProp/Geom2dProp_Line.hxx | 140 -- .../Geom2dProp/Geom2dProp_OffsetCurve.cxx | 123 -- .../Geom2dProp/Geom2dProp_OffsetCurve.hxx | 106 -- .../Geom2dProp/Geom2dProp_OtherCurve.cxx | 123 -- .../Geom2dProp/Geom2dProp_OtherCurve.hxx | 106 -- .../TKG2d/Geom2dProp/Geom2dProp_Parabola.cxx | 141 -- .../TKG2d/Geom2dProp/Geom2dProp_Parabola.hxx | 103 -- src/ModelingData/TKG2d/PACKAGES.cmake | 1 - src/ModelingData/TKG3d/GTests/FILES.cmake | 23 - .../GTests/GeomProp_BSplineCurve_Test.cxx | 529 ------ .../GTests/GeomProp_BSplineSurface_Test.cxx | 471 ----- .../GTests/GeomProp_BezierCurve_Test.cxx | 469 ----- .../GTests/GeomProp_BezierSurface_Test.cxx | 459 ----- .../TKG3d/GTests/GeomProp_Circle_Test.cxx | 440 ----- .../TKG3d/GTests/GeomProp_Cone_Test.cxx | 407 ----- .../TKG3d/GTests/GeomProp_Cylinder_Test.cxx | 397 ----- .../TKG3d/GTests/GeomProp_Ellipse_Test.cxx | 474 ----- .../TKG3d/GTests/GeomProp_Hyperbola_Test.cxx | 429 ----- .../TKG3d/GTests/GeomProp_Line_Test.cxx | 398 ----- .../GTests/GeomProp_OffsetCurve_Test.cxx | 441 ----- .../GTests/GeomProp_OffsetSurface_Test.cxx | 418 ----- .../TKG3d/GTests/GeomProp_OtherCurve_Test.cxx | 433 ----- .../GTests/GeomProp_OtherSurface_Test.cxx | 391 ---- .../TKG3d/GTests/GeomProp_Parabola_Test.cxx | 425 ----- .../TKG3d/GTests/GeomProp_Plane_Test.cxx | 371 ---- .../TKG3d/GTests/GeomProp_Sphere_Test.cxx | 440 ----- .../GeomProp_SurfaceOfExtrusion_Test.cxx | 414 ----- .../GeomProp_SurfaceOfRevolution_Test.cxx | 405 ----- .../TKG3d/GTests/GeomProp_Test.cxx | 563 ------ .../TKG3d/GTests/GeomProp_Torus_Test.cxx | 416 ----- .../TKG3d/GTests/GeomProp_VsCLProps_Test.cxx | 244 --- .../TKG3d/GTests/GeomProp_VsSLProps_Test.cxx | 210 --- src/ModelingData/TKG3d/GeomProp/FILES.cmake | 48 - src/ModelingData/TKG3d/GeomProp/GeomProp.cxx | 446 ----- src/ModelingData/TKG3d/GeomProp/GeomProp.hxx | 331 ---- .../TKG3d/GeomProp/GeomProp_BSplineCurve.cxx | 125 -- .../TKG3d/GeomProp/GeomProp_BSplineCurve.hxx | 107 -- .../GeomProp/GeomProp_BSplineSurface.cxx | 84 - .../GeomProp/GeomProp_BSplineSurface.hxx | 100 -- .../TKG3d/GeomProp/GeomProp_BezierCurve.cxx | 124 -- .../TKG3d/GeomProp/GeomProp_BezierCurve.hxx | 103 -- .../TKG3d/GeomProp/GeomProp_BezierSurface.cxx | 84 - .../TKG3d/GeomProp/GeomProp_BezierSurface.hxx | 100 -- .../TKG3d/GeomProp/GeomProp_Circle.hxx | 164 -- .../TKG3d/GeomProp/GeomProp_Cone.cxx | 83 - .../TKG3d/GeomProp/GeomProp_Cone.hxx | 100 -- .../TKG3d/GeomProp/GeomProp_Curve.cxx | 550 ------ .../TKG3d/GeomProp/GeomProp_Curve.hxx | 200 --- .../GeomProp/GeomProp_CurveAnalysisTools.pxx | 795 --------- .../TKG3d/GeomProp/GeomProp_Cylinder.hxx | 143 -- .../TKG3d/GeomProp/GeomProp_Ellipse.cxx | 163 -- .../TKG3d/GeomProp/GeomProp_Ellipse.hxx | 104 -- .../TKG3d/GeomProp/GeomProp_Hyperbola.cxx | 140 -- .../TKG3d/GeomProp/GeomProp_Hyperbola.hxx | 103 -- .../TKG3d/GeomProp/GeomProp_Line.hxx | 140 -- .../TKG3d/GeomProp/GeomProp_OffsetCurve.cxx | 123 -- .../TKG3d/GeomProp/GeomProp_OffsetCurve.hxx | 104 -- .../TKG3d/GeomProp/GeomProp_OffsetSurface.cxx | 84 - .../TKG3d/GeomProp/GeomProp_OffsetSurface.hxx | 100 -- .../TKG3d/GeomProp/GeomProp_OtherCurve.cxx | 122 -- .../TKG3d/GeomProp/GeomProp_OtherCurve.hxx | 104 -- .../TKG3d/GeomProp/GeomProp_OtherSurface.cxx | 84 - .../TKG3d/GeomProp/GeomProp_OtherSurface.hxx | 100 -- .../TKG3d/GeomProp/GeomProp_Parabola.cxx | 139 -- .../TKG3d/GeomProp/GeomProp_Parabola.hxx | 103 -- .../TKG3d/GeomProp/GeomProp_Plane.hxx | 137 -- .../TKG3d/GeomProp/GeomProp_Sphere.hxx | 142 -- .../TKG3d/GeomProp/GeomProp_Surface.cxx | 329 ---- .../TKG3d/GeomProp/GeomProp_Surface.hxx | 171 -- .../GeomProp_SurfaceAnalysisTools.pxx | 181 -- .../GeomProp/GeomProp_SurfaceOfExtrusion.cxx | 84 - .../GeomProp/GeomProp_SurfaceOfExtrusion.hxx | 100 -- .../GeomProp/GeomProp_SurfaceOfRevolution.cxx | 84 - .../GeomProp/GeomProp_SurfaceOfRevolution.hxx | 100 -- .../TKG3d/GeomProp/GeomProp_Torus.cxx | 83 - .../TKG3d/GeomProp/GeomProp_Torus.hxx | 99 - src/ModelingData/TKG3d/PACKAGES.cmake | 1 - 114 files changed, 29055 deletions(-) delete mode 100644 src/ModelingData/TKBRep/BRepProp/BRepProp_Curve.cxx delete mode 100644 src/ModelingData/TKBRep/BRepProp/BRepProp_Curve.hxx delete mode 100644 src/ModelingData/TKBRep/BRepProp/BRepProp_Surface.cxx delete mode 100644 src/ModelingData/TKBRep/BRepProp/BRepProp_Surface.hxx delete mode 100644 src/ModelingData/TKBRep/BRepProp/FILES.cmake delete mode 100644 src/ModelingData/TKBRep/GTests/BRepProp_Test.cxx delete mode 100644 src/ModelingData/TKBRep/GTests/BRepProp_VsBRepLProp_Test.cxx delete mode 100644 src/ModelingData/TKG2d/GTests/Geom2dProp_BSplineCurve_Test.cxx delete mode 100644 src/ModelingData/TKG2d/GTests/Geom2dProp_BezierCurve_Test.cxx delete mode 100644 src/ModelingData/TKG2d/GTests/Geom2dProp_Circle_Test.cxx delete mode 100644 src/ModelingData/TKG2d/GTests/Geom2dProp_Ellipse_Test.cxx delete mode 100644 src/ModelingData/TKG2d/GTests/Geom2dProp_Hyperbola_Test.cxx delete mode 100644 src/ModelingData/TKG2d/GTests/Geom2dProp_Line_Test.cxx delete mode 100644 src/ModelingData/TKG2d/GTests/Geom2dProp_OffsetCurve_Test.cxx delete mode 100644 src/ModelingData/TKG2d/GTests/Geom2dProp_OtherCurve_Test.cxx delete mode 100644 src/ModelingData/TKG2d/GTests/Geom2dProp_Parabola_Test.cxx delete mode 100644 src/ModelingData/TKG2d/GTests/Geom2dProp_Test.cxx delete mode 100644 src/ModelingData/TKG2d/GTests/Geom2dProp_VsCLProps2d_Test.cxx delete mode 100644 src/ModelingData/TKG2d/GTests/Geom2dProp_VsLProp_Test.cxx delete mode 100644 src/ModelingData/TKG2d/Geom2dProp/FILES.cmake delete mode 100644 src/ModelingData/TKG2d/Geom2dProp/Geom2dProp.cxx delete mode 100644 src/ModelingData/TKG2d/Geom2dProp/Geom2dProp.hxx delete mode 100644 src/ModelingData/TKG2d/Geom2dProp/Geom2dProp_BSplineCurve.cxx delete mode 100644 src/ModelingData/TKG2d/Geom2dProp/Geom2dProp_BSplineCurve.hxx delete mode 100644 src/ModelingData/TKG2d/Geom2dProp/Geom2dProp_BezierCurve.cxx delete mode 100644 src/ModelingData/TKG2d/Geom2dProp/Geom2dProp_BezierCurve.hxx delete mode 100644 src/ModelingData/TKG2d/Geom2dProp/Geom2dProp_Circle.hxx delete mode 100644 src/ModelingData/TKG2d/Geom2dProp/Geom2dProp_Curve.cxx delete mode 100644 src/ModelingData/TKG2d/Geom2dProp/Geom2dProp_Curve.hxx delete mode 100644 src/ModelingData/TKG2d/Geom2dProp/Geom2dProp_CurveAnalysisTools.pxx delete mode 100644 src/ModelingData/TKG2d/Geom2dProp/Geom2dProp_Ellipse.cxx delete mode 100644 src/ModelingData/TKG2d/Geom2dProp/Geom2dProp_Ellipse.hxx delete mode 100644 src/ModelingData/TKG2d/Geom2dProp/Geom2dProp_Hyperbola.cxx delete mode 100644 src/ModelingData/TKG2d/Geom2dProp/Geom2dProp_Hyperbola.hxx delete mode 100644 src/ModelingData/TKG2d/Geom2dProp/Geom2dProp_Line.hxx delete mode 100644 src/ModelingData/TKG2d/Geom2dProp/Geom2dProp_OffsetCurve.cxx delete mode 100644 src/ModelingData/TKG2d/Geom2dProp/Geom2dProp_OffsetCurve.hxx delete mode 100644 src/ModelingData/TKG2d/Geom2dProp/Geom2dProp_OtherCurve.cxx delete mode 100644 src/ModelingData/TKG2d/Geom2dProp/Geom2dProp_OtherCurve.hxx delete mode 100644 src/ModelingData/TKG2d/Geom2dProp/Geom2dProp_Parabola.cxx delete mode 100644 src/ModelingData/TKG2d/Geom2dProp/Geom2dProp_Parabola.hxx delete mode 100644 src/ModelingData/TKG3d/GTests/GeomProp_BSplineCurve_Test.cxx delete mode 100644 src/ModelingData/TKG3d/GTests/GeomProp_BSplineSurface_Test.cxx delete mode 100644 src/ModelingData/TKG3d/GTests/GeomProp_BezierCurve_Test.cxx delete mode 100644 src/ModelingData/TKG3d/GTests/GeomProp_BezierSurface_Test.cxx delete mode 100644 src/ModelingData/TKG3d/GTests/GeomProp_Circle_Test.cxx delete mode 100644 src/ModelingData/TKG3d/GTests/GeomProp_Cone_Test.cxx delete mode 100644 src/ModelingData/TKG3d/GTests/GeomProp_Cylinder_Test.cxx delete mode 100644 src/ModelingData/TKG3d/GTests/GeomProp_Ellipse_Test.cxx delete mode 100644 src/ModelingData/TKG3d/GTests/GeomProp_Hyperbola_Test.cxx delete mode 100644 src/ModelingData/TKG3d/GTests/GeomProp_Line_Test.cxx delete mode 100644 src/ModelingData/TKG3d/GTests/GeomProp_OffsetCurve_Test.cxx delete mode 100644 src/ModelingData/TKG3d/GTests/GeomProp_OffsetSurface_Test.cxx delete mode 100644 src/ModelingData/TKG3d/GTests/GeomProp_OtherCurve_Test.cxx delete mode 100644 src/ModelingData/TKG3d/GTests/GeomProp_OtherSurface_Test.cxx delete mode 100644 src/ModelingData/TKG3d/GTests/GeomProp_Parabola_Test.cxx delete mode 100644 src/ModelingData/TKG3d/GTests/GeomProp_Plane_Test.cxx delete mode 100644 src/ModelingData/TKG3d/GTests/GeomProp_Sphere_Test.cxx delete mode 100644 src/ModelingData/TKG3d/GTests/GeomProp_SurfaceOfExtrusion_Test.cxx delete mode 100644 src/ModelingData/TKG3d/GTests/GeomProp_SurfaceOfRevolution_Test.cxx delete mode 100644 src/ModelingData/TKG3d/GTests/GeomProp_Test.cxx delete mode 100644 src/ModelingData/TKG3d/GTests/GeomProp_Torus_Test.cxx delete mode 100644 src/ModelingData/TKG3d/GTests/GeomProp_VsCLProps_Test.cxx delete mode 100644 src/ModelingData/TKG3d/GTests/GeomProp_VsSLProps_Test.cxx delete mode 100644 src/ModelingData/TKG3d/GeomProp/FILES.cmake delete mode 100644 src/ModelingData/TKG3d/GeomProp/GeomProp.cxx delete mode 100644 src/ModelingData/TKG3d/GeomProp/GeomProp.hxx delete mode 100644 src/ModelingData/TKG3d/GeomProp/GeomProp_BSplineCurve.cxx delete mode 100644 src/ModelingData/TKG3d/GeomProp/GeomProp_BSplineCurve.hxx delete mode 100644 src/ModelingData/TKG3d/GeomProp/GeomProp_BSplineSurface.cxx delete mode 100644 src/ModelingData/TKG3d/GeomProp/GeomProp_BSplineSurface.hxx delete mode 100644 src/ModelingData/TKG3d/GeomProp/GeomProp_BezierCurve.cxx delete mode 100644 src/ModelingData/TKG3d/GeomProp/GeomProp_BezierCurve.hxx delete mode 100644 src/ModelingData/TKG3d/GeomProp/GeomProp_BezierSurface.cxx delete mode 100644 src/ModelingData/TKG3d/GeomProp/GeomProp_BezierSurface.hxx delete mode 100644 src/ModelingData/TKG3d/GeomProp/GeomProp_Circle.hxx delete mode 100644 src/ModelingData/TKG3d/GeomProp/GeomProp_Cone.cxx delete mode 100644 src/ModelingData/TKG3d/GeomProp/GeomProp_Cone.hxx delete mode 100644 src/ModelingData/TKG3d/GeomProp/GeomProp_Curve.cxx delete mode 100644 src/ModelingData/TKG3d/GeomProp/GeomProp_Curve.hxx delete mode 100644 src/ModelingData/TKG3d/GeomProp/GeomProp_CurveAnalysisTools.pxx delete mode 100644 src/ModelingData/TKG3d/GeomProp/GeomProp_Cylinder.hxx delete mode 100644 src/ModelingData/TKG3d/GeomProp/GeomProp_Ellipse.cxx delete mode 100644 src/ModelingData/TKG3d/GeomProp/GeomProp_Ellipse.hxx delete mode 100644 src/ModelingData/TKG3d/GeomProp/GeomProp_Hyperbola.cxx delete mode 100644 src/ModelingData/TKG3d/GeomProp/GeomProp_Hyperbola.hxx delete mode 100644 src/ModelingData/TKG3d/GeomProp/GeomProp_Line.hxx delete mode 100644 src/ModelingData/TKG3d/GeomProp/GeomProp_OffsetCurve.cxx delete mode 100644 src/ModelingData/TKG3d/GeomProp/GeomProp_OffsetCurve.hxx delete mode 100644 src/ModelingData/TKG3d/GeomProp/GeomProp_OffsetSurface.cxx delete mode 100644 src/ModelingData/TKG3d/GeomProp/GeomProp_OffsetSurface.hxx delete mode 100644 src/ModelingData/TKG3d/GeomProp/GeomProp_OtherCurve.cxx delete mode 100644 src/ModelingData/TKG3d/GeomProp/GeomProp_OtherCurve.hxx delete mode 100644 src/ModelingData/TKG3d/GeomProp/GeomProp_OtherSurface.cxx delete mode 100644 src/ModelingData/TKG3d/GeomProp/GeomProp_OtherSurface.hxx delete mode 100644 src/ModelingData/TKG3d/GeomProp/GeomProp_Parabola.cxx delete mode 100644 src/ModelingData/TKG3d/GeomProp/GeomProp_Parabola.hxx delete mode 100644 src/ModelingData/TKG3d/GeomProp/GeomProp_Plane.hxx delete mode 100644 src/ModelingData/TKG3d/GeomProp/GeomProp_Sphere.hxx delete mode 100644 src/ModelingData/TKG3d/GeomProp/GeomProp_Surface.cxx delete mode 100644 src/ModelingData/TKG3d/GeomProp/GeomProp_Surface.hxx delete mode 100644 src/ModelingData/TKG3d/GeomProp/GeomProp_SurfaceAnalysisTools.pxx delete mode 100644 src/ModelingData/TKG3d/GeomProp/GeomProp_SurfaceOfExtrusion.cxx delete mode 100644 src/ModelingData/TKG3d/GeomProp/GeomProp_SurfaceOfExtrusion.hxx delete mode 100644 src/ModelingData/TKG3d/GeomProp/GeomProp_SurfaceOfRevolution.cxx delete mode 100644 src/ModelingData/TKG3d/GeomProp/GeomProp_SurfaceOfRevolution.hxx delete mode 100644 src/ModelingData/TKG3d/GeomProp/GeomProp_Torus.cxx delete mode 100644 src/ModelingData/TKG3d/GeomProp/GeomProp_Torus.hxx diff --git a/src/ModelingData/TKBRep/BRepProp/BRepProp_Curve.cxx b/src/ModelingData/TKBRep/BRepProp/BRepProp_Curve.cxx deleted file mode 100644 index dffad1ef18..0000000000 --- a/src/ModelingData/TKBRep/BRepProp/BRepProp_Curve.cxx +++ /dev/null @@ -1,258 +0,0 @@ -// 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 - -#include -#include -#include -#include -#include -#include - -//================================================================================================= - -BRepProp_Curve::BRepProp_Curve(const TopoDS_Edge& theEdge) -{ - initialization(theEdge); -} - -//================================================================================================= - -BRepProp_Curve::BRepProp_Curve(const BRepAdaptor_Curve& theCurve) -{ - initialization(theCurve); -} - -//================================================================================================= - -BRepProp_Curve::BRepProp_Curve(const occ::handle& theCurve) -{ - initialization(theCurve); -} - -//================================================================================================= - -void BRepProp_Curve::initialization(const TopoDS_Edge& theEdge) -{ - if (theEdge.IsNull()) - { - myOwned.Nullify(); - myPtr = nullptr; - return; - } - myOwned = new BRepAdaptor_Curve(theEdge); - myPtr = myOwned.get(); -} - -//================================================================================================= - -void BRepProp_Curve::initialization(const BRepAdaptor_Curve& theCurve) -{ - myOwned.Nullify(); - myPtr = &theCurve; -} - -//================================================================================================= - -void BRepProp_Curve::initialization(const occ::handle& theCurve) -{ - myOwned = theCurve; - myPtr = myOwned.get(); -} - -//================================================================================================= - -GeomProp::TangentResult BRepProp_Curve::Tangent(const double theParam, const double theTol) const -{ - gp_Pnt aPnt; - gp_Vec aD1, aD2, aD3; - myPtr->D3(theParam, aPnt, aD1, aD2, aD3); - - // If D1 is non-null, use it directly (no sign ambiguity). - if (aD1.SquareMagnitude() > theTol * theTol) - { - return {gp_Dir(aD1), true}; - } - - // D1 is null: sample nearby D0 points for sign correction of higher derivatives. - constexpr double THE_DIV_FACTOR = 1.e-3; - constexpr double THE_MIN_STEP = 1.e-7; - const double anUFirst = myPtr->FirstParameter(); - const double anULast = myPtr->LastParameter(); - double aDu = 0.0; - if (anULast < RealLast() && anUFirst > RealFirst()) - aDu = anULast - anUFirst; - const double aDelta = std::max(aDu * THE_DIV_FACTOR, THE_MIN_STEP); - const double aU = (theParam - anUFirst < aDelta) ? theParam + aDelta : theParam - aDelta; - - gp_Pnt aP1, aP2; - myPtr->D0(std::min(theParam, aU), aP1); - myPtr->D0(std::max(theParam, aU), aP2); - return GeomProp::ComputeTangent(aD1, aD2, aD3, theTol, aP1, aP2); -} - -//================================================================================================= - -GeomProp::CurvatureResult BRepProp_Curve::Curvature(const double theParam, - const double theTol) const -{ - gp_Pnt aPnt; - gp_Vec aD1, aD2; - myPtr->D2(theParam, aPnt, aD1, aD2); - return GeomProp::ComputeCurvature(aD1, aD2, theTol); -} - -//================================================================================================= - -GeomProp::NormalResult BRepProp_Curve::Normal(const double theParam, const double theTol) const -{ - gp_Pnt aPnt; - gp_Vec aD1, aD2; - myPtr->D2(theParam, aPnt, aD1, aD2); - return GeomProp::ComputeNormal(aD1, aD2, theTol); -} - -//================================================================================================= - -GeomProp::CentreResult BRepProp_Curve::CentreOfCurvature(const double theParam, - const double theTol) const -{ - gp_Pnt aPnt; - gp_Vec aD1, aD2; - myPtr->D2(theParam, aPnt, aD1, aD2); - return GeomProp::ComputeCentreOfCurvature(aPnt, aD1, aD2, theTol); -} - -//================================================================================================= - -GeomAbs_Shape BRepProp_Curve::Continuity(const BRepAdaptor_Curve& theCurve1, - const BRepAdaptor_Curve& theCurve2, - const double theU1, - const double theU2, - const double theTolLinear, - const double theTolAngular) -{ - GeomAbs_Shape aCont = GeomAbs_C0; - bool isChecked = false; - - // Determine maximum derivative order for each curve. - const GeomAbs_Shape aCont1 = theCurve1.Continuity(); - const GeomAbs_Shape aCont2 = theCurve2.Continuity(); - int aN1 = 0; - int aN2 = 0; - if (aCont1 >= 5) - aN1 = 3; - else if (aCont1 == 4) - aN1 = 2; - else if (aCont1 >= 2) - aN1 = 1; - if (aCont2 >= 5) - aN2 = 3; - else if (aCont2 == 4) - aN2 = 2; - else if (aCont2 >= 2) - aN2 = 1; - - // Evaluate properties at junction points. - BRepProp_Curve aProp1(theCurve1); - BRepProp_Curve aProp2(theCurve2); - - // Check point coincidence. - gp_Pnt aPnt1, aPnt2; - gp_Vec aD1_1, aD1_2; - theCurve1.D1(theU1, aPnt1, aD1_1); - theCurve2.D1(theU2, aPnt2, aD1_2); - if (!aPnt1.IsEqual(aPnt2, theTolLinear)) - { - throw Standard_Failure("Curves not connected"); - } - - const int aMinOrder = std::min(aN1, aN2); - if (aMinOrder >= 1) - { - // Account for edge orientation. - gp_Vec aVec1 = aD1_1; - gp_Vec aVec2 = aD1_2; - if (theCurve1.Edge().Orientation() == TopAbs_REVERSED) - aVec1.Reverse(); - if (theCurve2.Edge().Orientation() == TopAbs_REVERSED) - aVec2.Reverse(); - - if (aVec1.IsEqual(aVec2, theTolLinear, theTolAngular)) - { - aCont = GeomAbs_C1; - } - else - { - // Check G1 continuity via tangent directions. - const GeomProp::TangentResult aTan1 = aProp1.Tangent(theU1, theTolLinear); - const GeomProp::TangentResult aTan2 = aProp2.Tangent(theU2, theTolLinear); - if (aTan1.IsDefined && aTan2.IsDefined) - { - gp_Dir aDir1 = aTan1.Direction; - gp_Dir aDir2 = aTan2.Direction; - if (theCurve1.Edge().Orientation() == TopAbs_REVERSED) - aDir1.Reverse(); - if (theCurve2.Edge().Orientation() == TopAbs_REVERSED) - aDir2.Reverse(); - if (aDir1.IsEqual(aDir2, theTolAngular)) - { - aCont = GeomAbs_G1; - } - isChecked = true; - } - else - { - isChecked = true; - } - } - } - - if (aMinOrder >= 2 && !isChecked) - { - // Compare second derivatives. - gp_Pnt aDummy; - gp_Vec aDummy1, aDummy2; - gp_Vec aD2_1, aD2_2; - theCurve1.D2(theU1, aDummy, aDummy1, aD2_1); - theCurve2.D2(theU2, aDummy, aDummy2, aD2_2); - if (aD2_1.IsEqual(aD2_2, theTolLinear, theTolAngular)) - { - aCont = GeomAbs_C2; - } - } - - // Same periodic edge implies CN. - const TopoDS_Edge& anEdge1 = theCurve1.Edge(); - const TopoDS_Edge& anEdge2 = theCurve2.Edge(); - if (anEdge1.IsSame(anEdge2) && theCurve1.IsPeriodic() && aCont >= GeomAbs_G1) - aCont = GeomAbs_CN; - - return aCont; -} - -//================================================================================================= - -GeomAbs_Shape BRepProp_Curve::Continuity(const BRepAdaptor_Curve& theCurve1, - const BRepAdaptor_Curve& theCurve2, - const double theU1, - const double theU2) -{ - return Continuity(theCurve1, - theCurve2, - theU1, - theU2, - Precision::Confusion(), - Precision::Angular()); -} diff --git a/src/ModelingData/TKBRep/BRepProp/BRepProp_Curve.hxx b/src/ModelingData/TKBRep/BRepProp/BRepProp_Curve.hxx deleted file mode 100644 index beaddb3b2c..0000000000 --- a/src/ModelingData/TKBRep/BRepProp/BRepProp_Curve.hxx +++ /dev/null @@ -1,139 +0,0 @@ -// 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. - -#ifndef _BRepProp_Curve_HeaderFile -#define _BRepProp_Curve_HeaderFile - -#include -#include -#include -#include -#include - -class TopoDS_Edge; - -//! @brief Local differential property evaluator for BRep edges. -//! -//! Thin wrapper over GeomProp:: free functions. -//! Delegates derivative computation to BRepAdaptor_Curve and passes -//! results to GeomProp::ComputeTangent, ComputeCurvature, etc. -//! -//! Can be initialized from a TopoDS_Edge or a BRepAdaptor_Curve. -//! When initialized from an existing BRepAdaptor_Curve, the adaptor is -//! referenced without copying (non-owning); when initialized from a -//! TopoDS_Edge, an internal adaptor is created and owned. -//! -//! Usage: -//! @code -//! BRepProp_Curve aProp(myEdge); -//! GeomProp::CurvatureResult aCurv = aProp.Curvature(0.5, Precision::Confusion()); -//! if (aCurv.IsDefined) -//! { -//! double aValue = aCurv.Value; -//! } -//! @endcode -class BRepProp_Curve -{ -public: - DEFINE_STANDARD_ALLOC - - //! Construct from a TopoDS_Edge. - //! Creates an internal BRepAdaptor_Curve (owning). - //! @param[in] theEdge the edge to evaluate - Standard_EXPORT BRepProp_Curve(const TopoDS_Edge& theEdge); - - //! Construct from an existing BRepAdaptor_Curve. - //! The adaptor is referenced without copying (non-owning); - //! the caller must ensure the adaptor outlives this object. - //! @param[in] theCurve the adaptor to reference - Standard_EXPORT BRepProp_Curve(const BRepAdaptor_Curve& theCurve); - - //! Construct from a handle to BRepAdaptor_Curve. - //! Shares ownership of the adaptor (no copy). - //! @param[in] theCurve handle to the adaptor - Standard_EXPORT BRepProp_Curve(const occ::handle& theCurve); - - //! Non-copyable and non-movable. - BRepProp_Curve(const BRepProp_Curve&) = delete; - BRepProp_Curve& operator=(const BRepProp_Curve&) = delete; - BRepProp_Curve(BRepProp_Curve&&) = delete; - BRepProp_Curve& operator=(BRepProp_Curve&&) = delete; - - //! Returns the underlying adaptor. - const BRepAdaptor_Curve& Adaptor() const { return *myPtr; } - - //! Compute tangent at given parameter. - //! @param[in] theParam curve parameter - //! @param[in] theTol linear tolerance - //! @return tangent result with validity flag - Standard_EXPORT GeomProp::TangentResult Tangent(double theParam, double theTol) const; - - //! Compute curvature at given parameter. - //! @param[in] theParam curve parameter - //! @param[in] theTol linear tolerance - //! @return curvature result with validity and infinity flags - Standard_EXPORT GeomProp::CurvatureResult Curvature(double theParam, double theTol) const; - - //! Compute normal at given parameter. - //! @param[in] theParam curve parameter - //! @param[in] theTol linear tolerance - //! @return normal result with validity flag - Standard_EXPORT GeomProp::NormalResult Normal(double theParam, double theTol) const; - - //! Compute centre of curvature at given parameter. - //! @param[in] theParam curve parameter - //! @param[in] theTol linear tolerance - //! @return centre result with validity flag - Standard_EXPORT GeomProp::CentreResult CentreOfCurvature(double theParam, double theTol) const; - - //! Computes the regularity at the junction between two curves. - //! The point theU1 on theCurve1 and the point theU2 on theCurve2 must be coincident. - //! @param[in] theCurve1 first curve adaptor - //! @param[in] theCurve2 second curve adaptor - //! @param[in] theU1 parameter on theCurve1 - //! @param[in] theU2 parameter on theCurve2 - //! @param[in] theTolLinear linear tolerance - //! @param[in] theTolAngular angular tolerance - //! @return the continuity order (C0, G1, C1, C2, CN) - Standard_EXPORT static GeomAbs_Shape Continuity(const BRepAdaptor_Curve& theCurve1, - const BRepAdaptor_Curve& theCurve2, - double theU1, - double theU2, - double theTolLinear, - double theTolAngular); - - //! Same as above but using the standard tolerances from package Precision. - Standard_EXPORT static GeomAbs_Shape Continuity(const BRepAdaptor_Curve& theCurve1, - const BRepAdaptor_Curve& theCurve2, - double theU1, - double theU2); - -protected: - //! Initialize from a TopoDS_Edge. - //! @param[in] theEdge the edge to evaluate - Standard_EXPORT void initialization(const TopoDS_Edge& theEdge); - - //! Initialize from an existing BRepAdaptor_Curve (non-owning). - //! @param[in] theCurve the adaptor to reference - Standard_EXPORT void initialization(const BRepAdaptor_Curve& theCurve); - - //! Initialize from a handle to BRepAdaptor_Curve. - //! @param[in] theCurve handle to the adaptor - Standard_EXPORT void initialization(const occ::handle& theCurve); - -private: - occ::handle myOwned; //!< Owns the adaptor when created from TopoDS_Edge. - const BRepAdaptor_Curve* myPtr = nullptr; //!< Non-owning pointer to the active adaptor. -}; - -#endif // _BRepProp_Curve_HeaderFile diff --git a/src/ModelingData/TKBRep/BRepProp/BRepProp_Surface.cxx b/src/ModelingData/TKBRep/BRepProp/BRepProp_Surface.cxx deleted file mode 100644 index 382ad5ef35..0000000000 --- a/src/ModelingData/TKBRep/BRepProp/BRepProp_Surface.cxx +++ /dev/null @@ -1,115 +0,0 @@ -// 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 - -#include - -//================================================================================================= - -BRepProp_Surface::BRepProp_Surface(const TopoDS_Face& theFace) -{ - initialization(theFace); -} - -//================================================================================================= - -BRepProp_Surface::BRepProp_Surface(const BRepAdaptor_Surface& theSurface) -{ - initialization(theSurface); -} - -//================================================================================================= - -BRepProp_Surface::BRepProp_Surface(const occ::handle& theSurface) -{ - initialization(theSurface); -} - -//================================================================================================= - -void BRepProp_Surface::initialization(const TopoDS_Face& theFace) -{ - if (theFace.IsNull()) - { - myOwned.Nullify(); - myPtr = nullptr; - return; - } - myOwned = new BRepAdaptor_Surface(theFace); - myPtr = myOwned.get(); -} - -//================================================================================================= - -void BRepProp_Surface::initialization(const BRepAdaptor_Surface& theSurface) -{ - myOwned.Nullify(); - myPtr = &theSurface; -} - -//================================================================================================= - -void BRepProp_Surface::initialization(const occ::handle& theSurface) -{ - myOwned = theSurface; - myPtr = myOwned.get(); -} - -//================================================================================================= - -GeomProp::SurfaceNormalResult BRepProp_Surface::Normal(const double theU, - const double theV, - const double theTol) const -{ - if (myPtr == nullptr) - { - return {{}, false}; - } - gp_Pnt aPnt; - gp_Vec aD1U, aD1V; - myPtr->D1(theU, theV, aPnt, aD1U, aD1V); - return GeomProp::ComputeSurfaceNormal(aD1U, aD1V, theTol); -} - -//================================================================================================= - -GeomProp::SurfaceCurvatureResult BRepProp_Surface::Curvatures(const double theU, - const double theV, - const double theTol) const -{ - if (myPtr == nullptr) - { - return {}; - } - gp_Pnt aPnt; - gp_Vec aD1U, aD1V, aD2U, aD2V, aD2UV; - myPtr->D2(theU, theV, aPnt, aD1U, aD1V, aD2U, aD2V, aD2UV); - return GeomProp::ComputeSurfaceCurvatures(aD1U, aD1V, aD2U, aD2V, aD2UV, theTol); -} - -//================================================================================================= - -GeomProp::MeanGaussianResult BRepProp_Surface::MeanGaussian(const double theU, - const double theV, - const double theTol) const -{ - if (myPtr == nullptr) - { - return {}; - } - gp_Pnt aPnt; - gp_Vec aD1U, aD1V, aD2U, aD2V, aD2UV; - myPtr->D2(theU, theV, aPnt, aD1U, aD1V, aD2U, aD2V, aD2UV); - return GeomProp::ComputeMeanGaussian(aD1U, aD1V, aD2U, aD2V, aD2UV, theTol); -} diff --git a/src/ModelingData/TKBRep/BRepProp/BRepProp_Surface.hxx b/src/ModelingData/TKBRep/BRepProp/BRepProp_Surface.hxx deleted file mode 100644 index 60c4ca480b..0000000000 --- a/src/ModelingData/TKBRep/BRepProp/BRepProp_Surface.hxx +++ /dev/null @@ -1,119 +0,0 @@ -// 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. - -#ifndef _BRepProp_Surface_HeaderFile -#define _BRepProp_Surface_HeaderFile - -#include -#include -#include -#include - -class TopoDS_Face; - -//! @brief Local differential property evaluator for BRep faces. -//! -//! Thin wrapper over GeomProp:: free functions. -//! Delegates derivative computation to BRepAdaptor_Surface and passes -//! results to GeomProp::ComputeSurfaceNormal, ComputeSurfaceCurvatures, etc. -//! -//! Can be initialized from a TopoDS_Face or a BRepAdaptor_Surface. -//! When initialized from an existing BRepAdaptor_Surface, the adaptor is -//! referenced without copying (non-owning); when initialized from a -//! TopoDS_Face, an internal adaptor is created and owned. -//! -//! Usage: -//! @code -//! BRepProp_Surface aProp(myFace); -//! GeomProp::SurfaceNormalResult aNorm = aProp.Normal(0.5, 0.5, Precision::Confusion()); -//! if (aNorm.IsDefined) -//! { -//! gp_Dir aDir = aNorm.Direction; -//! } -//! @endcode -class BRepProp_Surface -{ -public: - DEFINE_STANDARD_ALLOC - - //! Construct from a TopoDS_Face. - //! Creates an internal BRepAdaptor_Surface (owning). - //! @param[in] theFace the face to evaluate - Standard_EXPORT BRepProp_Surface(const TopoDS_Face& theFace); - - //! Construct from an existing BRepAdaptor_Surface. - //! The adaptor is referenced without copying (non-owning); - //! the caller must ensure the adaptor outlives this object. - //! @param[in] theSurface the adaptor to reference - Standard_EXPORT BRepProp_Surface(const BRepAdaptor_Surface& theSurface); - - //! Construct from a handle to BRepAdaptor_Surface. - //! Shares ownership of the adaptor (no copy). - //! @param[in] theSurface handle to the adaptor - Standard_EXPORT BRepProp_Surface(const occ::handle& theSurface); - - //! Non-copyable and non-movable. - BRepProp_Surface(const BRepProp_Surface&) = delete; - BRepProp_Surface& operator=(const BRepProp_Surface&) = delete; - BRepProp_Surface(BRepProp_Surface&&) = delete; - BRepProp_Surface& operator=(BRepProp_Surface&&) = delete; - - //! Returns the underlying adaptor. - const BRepAdaptor_Surface& Adaptor() const { return *myPtr; } - - //! Compute surface normal at given (U, V) parameter. - //! @param[in] theU U parameter - //! @param[in] theV V parameter - //! @param[in] theTol linear tolerance - //! @return normal result with validity flag - Standard_EXPORT GeomProp::SurfaceNormalResult Normal(double theU, - double theV, - double theTol) const; - - //! Compute principal curvatures at given (U, V) parameter. - //! @param[in] theU U parameter - //! @param[in] theV V parameter - //! @param[in] theTol linear tolerance - //! @return curvature result with min/max values, directions, and validity flag - Standard_EXPORT GeomProp::SurfaceCurvatureResult Curvatures(double theU, - double theV, - double theTol) const; - - //! Compute mean and Gaussian curvatures at given (U, V) parameter. - //! @param[in] theU U parameter - //! @param[in] theV V parameter - //! @param[in] theTol linear tolerance - //! @return mean/Gaussian curvature result with validity flag - Standard_EXPORT GeomProp::MeanGaussianResult MeanGaussian(double theU, - double theV, - double theTol) const; - -protected: - //! Initialize from a TopoDS_Face. - //! @param[in] theFace the face to evaluate - Standard_EXPORT void initialization(const TopoDS_Face& theFace); - - //! Initialize from an existing BRepAdaptor_Surface (non-owning). - //! @param[in] theSurface the adaptor to reference - Standard_EXPORT void initialization(const BRepAdaptor_Surface& theSurface); - - //! Initialize from a handle to BRepAdaptor_Surface. - //! @param[in] theSurface handle to the adaptor - Standard_EXPORT void initialization(const occ::handle& theSurface); - -private: - occ::handle myOwned; //!< Owns the adaptor when created from TopoDS_Face. - const BRepAdaptor_Surface* myPtr = nullptr; //!< Non-owning pointer to the active adaptor. -}; - -#endif // _BRepProp_Surface_HeaderFile diff --git a/src/ModelingData/TKBRep/BRepProp/FILES.cmake b/src/ModelingData/TKBRep/BRepProp/FILES.cmake deleted file mode 100644 index 24cb07128f..0000000000 --- a/src/ModelingData/TKBRep/BRepProp/FILES.cmake +++ /dev/null @@ -1,9 +0,0 @@ -# Source files for BRepProp package -set(OCCT_BRepProp_FILES_LOCATION "${CMAKE_CURRENT_LIST_DIR}") - -set(OCCT_BRepProp_FILES - BRepProp_Curve.cxx - BRepProp_Curve.hxx - BRepProp_Surface.cxx - BRepProp_Surface.hxx -) diff --git a/src/ModelingData/TKBRep/GTests/BRepProp_Test.cxx b/src/ModelingData/TKBRep/GTests/BRepProp_Test.cxx deleted file mode 100644 index 4e7f1ac8ac..0000000000 --- a/src/ModelingData/TKBRep/GTests/BRepProp_Test.cxx +++ /dev/null @@ -1,290 +0,0 @@ -// 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. - -// Unit tests for BRepProp_Curve and BRepProp_Surface on built BRep shapes. - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -namespace -{ -constexpr double THE_LIN_TOL = Precision::PConfusion(); -constexpr double THE_CURV_TOL = 1.0e-8; -constexpr double THE_DIR_TOL = Precision::Confusion(); -constexpr double THE_POINT_TOL = Precision::Confusion(); -} // namespace - -// ============================================================ -// BRepProp_Curve tests -// ============================================================ - -TEST(BRepProp_CurveTest, InitializeFromEdge_Line) -{ - BRepBuilderAPI_MakeEdge aMakeEdge(gp_Lin(gp_Pnt(0, 0, 0), gp_Dir(1, 0, 0)), 0.0, 10.0); - ASSERT_TRUE(aMakeEdge.IsDone()); - const TopoDS_Edge& anEdge = aMakeEdge.Edge(); - - BRepProp_Curve aProp(anEdge); - - // Tangent on a line should be defined. - const GeomProp::TangentResult aTan = aProp.Tangent(5.0, THE_LIN_TOL); - ASSERT_TRUE(aTan.IsDefined); - EXPECT_NEAR(std::abs(aTan.Direction.Dot(gp_Dir(1, 0, 0))), 1.0, THE_DIR_TOL); - - // Curvature of a line should be zero. - const GeomProp::CurvatureResult aCurv = aProp.Curvature(5.0, THE_LIN_TOL); - ASSERT_TRUE(aCurv.IsDefined); - EXPECT_NEAR(aCurv.Value, 0.0, THE_CURV_TOL); -} - -TEST(BRepProp_CurveTest, InitializeFromEdge_Circle) -{ - constexpr double aRadius = 5.0; - gp_Circ aCirc(gp_Ax2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), aRadius); - BRepBuilderAPI_MakeEdge aMakeEdge(aCirc); - ASSERT_TRUE(aMakeEdge.IsDone()); - const TopoDS_Edge& anEdge = aMakeEdge.Edge(); - - BRepProp_Curve aProp(anEdge); - - // Check curvature = 1/R at midpoint. - const GeomProp::CurvatureResult aCurv = aProp.Curvature(M_PI, THE_LIN_TOL); - ASSERT_TRUE(aCurv.IsDefined); - EXPECT_NEAR(aCurv.Value, 1.0 / aRadius, THE_CURV_TOL); - - // Check normal is defined. - const GeomProp::NormalResult aNorm = aProp.Normal(M_PI, THE_LIN_TOL); - ASSERT_TRUE(aNorm.IsDefined); - - // Check centre of curvature should be at origin. - const GeomProp::CentreResult aCent = aProp.CentreOfCurvature(M_PI, THE_LIN_TOL); - ASSERT_TRUE(aCent.IsDefined); - EXPECT_NEAR(aCent.Centre.Distance(gp_Pnt(0, 0, 0)), 0.0, THE_POINT_TOL); -} - -TEST(BRepProp_CurveTest, InitializeFromAdaptor) -{ - constexpr double aRadius = 3.0; - gp_Circ aCirc(gp_Ax2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), aRadius); - BRepBuilderAPI_MakeEdge aMakeEdge(aCirc); - ASSERT_TRUE(aMakeEdge.IsDone()); - - BRepAdaptor_Curve anAdaptor(aMakeEdge.Edge()); - - BRepProp_Curve aProp(anAdaptor); - - const GeomProp::CurvatureResult aCurv = aProp.Curvature(M_PI / 2.0, THE_LIN_TOL); - ASSERT_TRUE(aCurv.IsDefined); - EXPECT_NEAR(aCurv.Value, 1.0 / aRadius, THE_CURV_TOL); -} - -TEST(BRepProp_CurveTest, BoxEdge_Tangent) -{ - BRepPrimAPI_MakeBox aBoxMaker(10.0, 20.0, 30.0); - const TopoDS_Shape& aBox = aBoxMaker.Shape(); - ASSERT_TRUE(aBoxMaker.IsDone()); - - // Get the first edge. - TopExp_Explorer anExp(aBox, TopAbs_EDGE); - ASSERT_TRUE(anExp.More()); - const TopoDS_Edge& anEdge = TopoDS::Edge(anExp.Current()); - - BRepProp_Curve aProp(anEdge); - - double aFirst = 0.0, aLast = 0.0; - BRep_Tool::Range(anEdge, aFirst, aLast); - const double aMid = 0.5 * (aFirst + aLast); - - // Box edges are lines - tangent should be defined and curvature zero. - const GeomProp::TangentResult aTan = aProp.Tangent(aMid, THE_LIN_TOL); - EXPECT_TRUE(aTan.IsDefined); - - const GeomProp::CurvatureResult aCurv = aProp.Curvature(aMid, THE_LIN_TOL); - ASSERT_TRUE(aCurv.IsDefined); - EXPECT_NEAR(aCurv.Value, 0.0, THE_CURV_TOL); -} - -TEST(BRepProp_CurveTest, CylinderEdge_Curvature) -{ - constexpr double aRadius = 4.0; - constexpr double aHeight = 10.0; - BRepPrimAPI_MakeCylinder aCylMaker(aRadius, aHeight); - const TopoDS_Shape& aCyl = aCylMaker.Shape(); - ASSERT_TRUE(aCylMaker.IsDone()); - - // Find a circular edge (not a seam line). - for (TopExp_Explorer anExp(aCyl, TopAbs_EDGE); anExp.More(); anExp.Next()) - { - const TopoDS_Edge& anEdge = TopoDS::Edge(anExp.Current()); - BRepProp_Curve aProp(anEdge); - - double aFirst = 0.0, aLast = 0.0; - BRep_Tool::Range(anEdge, aFirst, aLast); - const double aMid = 0.5 * (aFirst + aLast); - - const GeomProp::CurvatureResult aCurv = aProp.Curvature(aMid, THE_LIN_TOL); - if (aCurv.IsDefined && aCurv.Value > THE_CURV_TOL) - { - // Circular edge: curvature = 1/R. - EXPECT_NEAR(aCurv.Value, 1.0 / aRadius, THE_CURV_TOL); - return; - } - } - // At least one circular edge should have been found. - FAIL() << "No circular edge found on cylinder"; -} - -// ============================================================ -// BRepProp_Surface tests -// ============================================================ - -TEST(BRepProp_SurfaceTest, BoxFace_PlanarNormal) -{ - BRepPrimAPI_MakeBox aBoxMaker(10.0, 20.0, 30.0); - const TopoDS_Shape& aBox = aBoxMaker.Shape(); - ASSERT_TRUE(aBoxMaker.IsDone()); - - TopExp_Explorer anExp(aBox, TopAbs_FACE); - ASSERT_TRUE(anExp.More()); - const TopoDS_Face& aFace = TopoDS::Face(anExp.Current()); - - BRepProp_Surface aProp(aFace); - - const GeomProp::SurfaceNormalResult aNorm = aProp.Normal(0.5, 0.5, THE_LIN_TOL); - ASSERT_TRUE(aNorm.IsDefined); - - // Plane curvatures should be zero. - const GeomProp::SurfaceCurvatureResult aCurv = aProp.Curvatures(0.5, 0.5, THE_LIN_TOL); - ASSERT_TRUE(aCurv.IsDefined); - EXPECT_NEAR(aCurv.MinCurvature, 0.0, THE_CURV_TOL); - EXPECT_NEAR(aCurv.MaxCurvature, 0.0, THE_CURV_TOL); - - const GeomProp::MeanGaussianResult aMG = aProp.MeanGaussian(0.5, 0.5, THE_LIN_TOL); - ASSERT_TRUE(aMG.IsDefined); - EXPECT_NEAR(aMG.MeanCurvature, 0.0, THE_CURV_TOL); - EXPECT_NEAR(aMG.GaussianCurvature, 0.0, THE_CURV_TOL); -} - -TEST(BRepProp_SurfaceTest, InitializeFromAdaptor) -{ - BRepPrimAPI_MakeBox aBoxMaker(10.0, 20.0, 30.0); - const TopoDS_Shape& aBox = aBoxMaker.Shape(); - ASSERT_TRUE(aBoxMaker.IsDone()); - - TopExp_Explorer anExp(aBox, TopAbs_FACE); - ASSERT_TRUE(anExp.More()); - const TopoDS_Face& aFace = TopoDS::Face(anExp.Current()); - - BRepAdaptor_Surface anAdaptor(aFace); - BRepProp_Surface aProp(anAdaptor); - - const GeomProp::SurfaceNormalResult aNorm = aProp.Normal(0.5, 0.5, THE_LIN_TOL); - ASSERT_TRUE(aNorm.IsDefined); -} - -TEST(BRepProp_SurfaceTest, SphereFace_Curvatures) -{ - constexpr double aRadius = 5.0; - BRepPrimAPI_MakeSphere aSphMaker(aRadius); - const TopoDS_Shape& aSph = aSphMaker.Shape(); - ASSERT_TRUE(aSphMaker.IsDone()); - - // Find the spherical face. - TopExp_Explorer anExp(aSph, TopAbs_FACE); - ASSERT_TRUE(anExp.More()); - const TopoDS_Face& aFace = TopoDS::Face(anExp.Current()); - - BRepProp_Surface aProp(aFace); - - // Evaluate at equator-like parameter (away from poles). - const double aU = M_PI; - const double aV = 0.0; - - const GeomProp::SurfaceCurvatureResult aCurv = aProp.Curvatures(aU, aV, THE_LIN_TOL); - ASSERT_TRUE(aCurv.IsDefined); - - // Sphere: both principal curvatures = 1/R in absolute value. - // Sign depends on face orientation (BRepAdaptor_Surface accounts for it). - EXPECT_NEAR(std::abs(aCurv.MinCurvature), 1.0 / aRadius, THE_POINT_TOL); - EXPECT_NEAR(std::abs(aCurv.MaxCurvature), 1.0 / aRadius, THE_POINT_TOL); - - const GeomProp::MeanGaussianResult aMG = aProp.MeanGaussian(aU, aV, THE_LIN_TOL); - ASSERT_TRUE(aMG.IsDefined); - EXPECT_NEAR(std::abs(aMG.MeanCurvature), 1.0 / aRadius, THE_POINT_TOL); - EXPECT_NEAR(aMG.GaussianCurvature, 1.0 / (aRadius * aRadius), THE_POINT_TOL); -} - -TEST(BRepProp_SurfaceTest, CylinderFace_Curvatures) -{ - constexpr double aRadius = 3.0; - constexpr double aHeight = 10.0; - BRepPrimAPI_MakeCylinder aCylMaker(aRadius, aHeight); - const TopoDS_Shape& aCyl = aCylMaker.Shape(); - ASSERT_TRUE(aCylMaker.IsDone()); - - // Find the cylindrical face (lateral). - for (TopExp_Explorer anExp(aCyl, TopAbs_FACE); anExp.More(); anExp.Next()) - { - const TopoDS_Face& aFace = TopoDS::Face(anExp.Current()); - BRepAdaptor_Surface anAdaptor(aFace); - if (anAdaptor.GetType() != GeomAbs_Cylinder) - { - continue; - } - - BRepProp_Surface aProp(aFace); - - const double aU = M_PI / 4.0; - const double aV = aHeight / 2.0; - - const GeomProp::SurfaceCurvatureResult aCurv = aProp.Curvatures(aU, aV, THE_LIN_TOL); - ASSERT_TRUE(aCurv.IsDefined); - - // Cylinder: one curvature = 1/R, the other = 0. - const double aMin = std::min(std::abs(aCurv.MinCurvature), std::abs(aCurv.MaxCurvature)); - const double aMax = std::max(std::abs(aCurv.MinCurvature), std::abs(aCurv.MaxCurvature)); - EXPECT_NEAR(aMin, 0.0, THE_CURV_TOL); - EXPECT_NEAR(aMax, 1.0 / aRadius, THE_POINT_TOL); - - const GeomProp::MeanGaussianResult aMG = aProp.MeanGaussian(aU, aV, THE_LIN_TOL); - ASSERT_TRUE(aMG.IsDefined); - // Gaussian curvature of cylinder = 0. - EXPECT_NEAR(aMG.GaussianCurvature, 0.0, THE_CURV_TOL); - return; - } - FAIL() << "No cylindrical face found"; -} diff --git a/src/ModelingData/TKBRep/GTests/BRepProp_VsBRepLProp_Test.cxx b/src/ModelingData/TKBRep/GTests/BRepProp_VsBRepLProp_Test.cxx deleted file mode 100644 index 38dac954b0..0000000000 --- a/src/ModelingData/TKBRep/GTests/BRepProp_VsBRepLProp_Test.cxx +++ /dev/null @@ -1,329 +0,0 @@ -// 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. - -// Cross-validation tests comparing BRepProp_Curve / BRepProp_Surface -// against old BRepLProp_CLProps / BRepLProp_SLProps. - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -namespace -{ -constexpr double THE_LIN_TOL = Precision::PConfusion(); -constexpr double THE_CURV_TOL = 1.0e-8; -constexpr double THE_DIR_TOL = 1.0e-6; -constexpr double THE_POINT_TOL = 1.0e-6; - -// ============================================================ -// Curve cross-validation helpers -// ============================================================ - -void compareCurveTangent(const TopoDS_Edge& theEdge, const double theParam) -{ - BRepAdaptor_Curve anAdaptor(theEdge); - - // New API - BRepProp_Curve aNewProp(anAdaptor); - const GeomProp::TangentResult aNew = aNewProp.Tangent(theParam, THE_LIN_TOL); - - // Old API - BRepLProp_CLProps anOld(anAdaptor, theParam, 2, THE_LIN_TOL); - if (anOld.IsTangentDefined()) - { - ASSERT_TRUE(aNew.IsDefined) << "New tangent undefined but old is defined at param=" << theParam; - gp_Dir anOldDir; - anOld.Tangent(anOldDir); - const double aDot = aNew.Direction.Dot(anOldDir); - EXPECT_NEAR(std::abs(aDot), 1.0, THE_DIR_TOL) - << "Tangent direction mismatch at param=" << theParam; - } -} - -void compareCurveCurvature(const TopoDS_Edge& theEdge, const double theParam) -{ - BRepAdaptor_Curve anAdaptor(theEdge); - - BRepProp_Curve aNewProp(anAdaptor); - const GeomProp::CurvatureResult aNew = aNewProp.Curvature(theParam, THE_LIN_TOL); - - BRepLProp_CLProps anOld(anAdaptor, theParam, 2, THE_LIN_TOL); - if (anOld.IsTangentDefined()) - { - ASSERT_TRUE(aNew.IsDefined) << "New curvature undefined at param=" << theParam; - EXPECT_NEAR(aNew.Value, anOld.Curvature(), THE_CURV_TOL) - << "Curvature mismatch at param=" << theParam; - } -} - -void compareCurveNormal(const TopoDS_Edge& theEdge, const double theParam) -{ - BRepAdaptor_Curve anAdaptor(theEdge); - - BRepProp_Curve aNewProp(anAdaptor); - const GeomProp::NormalResult aNew = aNewProp.Normal(theParam, THE_LIN_TOL); - - BRepLProp_CLProps anOld(anAdaptor, theParam, 2, THE_LIN_TOL); - if (anOld.IsTangentDefined() && std::abs(anOld.Curvature()) > THE_LIN_TOL) - { - ASSERT_TRUE(aNew.IsDefined) << "New normal undefined but old is defined at param=" << theParam; - gp_Dir anOldDir; - anOld.Normal(anOldDir); - const double aDot = aNew.Direction.Dot(anOldDir); - EXPECT_NEAR(std::abs(aDot), 1.0, THE_DIR_TOL) - << "Normal direction mismatch at param=" << theParam; - } -} - -void compareCurveCentre(const TopoDS_Edge& theEdge, const double theParam) -{ - BRepAdaptor_Curve anAdaptor(theEdge); - - BRepProp_Curve aNewProp(anAdaptor); - const GeomProp::CentreResult aNew = aNewProp.CentreOfCurvature(theParam, THE_LIN_TOL); - - BRepLProp_CLProps anOld(anAdaptor, theParam, 2, THE_LIN_TOL); - if (anOld.IsTangentDefined() && std::abs(anOld.Curvature()) > THE_LIN_TOL) - { - ASSERT_TRUE(aNew.IsDefined) << "New centre undefined at param=" << theParam; - gp_Pnt anOldPnt; - anOld.CentreOfCurvature(anOldPnt); - EXPECT_NEAR(aNew.Centre.Distance(anOldPnt), 0.0, THE_POINT_TOL) - << "Centre of curvature mismatch at param=" << theParam; - } -} - -// ============================================================ -// Surface cross-validation helpers -// ============================================================ - -void compareSurfaceNormal(const TopoDS_Face& theFace, const double theU, const double theV) -{ - BRepAdaptor_Surface anAdaptor(theFace); - - BRepProp_Surface aNewProp(anAdaptor); - const GeomProp::SurfaceNormalResult aNew = aNewProp.Normal(theU, theV, THE_LIN_TOL); - - BRepLProp_SLProps anOld(anAdaptor, theU, theV, 2, THE_LIN_TOL); - if (anOld.IsNormalDefined()) - { - ASSERT_TRUE(aNew.IsDefined) << "New normal undefined but old is defined at (" << theU << ", " - << theV << ")"; - const gp_Dir& anOldDir = anOld.Normal(); - const double aDot = aNew.Direction.Dot(anOldDir); - EXPECT_NEAR(std::abs(aDot), 1.0, THE_DIR_TOL) - << "Surface normal mismatch at (" << theU << ", " << theV << ")"; - } -} - -void compareSurfaceCurvatures(const TopoDS_Face& theFace, const double theU, const double theV) -{ - BRepAdaptor_Surface anAdaptor(theFace); - - BRepProp_Surface aNewProp(anAdaptor); - const GeomProp::SurfaceCurvatureResult aNew = aNewProp.Curvatures(theU, theV, THE_LIN_TOL); - - BRepLProp_SLProps anOld(anAdaptor, theU, theV, 2, THE_LIN_TOL); - if (anOld.IsCurvatureDefined()) - { - ASSERT_TRUE(aNew.IsDefined) << "New curvatures undefined at (" << theU << ", " << theV << ")"; - EXPECT_NEAR(aNew.MinCurvature, anOld.MinCurvature(), THE_CURV_TOL) - << "Min curvature mismatch at (" << theU << ", " << theV << ")"; - EXPECT_NEAR(aNew.MaxCurvature, anOld.MaxCurvature(), THE_CURV_TOL) - << "Max curvature mismatch at (" << theU << ", " << theV << ")"; - } -} - -void compareSurfaceMeanGaussian(const TopoDS_Face& theFace, const double theU, const double theV) -{ - BRepAdaptor_Surface anAdaptor(theFace); - - BRepProp_Surface aNewProp(anAdaptor); - const GeomProp::MeanGaussianResult aNew = aNewProp.MeanGaussian(theU, theV, THE_LIN_TOL); - - BRepLProp_SLProps anOld(anAdaptor, theU, theV, 2, THE_LIN_TOL); - if (anOld.IsCurvatureDefined()) - { - ASSERT_TRUE(aNew.IsDefined) << "New mean/gaussian undefined at (" << theU << ", " << theV - << ")"; - EXPECT_NEAR(aNew.MeanCurvature, anOld.MeanCurvature(), THE_CURV_TOL) - << "Mean curvature mismatch at (" << theU << ", " << theV << ")"; - EXPECT_NEAR(aNew.GaussianCurvature, anOld.GaussianCurvature(), THE_CURV_TOL) - << "Gaussian curvature mismatch at (" << theU << ", " << theV << ")"; - } -} -} // namespace - -// ============================================================ -// Curve cross-validation tests -// ============================================================ - -TEST(BRepProp_VsBRepLPropTest, Curve_LineEdge) -{ - BRepBuilderAPI_MakeEdge aMakeEdge(gp_Lin(gp_Pnt(0, 0, 0), gp_Dir(1, 0, 0)), 0.0, 10.0); - ASSERT_TRUE(aMakeEdge.IsDone()); - const TopoDS_Edge& anEdge = aMakeEdge.Edge(); - - for (double aParam = 1.0; aParam <= 9.0; aParam += 2.0) - { - compareCurveTangent(anEdge, aParam); - compareCurveCurvature(anEdge, aParam); - } -} - -TEST(BRepProp_VsBRepLPropTest, Curve_CircleEdge) -{ - constexpr double aRadius = 5.0; - gp_Circ aCirc(gp_Ax2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), aRadius); - BRepBuilderAPI_MakeEdge aMakeEdge(aCirc); - ASSERT_TRUE(aMakeEdge.IsDone()); - const TopoDS_Edge& anEdge = aMakeEdge.Edge(); - - for (double aParam = 0.5; aParam < 2.0 * M_PI; aParam += 1.0) - { - compareCurveTangent(anEdge, aParam); - compareCurveCurvature(anEdge, aParam); - compareCurveNormal(anEdge, aParam); - compareCurveCentre(anEdge, aParam); - } -} - -TEST(BRepProp_VsBRepLPropTest, Curve_BoxEdges) -{ - BRepPrimAPI_MakeBox aBoxMaker(10.0, 20.0, 30.0); - const TopoDS_Shape& aBox = aBoxMaker.Shape(); - ASSERT_TRUE(aBoxMaker.IsDone()); - - for (TopExp_Explorer anExp(aBox, TopAbs_EDGE); anExp.More(); anExp.Next()) - { - const TopoDS_Edge& anEdge = TopoDS::Edge(anExp.Current()); - double aFirst = 0.0, aLast = 0.0; - BRep_Tool::Range(anEdge, aFirst, aLast); - const double aMid = 0.5 * (aFirst + aLast); - - compareCurveTangent(anEdge, aMid); - compareCurveCurvature(anEdge, aMid); - } -} - -TEST(BRepProp_VsBRepLPropTest, Curve_CylinderEdges) -{ - BRepPrimAPI_MakeCylinder aCylMaker(4.0, 10.0); - const TopoDS_Shape& aCyl = aCylMaker.Shape(); - ASSERT_TRUE(aCylMaker.IsDone()); - - for (TopExp_Explorer anExp(aCyl, TopAbs_EDGE); anExp.More(); anExp.Next()) - { - const TopoDS_Edge& anEdge = TopoDS::Edge(anExp.Current()); - double aFirst = 0.0, aLast = 0.0; - BRep_Tool::Range(anEdge, aFirst, aLast); - const double aMid = 0.5 * (aFirst + aLast); - - compareCurveTangent(anEdge, aMid); - compareCurveCurvature(anEdge, aMid); - compareCurveNormal(anEdge, aMid); - compareCurveCentre(anEdge, aMid); - } -} - -// ============================================================ -// Surface cross-validation tests -// ============================================================ - -TEST(BRepProp_VsBRepLPropTest, Surface_BoxFaces) -{ - BRepPrimAPI_MakeBox aBoxMaker(10.0, 20.0, 30.0); - const TopoDS_Shape& aBox = aBoxMaker.Shape(); - ASSERT_TRUE(aBoxMaker.IsDone()); - - for (TopExp_Explorer anExp(aBox, TopAbs_FACE); anExp.More(); anExp.Next()) - { - const TopoDS_Face& aFace = TopoDS::Face(anExp.Current()); - compareSurfaceNormal(aFace, 0.5, 0.5); - compareSurfaceCurvatures(aFace, 0.5, 0.5); - compareSurfaceMeanGaussian(aFace, 0.5, 0.5); - } -} - -TEST(BRepProp_VsBRepLPropTest, Surface_SphereFace) -{ - constexpr double aRadius = 5.0; - BRepPrimAPI_MakeSphere aSphMaker(aRadius); - const TopoDS_Shape& aSph = aSphMaker.Shape(); - ASSERT_TRUE(aSphMaker.IsDone()); - - TopExp_Explorer anExp(aSph, TopAbs_FACE); - ASSERT_TRUE(anExp.More()); - const TopoDS_Face& aFace = TopoDS::Face(anExp.Current()); - - // Evaluate at several points away from poles. - for (double aU = 0.5; aU < 2.0 * M_PI; aU += 1.0) - { - compareSurfaceNormal(aFace, aU, 0.0); - compareSurfaceCurvatures(aFace, aU, 0.0); - compareSurfaceMeanGaussian(aFace, aU, 0.0); - } -} - -TEST(BRepProp_VsBRepLPropTest, Surface_CylinderFace) -{ - constexpr double aRadius = 3.0; - constexpr double aHeight = 10.0; - BRepPrimAPI_MakeCylinder aCylMaker(aRadius, aHeight); - const TopoDS_Shape& aCyl = aCylMaker.Shape(); - ASSERT_TRUE(aCylMaker.IsDone()); - - for (TopExp_Explorer anExp(aCyl, TopAbs_FACE); anExp.More(); anExp.Next()) - { - const TopoDS_Face& aFace = TopoDS::Face(anExp.Current()); - BRepAdaptor_Surface anAdaptor(aFace); - if (anAdaptor.GetType() != GeomAbs_Cylinder) - { - continue; - } - - for (double aU = 0.5; aU < 2.0 * M_PI; aU += 1.5) - { - const double aV = aHeight / 2.0; - compareSurfaceNormal(aFace, aU, aV); - compareSurfaceCurvatures(aFace, aU, aV); - compareSurfaceMeanGaussian(aFace, aU, aV); - } - return; - } - FAIL() << "No cylindrical face found"; -} diff --git a/src/ModelingData/TKBRep/GTests/FILES.cmake b/src/ModelingData/TKBRep/GTests/FILES.cmake index 6bcb580871..21626778fd 100644 --- a/src/ModelingData/TKBRep/GTests/FILES.cmake +++ b/src/ModelingData/TKBRep/GTests/FILES.cmake @@ -4,8 +4,6 @@ set(OCCT_TKBRep_GTests_FILES_LOCATION "${CMAKE_CURRENT_LIST_DIR}") set(OCCT_TKBRep_GTests_FILES BRep_Tool_Test.cxx BRepAdaptor_CompCurve_Test.cxx - BRepProp_Test.cxx - BRepProp_VsBRepLProp_Test.cxx TopExp_Test.cxx TopoDS_Builder_Test.cxx TopoDS_Edge_Test.cxx diff --git a/src/ModelingData/TKBRep/PACKAGES.cmake b/src/ModelingData/TKBRep/PACKAGES.cmake index 484920a6e5..8189ac33ed 100644 --- a/src/ModelingData/TKBRep/PACKAGES.cmake +++ b/src/ModelingData/TKBRep/PACKAGES.cmake @@ -5,7 +5,6 @@ set(OCCT_TKBRep_LIST_OF_PACKAGES TopTools BRep BRepLProp - BRepProp BRepAdaptor BRepTools BinTools diff --git a/src/ModelingData/TKG2d/GTests/FILES.cmake b/src/ModelingData/TKG2d/GTests/FILES.cmake index 74294f91c4..106aeae91e 100644 --- a/src/ModelingData/TKG2d/GTests/FILES.cmake +++ b/src/ModelingData/TKG2d/GTests/FILES.cmake @@ -29,18 +29,6 @@ set(OCCT_TKG2d_GTests_FILES Geom2dEval_TBezierCurve_Test.cxx Geom2dGcc_Circ2d2TanOn_Test.cxx Geom2dGcc_Circ2d2TanRad_Test.cxx - Geom2dProp_BezierCurve_Test.cxx - Geom2dProp_BSplineCurve_Test.cxx - Geom2dProp_Circle_Test.cxx - Geom2dProp_Ellipse_Test.cxx - Geom2dProp_Hyperbola_Test.cxx - Geom2dProp_Line_Test.cxx - Geom2dProp_OffsetCurve_Test.cxx - Geom2dProp_OtherCurve_Test.cxx - Geom2dProp_Parabola_Test.cxx - Geom2dProp_Test.cxx - Geom2dProp_VsCLProps2d_Test.cxx - Geom2dProp_VsLProp_Test.cxx Geom2dGridEval_BezierCurve_Test.cxx Geom2dGridEval_Curve_Test.cxx Geom2dGridEval_Ellipse_Test.cxx diff --git a/src/ModelingData/TKG2d/GTests/Geom2dProp_BSplineCurve_Test.cxx b/src/ModelingData/TKG2d/GTests/Geom2dProp_BSplineCurve_Test.cxx deleted file mode 100644 index 11b4e2744b..0000000000 --- a/src/ModelingData/TKG2d/GTests/Geom2dProp_BSplineCurve_Test.cxx +++ /dev/null @@ -1,588 +0,0 @@ -// 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. - -// Tests for Geom2dProp_Curve with 2D BSpline curves: local differential -// properties (tangent, curvature, normal, centre of curvature) and global -// curve analysis (curvature extrema and inflection points). - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -namespace -{ -constexpr double THE_LIN_TOL = Precision::PConfusion(); -constexpr double THE_CURV_TOL = 1.0e-8; -constexpr double THE_DIR_TOL = 1.0e-6; -constexpr double THE_POINT_TOL = 1.0e-6; -constexpr double THE_PARAM_TOL = 1.0e-4; - -void compareTangent(Geom2dProp_Curve& theProp, Geom2dLProp_CLProps2d& theOld, const double theParam) -{ - theOld.SetParameter(theParam); - const Geom2dProp::TangentResult aNew = theProp.Tangent(theParam, THE_LIN_TOL); - if (theOld.IsTangentDefined()) - { - ASSERT_TRUE(aNew.IsDefined) << "Tangent undefined at U=" << theParam; - gp_Dir2d anOldDir; - theOld.Tangent(anOldDir); - const double aDot = aNew.Direction.X() * anOldDir.X() + aNew.Direction.Y() * anOldDir.Y(); - EXPECT_NEAR(std::abs(aDot), 1.0, THE_DIR_TOL) << "Tangent mismatch at U=" << theParam; - } -} - -void compareCurvature(Geom2dProp_Curve& theProp, - Geom2dLProp_CLProps2d& theOld, - const double theParam) -{ - theOld.SetParameter(theParam); - const Geom2dProp::CurvatureResult aNew = theProp.Curvature(theParam, THE_LIN_TOL); - const double aOldCurv = theOld.Curvature(); - if (aNew.IsDefined && !aNew.IsInfinite) - { - EXPECT_NEAR(aNew.Value, aOldCurv, THE_CURV_TOL) << "Curvature mismatch at U=" << theParam; - } -} - -void compareNormal(Geom2dProp_Curve& theProp, Geom2dLProp_CLProps2d& theOld, const double theParam) -{ - theOld.SetParameter(theParam); - const Geom2dProp::NormalResult aNew = theProp.Normal(theParam, THE_LIN_TOL); - const double aOldCurv = theOld.Curvature(); - if (std::abs(aOldCurv) < THE_LIN_TOL) - { - return; - } - if (aNew.IsDefined) - { - gp_Dir2d anOldNorm; - theOld.Normal(anOldNorm); - const double aDot = aNew.Direction.X() * anOldNorm.X() + aNew.Direction.Y() * anOldNorm.Y(); - EXPECT_NEAR(std::abs(aDot), 1.0, THE_DIR_TOL) << "Normal mismatch at U=" << theParam; - } -} - -void compareCentre(Geom2dProp_Curve& theProp, Geom2dLProp_CLProps2d& theOld, const double theParam) -{ - theOld.SetParameter(theParam); - const Geom2dProp::CentreResult aNew = theProp.CentreOfCurvature(theParam, THE_LIN_TOL); - const double aOldCurv = theOld.Curvature(); - if (std::abs(aOldCurv) < THE_LIN_TOL) - { - return; - } - if (aNew.IsDefined) - { - gp_Pnt2d anOldCentre; - theOld.CentreOfCurvature(anOldCentre); - EXPECT_NEAR(aNew.Centre.X(), anOldCentre.X(), THE_POINT_TOL) - << "Centre X mismatch at U=" << theParam; - EXPECT_NEAR(aNew.Centre.Y(), anOldCentre.Y(), THE_POINT_TOL) - << "Centre Y mismatch at U=" << theParam; - } -} - -void compareAll(Geom2dProp_Curve& theProp, - Geom2dLProp_CLProps2d& theOld, - const double theFirst, - const double theLast, - const int theNbSamples = 10) -{ - const double aStep = (theLast - theFirst) / theNbSamples; - for (int i = 0; i <= theNbSamples; ++i) - { - const double aParam = theFirst + i * aStep; - compareTangent(theProp, theOld, aParam); - compareCurvature(theProp, theOld, aParam); - compareNormal(theProp, theOld, aParam); - compareCentre(theProp, theOld, aParam); - } -} - -Geom2dProp::CIType mapLPropType(const LProp_CIType theType) -{ - switch (theType) - { - case LProp_Inflection: - return Geom2dProp::CIType::Inflection; - case LProp_MinCur: - return Geom2dProp::CIType::MinCurvature; - case LProp_MaxCur: - return Geom2dProp::CIType::MaxCurvature; - } - return Geom2dProp::CIType::Inflection; -} - -void compareExtrema(const Geom2dProp::CurveAnalysis& theNew, - const Geom2dLProp_CurAndInf2d& theOld, - const double theTol = THE_PARAM_TOL) -{ - EXPECT_EQ(theNew.Points.Length(), theOld.NbPoints()); - const int aNb = std::min(theNew.Points.Length(), theOld.NbPoints()); - for (int i = 0; i < aNb; ++i) - { - EXPECT_NEAR(theNew.Points.Value(i).Parameter, theOld.Parameter(i + 1), theTol) - << "Parameter mismatch at index " << i; - EXPECT_EQ(theNew.Points.Value(i).Type, mapLPropType(theOld.Type(i + 1))) - << "Type mismatch at index " << i; - } -} - -// Helper: create a cubic C2 BSpline with 6 poles. -// Knots [0, 0.33, 0.66, 1], mults [4,1,1,4], degree 3. -occ::handle makeCubicBSpline() -{ - NCollection_Array1 aPoles(1, 6); - aPoles(1) = gp_Pnt2d(0.0, 0.0); - aPoles(2) = gp_Pnt2d(1.0, 3.0); - aPoles(3) = gp_Pnt2d(2.0, 1.0); - aPoles(4) = gp_Pnt2d(3.0, 4.0); - aPoles(5) = gp_Pnt2d(4.0, 2.0); - aPoles(6) = gp_Pnt2d(5.0, 0.0); - - NCollection_Array1 aKnots(1, 4); - aKnots(1) = 0.0; - aKnots(2) = 0.33; - aKnots(3) = 0.66; - aKnots(4) = 1.0; - - NCollection_Array1 aMults(1, 4); - aMults(1) = 4; - aMults(2) = 1; - aMults(3) = 1; - aMults(4) = 4; - - return new Geom2d_BSplineCurve(aPoles, aKnots, aMults, 3); -} - -// Helper: create a quadratic C1 BSpline with 5 poles. -// Knots [0, 0.33, 0.66, 1], mults [3,1,1,3], degree 2. -occ::handle makeQuadraticBSpline() -{ - NCollection_Array1 aPoles(1, 5); - aPoles(1) = gp_Pnt2d(0.0, 0.0); - aPoles(2) = gp_Pnt2d(1.0, 3.0); - aPoles(3) = gp_Pnt2d(2.0, 1.0); - aPoles(4) = gp_Pnt2d(3.0, 3.0); - aPoles(5) = gp_Pnt2d(4.0, 0.0); - - NCollection_Array1 aKnots(1, 4); - aKnots(1) = 0.0; - aKnots(2) = 0.33; - aKnots(3) = 0.66; - aKnots(4) = 1.0; - - NCollection_Array1 aMults(1, 4); - aMults(1) = 3; - aMults(2) = 1; - aMults(3) = 1; - aMults(4) = 3; - - return new Geom2d_BSplineCurve(aPoles, aKnots, aMults, 2); -} - -// Helper: create a degree 4 BSpline with 5 poles. -// Knots [0, 1], mults [5, 5], degree 4. -occ::handle makeDegree4BSpline() -{ - NCollection_Array1 aPoles(1, 5); - aPoles(1) = gp_Pnt2d(0.0, 0.0); - aPoles(2) = gp_Pnt2d(1.0, 3.0); - aPoles(3) = gp_Pnt2d(2.0, -1.0); - aPoles(4) = gp_Pnt2d(3.0, 2.0); - aPoles(5) = gp_Pnt2d(4.0, 0.0); - - NCollection_Array1 aKnots(1, 2); - aKnots(1) = 0.0; - aKnots(2) = 1.0; - - NCollection_Array1 aMults(1, 2); - aMults(1) = 5; - aMults(2) = 5; - - return new Geom2d_BSplineCurve(aPoles, aKnots, aMults, 4); -} - -} // namespace - -// ============================================================================ -// Tangent tests -// ============================================================================ - -TEST(Geom2dProp_BSplineCurveTest, Tangent_CubicEndpoints) -{ - occ::handle aBSpline = makeCubicBSpline(); - Geom2dProp_Curve aProp(aBSpline); - - const Geom2dProp::TangentResult aTanFirst = aProp.Tangent(0.0, THE_LIN_TOL); - ASSERT_TRUE(aTanFirst.IsDefined); - // Tangent at start should point roughly toward second pole - const double aDotFirst = aTanFirst.Direction.X() * 1.0 + aTanFirst.Direction.Y() * 3.0; - EXPECT_GT(aDotFirst, 0.0); - - const Geom2dProp::TangentResult aTanLast = aProp.Tangent(1.0, THE_LIN_TOL); - ASSERT_TRUE(aTanLast.IsDefined); - // Tangent at end should point roughly from 5th pole toward 6th pole - const double aDotLast = aTanLast.Direction.X() * 1.0 + aTanLast.Direction.Y() * (-2.0); - EXPECT_GT(aDotLast, 0.0); -} - -TEST(Geom2dProp_BSplineCurveTest, Tangent_AtKnots) -{ - occ::handle aBSpline = makeCubicBSpline(); - Geom2dProp_Curve aProp(aBSpline); - - // Tangent should be defined at internal knots - const Geom2dProp::TangentResult aTan1 = aProp.Tangent(0.33, THE_LIN_TOL); - ASSERT_TRUE(aTan1.IsDefined); - - const Geom2dProp::TangentResult aTan2 = aProp.Tangent(0.66, THE_LIN_TOL); - ASSERT_TRUE(aTan2.IsDefined); - - // Directions at different knots should generally differ - const double aDot = - aTan1.Direction.X() * aTan2.Direction.X() + aTan1.Direction.Y() * aTan2.Direction.Y(); - EXPECT_LT(std::abs(aDot), 1.0 - 1.0e-10); -} - -// ============================================================================ -// Curvature tests -// ============================================================================ - -TEST(Geom2dProp_BSplineCurveTest, Curvature_CubicSmooth) -{ - occ::handle aBSpline = makeCubicBSpline(); - Geom2dProp_Curve aProp(aBSpline); - - for (double u = 0.0; u <= 1.0; u += 0.2) - { - const Geom2dProp::CurvatureResult aCurv = aProp.Curvature(u, THE_LIN_TOL); - EXPECT_TRUE(aCurv.IsDefined) << "Curvature undefined at U=" << u; - EXPECT_FALSE(aCurv.IsInfinite) << "Curvature infinite at U=" << u; - } -} - -TEST(Geom2dProp_BSplineCurveTest, Curvature_AtKnots) -{ - occ::handle aBSpline = makeCubicBSpline(); - Geom2dProp_Curve aProp(aBSpline); - - // Curvature at internal knots should be defined for C2 cubic - const Geom2dProp::CurvatureResult aCurv1 = aProp.Curvature(0.33, THE_LIN_TOL); - EXPECT_TRUE(aCurv1.IsDefined); - - const Geom2dProp::CurvatureResult aCurv2 = aProp.Curvature(0.66, THE_LIN_TOL); - EXPECT_TRUE(aCurv2.IsDefined); -} - -// ============================================================================ -// Normal tests -// ============================================================================ - -TEST(Geom2dProp_BSplineCurveTest, Normal_CubicSmooth) -{ - occ::handle aBSpline = makeCubicBSpline(); - Geom2dProp_Curve aProp(aBSpline); - - for (double u = 0.1; u <= 0.9; u += 0.2) - { - const Geom2dProp::NormalResult aNorm = aProp.Normal(u, THE_LIN_TOL); - if (aNorm.IsDefined) - { - // Normal must be perpendicular to tangent - const Geom2dProp::TangentResult aTan = aProp.Tangent(u, THE_LIN_TOL); - ASSERT_TRUE(aTan.IsDefined); - const double aDot = - aNorm.Direction.X() * aTan.Direction.X() + aNorm.Direction.Y() * aTan.Direction.Y(); - EXPECT_NEAR(aDot, 0.0, THE_DIR_TOL) << "Normal not perpendicular at U=" << u; - } - } -} - -// ============================================================================ -// Centre of curvature tests -// ============================================================================ - -TEST(Geom2dProp_BSplineCurveTest, Centre_CubicSmooth) -{ - occ::handle aBSpline = makeCubicBSpline(); - Geom2dProp_Curve aProp(aBSpline); - - for (double u = 0.1; u <= 0.9; u += 0.2) - { - const Geom2dProp::CurvatureResult aCurv = aProp.Curvature(u, THE_LIN_TOL); - const Geom2dProp::CentreResult aCentre = aProp.CentreOfCurvature(u, THE_LIN_TOL); - if (aCurv.IsDefined && !aCurv.IsInfinite && std::abs(aCurv.Value) > THE_LIN_TOL) - { - EXPECT_TRUE(aCentre.IsDefined) << "Centre undefined at U=" << u; - } - } -} - -// ============================================================================ -// Global analysis tests -// ============================================================================ - -TEST(Geom2dProp_BSplineCurveTest, FindCurvatureExtrema_Cubic) -{ - occ::handle aBSpline = makeCubicBSpline(); - Geom2dProp_Curve aProp(aBSpline); - - const Geom2dProp::CurveAnalysis aResult = aProp.FindCurvatureExtrema(); - ASSERT_TRUE(aResult.IsDone); - - // All extrema must be within parameter range - for (int i = 0; i < aResult.Points.Length(); ++i) - { - EXPECT_GE(aResult.Points.Value(i).Parameter, 0.0); - EXPECT_LE(aResult.Points.Value(i).Parameter, 1.0); - EXPECT_NE(aResult.Points.Value(i).Type, Geom2dProp::CIType::Inflection); - } -} - -TEST(Geom2dProp_BSplineCurveTest, FindInflections_Cubic) -{ - occ::handle aBSpline = makeCubicBSpline(); - Geom2dProp_Curve aProp(aBSpline); - - const Geom2dProp::CurveAnalysis aResult = aProp.FindInflections(); - ASSERT_TRUE(aResult.IsDone); - - for (int i = 0; i < aResult.Points.Length(); ++i) - { - EXPECT_GE(aResult.Points.Value(i).Parameter, 0.0); - EXPECT_LE(aResult.Points.Value(i).Parameter, 1.0); - EXPECT_EQ(aResult.Points.Value(i).Type, Geom2dProp::CIType::Inflection); - } -} - -TEST(Geom2dProp_BSplineCurveTest, FindCurvatureExtrema_LowContinuity) -{ - occ::handle aBSpline = makeQuadraticBSpline(); - Geom2dProp_Curve aProp(aBSpline); - - const Geom2dProp::CurveAnalysis aResult = aProp.FindCurvatureExtrema(); - ASSERT_TRUE(aResult.IsDone); - - for (int i = 0; i < aResult.Points.Length(); ++i) - { - EXPECT_GE(aResult.Points.Value(i).Parameter, 0.0); - EXPECT_LE(aResult.Points.Value(i).Parameter, 1.0); - } -} - -TEST(Geom2dProp_BSplineCurveTest, FindInflections_LowContinuity) -{ - occ::handle aBSpline = makeQuadraticBSpline(); - Geom2dProp_Curve aProp(aBSpline); - - const Geom2dProp::CurveAnalysis aResult = aProp.FindInflections(); - ASSERT_TRUE(aResult.IsDone); - - for (int i = 0; i < aResult.Points.Length(); ++i) - { - EXPECT_GE(aResult.Points.Value(i).Parameter, 0.0); - EXPECT_LE(aResult.Points.Value(i).Parameter, 1.0); - EXPECT_EQ(aResult.Points.Value(i).Type, Geom2dProp::CIType::Inflection); - } -} - -// ============================================================================ -// GetType test -// ============================================================================ - -TEST(Geom2dProp_BSplineCurveTest, GetType_IsBSpline) -{ - occ::handle aBSpline = makeCubicBSpline(); - Geom2dProp_Curve aProp(aBSpline); - EXPECT_EQ(aProp.GetType(), GeomAbs_BSplineCurve); -} - -// ============================================================================ -// Cross-validation vs CLProps2d -// ============================================================================ - -TEST(Geom2dProp_BSplineCurveTest, VsCLProps2d_CubicSmooth) -{ - occ::handle aBSpline = makeCubicBSpline(); - Geom2dProp_Curve aProp(aBSpline); - Geom2dLProp_CLProps2d aOld(aBSpline, 2, THE_LIN_TOL); - - for (double u = 0.0; u <= 1.0; u += 0.1) - { - compareTangent(aProp, aOld, u); - compareCurvature(aProp, aOld, u); - } -} - -TEST(Geom2dProp_BSplineCurveTest, VsCLProps2d_Quadratic) -{ - occ::handle aBSpline = makeQuadraticBSpline(); - Geom2dProp_Curve aProp(aBSpline); - Geom2dLProp_CLProps2d aOld(aBSpline, 2, THE_LIN_TOL); - - for (double u = 0.0; u <= 1.0; u += 0.1) - { - compareTangent(aProp, aOld, u); - compareCurvature(aProp, aOld, u); - } -} - -TEST(Geom2dProp_BSplineCurveTest, VsCLProps2d_Degree4) -{ - occ::handle aBSpline = makeDegree4BSpline(); - Geom2dProp_Curve aProp(aBSpline); - Geom2dLProp_CLProps2d aOld(aBSpline, 2, THE_LIN_TOL); - - for (double u = 0.0; u <= 1.0; u += 0.1) - { - compareTangent(aProp, aOld, u); - compareCurvature(aProp, aOld, u); - } -} - -TEST(Geom2dProp_BSplineCurveTest, VsCLProps2d_AllProperties_Cubic) -{ - occ::handle aBSpline = makeCubicBSpline(); - Geom2dProp_Curve aProp(aBSpline); - Geom2dLProp_CLProps2d aOld(aBSpline, 2, THE_LIN_TOL); - - compareAll(aProp, aOld, 0.0, 1.0, 20); -} - -TEST(Geom2dProp_BSplineCurveTest, VsCLProps2d_AllProperties_Degree4) -{ - occ::handle aBSpline = makeDegree4BSpline(); - Geom2dProp_Curve aProp(aBSpline); - Geom2dLProp_CLProps2d aOld(aBSpline, 2, THE_LIN_TOL); - - compareAll(aProp, aOld, 0.0, 1.0, 20); -} - -TEST(Geom2dProp_BSplineCurveTest, VsCLProps2d_LowContinuity) -{ - occ::handle aBSpline = makeQuadraticBSpline(); - Geom2dProp_Curve aProp(aBSpline); - Geom2dLProp_CLProps2d aOld(aBSpline, 2, THE_LIN_TOL); - - compareAll(aProp, aOld, 0.0, 1.0, 15); -} - -// ============================================================================ -// Cross-validation vs CurAndInf2d -// ============================================================================ - -TEST(Geom2dProp_BSplineCurveTest, VsCurAndInf2d_Cubic_Extrema) -{ - occ::handle aBSpline = makeCubicBSpline(); - - Geom2dLProp_CurAndInf2d anOld; - anOld.PerformCurExt(aBSpline); - ASSERT_TRUE(anOld.IsDone()); - - Geom2dProp_Curve aProp(aBSpline); - const Geom2dProp::CurveAnalysis aNew = aProp.FindCurvatureExtrema(); - ASSERT_TRUE(aNew.IsDone); - - compareExtrema(aNew, anOld); -} - -TEST(Geom2dProp_BSplineCurveTest, VsCurAndInf2d_Cubic_Inflections) -{ - occ::handle aBSpline = makeCubicBSpline(); - - Geom2dLProp_CurAndInf2d anOld; - anOld.PerformInf(aBSpline); - ASSERT_TRUE(anOld.IsDone()); - - Geom2dProp_Curve aProp(aBSpline); - const Geom2dProp::CurveAnalysis aNew = aProp.FindInflections(); - ASSERT_TRUE(aNew.IsDone); - - compareExtrema(aNew, anOld); -} - -TEST(Geom2dProp_BSplineCurveTest, VsCurAndInf2d_Degree4_FullPerform) -{ - occ::handle aBSpline = makeDegree4BSpline(); - - Geom2dLProp_CurAndInf2d anOld; - anOld.Perform(aBSpline); - ASSERT_TRUE(anOld.IsDone()); - - Geom2dProp_Curve aProp(aBSpline); - const Geom2dProp::CurveAnalysis aNewExt = aProp.FindCurvatureExtrema(); - const Geom2dProp::CurveAnalysis aNewInfl = aProp.FindInflections(); - ASSERT_TRUE(aNewExt.IsDone); - ASSERT_TRUE(aNewInfl.IsDone); - - const int aNewTotal = aNewExt.Points.Length() + aNewInfl.Points.Length(); - EXPECT_EQ(aNewTotal, anOld.NbPoints()); -} - -TEST(Geom2dProp_BSplineCurveTest, VsCLProps2d_CriticalPoints) -{ - NCollection_Array1 aPoles(1, 6); - aPoles(1) = gp_Pnt2d(0.0, 0.0); - aPoles(2) = gp_Pnt2d(1.0, 2.0); - aPoles(3) = gp_Pnt2d(2.0, -1.0); - aPoles(4) = gp_Pnt2d(3.0, 1.0); - aPoles(5) = gp_Pnt2d(4.0, -2.0); - aPoles(6) = gp_Pnt2d(5.0, 0.0); - NCollection_Array1 aKnots(1, 4); - aKnots(1) = 0.0; - aKnots(2) = 0.33; - aKnots(3) = 0.66; - aKnots(4) = 1.0; - NCollection_Array1 aMults(1, 4); - aMults(1) = 4; - aMults(2) = 1; - aMults(3) = 1; - aMults(4) = 4; - occ::handle aBSpline = new Geom2d_BSplineCurve(aPoles, aKnots, aMults, 3); - Geom2dProp_Curve aProp(aBSpline); - Geom2dLProp_CLProps2d aOld(aBSpline, 2, THE_LIN_TOL); - const double aParams[] = {0.0, - 1.0e-10, - 1.0e-6, - 0.33, - 0.33 + 1.0e-6, - 0.33 - 1.0e-6, - 0.66, - 0.66 + 1.0e-6, - 0.66 - 1.0e-6, - 1.0 - 1.0e-6, - 1.0 - 1.0e-10, - 1.0, - 0.165, - 0.495, - 0.83}; - for (const double aParam : aParams) - { - compareTangent(aProp, aOld, aParam); - compareCurvature(aProp, aOld, aParam); - compareNormal(aProp, aOld, aParam); - compareCentre(aProp, aOld, aParam); - } -} diff --git a/src/ModelingData/TKG2d/GTests/Geom2dProp_BezierCurve_Test.cxx b/src/ModelingData/TKG2d/GTests/Geom2dProp_BezierCurve_Test.cxx deleted file mode 100644 index bb0957b35a..0000000000 --- a/src/ModelingData/TKG2d/GTests/Geom2dProp_BezierCurve_Test.cxx +++ /dev/null @@ -1,534 +0,0 @@ -// 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -namespace -{ -constexpr double THE_LIN_TOL = Precision::PConfusion(); -constexpr double THE_CURV_TOL = 1.0e-8; -constexpr double THE_DIR_TOL = 1.0e-6; -constexpr double THE_POINT_TOL = 1.0e-6; - -void compareTangent(Geom2dProp_Curve& theProp, Geom2dLProp_CLProps2d& theOld, const double theParam) -{ - theOld.SetParameter(theParam); - const Geom2dProp::TangentResult aNew = theProp.Tangent(theParam, THE_LIN_TOL); - if (theOld.IsTangentDefined()) - { - ASSERT_TRUE(aNew.IsDefined); - gp_Dir2d anOldDir; - theOld.Tangent(anOldDir); - const double aDot = aNew.Direction.X() * anOldDir.X() + aNew.Direction.Y() * anOldDir.Y(); - EXPECT_NEAR(std::abs(aDot), 1.0, THE_DIR_TOL); - } -} - -void compareCurvature(Geom2dProp_Curve& theProp, - Geom2dLProp_CLProps2d& theOld, - const double theParam) -{ - theOld.SetParameter(theParam); - const Geom2dProp::CurvatureResult aNew = theProp.Curvature(theParam, THE_LIN_TOL); - const double aOldCurv = theOld.Curvature(); - if (aNew.IsDefined && !aNew.IsInfinite) - { - EXPECT_NEAR(aNew.Value, aOldCurv, THE_CURV_TOL); - } -} - -void compareNormal(Geom2dProp_Curve& theProp, Geom2dLProp_CLProps2d& theOld, const double theParam) -{ - theOld.SetParameter(theParam); - const Geom2dProp::NormalResult aNew = theProp.Normal(theParam, THE_LIN_TOL); - const double aOldCurv = theOld.Curvature(); - if (std::abs(aOldCurv) < THE_LIN_TOL) - { - return; - } - if (aNew.IsDefined) - { - gp_Dir2d anOldNorm; - theOld.Normal(anOldNorm); - const double aDot = aNew.Direction.X() * anOldNorm.X() + aNew.Direction.Y() * anOldNorm.Y(); - EXPECT_NEAR(std::abs(aDot), 1.0, THE_DIR_TOL); - } -} - -void compareCentre(Geom2dProp_Curve& theProp, Geom2dLProp_CLProps2d& theOld, const double theParam) -{ - theOld.SetParameter(theParam); - const Geom2dProp::CentreResult aNew = theProp.CentreOfCurvature(theParam, THE_LIN_TOL); - const double aOldCurv = theOld.Curvature(); - if (std::abs(aOldCurv) < THE_LIN_TOL) - { - return; - } - if (aNew.IsDefined) - { - gp_Pnt2d anOldCentre; - theOld.CentreOfCurvature(anOldCentre); - EXPECT_NEAR(aNew.Centre.X(), anOldCentre.X(), THE_POINT_TOL); - EXPECT_NEAR(aNew.Centre.Y(), anOldCentre.Y(), THE_POINT_TOL); - } -} - -void compareAll(Geom2dProp_Curve& theProp, - Geom2dLProp_CLProps2d& theOld, - const double theFirst, - const double theLast, - const int theNbSamples = 10) -{ - const double aStep = (theLast - theFirst) / theNbSamples; - for (int i = 0; i <= theNbSamples; ++i) - { - const double aParam = theFirst + i * aStep; - compareTangent(theProp, theOld, aParam); - compareCurvature(theProp, theOld, aParam); - compareNormal(theProp, theOld, aParam); - compareCentre(theProp, theOld, aParam); - } -} - -Geom2dProp::CIType mapLPropType(const LProp_CIType theType) -{ - switch (theType) - { - case LProp_Inflection: - return Geom2dProp::CIType::Inflection; - case LProp_MinCur: - return Geom2dProp::CIType::MinCurvature; - case LProp_MaxCur: - return Geom2dProp::CIType::MaxCurvature; - } - return Geom2dProp::CIType::Inflection; -} - -void compareExtrema(const Geom2dProp::CurveAnalysis& theNew, - const Geom2dLProp_CurAndInf2d& theOld, - const double theTol = 1.0e-4) -{ - EXPECT_EQ(theNew.Points.Length(), theOld.NbPoints()); - const int aNb = std::min(theNew.Points.Length(), theOld.NbPoints()); - for (int i = 0; i < aNb; ++i) - { - EXPECT_NEAR(theNew.Points.Value(i).Parameter, theOld.Parameter(i + 1), theTol) - << "Parameter mismatch at index " << i; - EXPECT_EQ(theNew.Points.Value(i).Type, mapLPropType(theOld.Type(i + 1))) - << "Type mismatch at index " << i; - } -} - -//! Create a linear Bezier (degree 1): P1(0,0), P2(4,0). -occ::handle makeLinearBezier() -{ - NCollection_Array1 aPoles(1, 2); - aPoles(1) = gp_Pnt2d(0.0, 0.0); - aPoles(2) = gp_Pnt2d(4.0, 0.0); - return new Geom2d_BezierCurve(aPoles); -} - -//! Create a quadratic Bezier: P1(0,0), P2(2,4), P3(4,0). -occ::handle makeQuadraticBezier() -{ - NCollection_Array1 aPoles(1, 3); - aPoles(1) = gp_Pnt2d(0.0, 0.0); - aPoles(2) = gp_Pnt2d(2.0, 4.0); - aPoles(3) = gp_Pnt2d(4.0, 0.0); - return new Geom2d_BezierCurve(aPoles); -} - -//! Create a cubic S-shaped Bezier: P1(0,0), P2(1,2), P3(3,-1), P4(4,1). -occ::handle makeCubicSBezier() -{ - NCollection_Array1 aPoles(1, 4); - aPoles(1) = gp_Pnt2d(0.0, 0.0); - aPoles(2) = gp_Pnt2d(1.0, 2.0); - aPoles(3) = gp_Pnt2d(3.0, -1.0); - aPoles(4) = gp_Pnt2d(4.0, 1.0); - return new Geom2d_BezierCurve(aPoles); -} - -//! Create a degree 5 Bezier: P1(0,0), P2(1,3), P3(2,-1), P4(3,2), P5(4,-2), P6(5,1). -occ::handle makeDegree5Bezier() -{ - NCollection_Array1 aPoles(1, 6); - aPoles(1) = gp_Pnt2d(0.0, 0.0); - aPoles(2) = gp_Pnt2d(1.0, 3.0); - aPoles(3) = gp_Pnt2d(2.0, -1.0); - aPoles(4) = gp_Pnt2d(3.0, 2.0); - aPoles(5) = gp_Pnt2d(4.0, -2.0); - aPoles(6) = gp_Pnt2d(5.0, 1.0); - return new Geom2d_BezierCurve(aPoles); -} - -} // namespace - -TEST(Geom2dProp_BezierCurveTest, Tangent_CubicEndpoints) -{ - // At t=0, tangent should be aligned with P1->P2; at t=1, with P3->P4. - occ::handle aBezier = makeCubicSBezier(); - Geom2dProp_Curve aProp(aBezier); - - // t=0: tangent along P1(0,0)->P2(1,2) = (1,2) - const Geom2dProp::TangentResult aTan0 = aProp.Tangent(0.0, THE_LIN_TOL); - ASSERT_TRUE(aTan0.IsDefined); - const gp_Dir2d anExpDir0(1.0, 2.0); - const double aDot0 = aTan0.Direction.X() * anExpDir0.X() + aTan0.Direction.Y() * anExpDir0.Y(); - EXPECT_NEAR(std::abs(aDot0), 1.0, THE_DIR_TOL); - - // t=1: tangent along P3(3,-1)->P4(4,1) = (1,2) - const Geom2dProp::TangentResult aTan1 = aProp.Tangent(1.0, THE_LIN_TOL); - ASSERT_TRUE(aTan1.IsDefined); - const gp_Dir2d anExpDir1(1.0, 2.0); - const double aDot1 = aTan1.Direction.X() * anExpDir1.X() + aTan1.Direction.Y() * anExpDir1.Y(); - EXPECT_NEAR(std::abs(aDot1), 1.0, THE_DIR_TOL); -} - -TEST(Geom2dProp_BezierCurveTest, Tangent_QuadraticMidpoint) -{ - // At midpoint t=0.5 of symmetric quadratic, tangent should be along X axis. - occ::handle aBezier = makeQuadraticBezier(); - Geom2dProp_Curve aProp(aBezier); - - const Geom2dProp::TangentResult aTan = aProp.Tangent(0.5, THE_LIN_TOL); - ASSERT_TRUE(aTan.IsDefined); - // By symmetry of P1(0,0), P2(2,4), P3(4,0), tangent at midpoint is horizontal. - const double aDotX = aTan.Direction.X() * 1.0 + aTan.Direction.Y() * 0.0; - EXPECT_NEAR(std::abs(aDotX), 1.0, THE_DIR_TOL); -} - -TEST(Geom2dProp_BezierCurveTest, Curvature_QuadraticConstantSign) -{ - // Quadratic Bezier curvature should not change sign. - occ::handle aBezier = makeQuadraticBezier(); - Geom2dProp_Curve aProp(aBezier); - - int aPositiveCount = 0; - int aNegativeCount = 0; - for (double t = 0.0; t <= 1.0; t += 0.05) - { - const Geom2dProp::CurvatureResult aCurv = aProp.Curvature(t, THE_LIN_TOL); - ASSERT_TRUE(aCurv.IsDefined); - if (aCurv.Value > THE_CURV_TOL) - { - ++aPositiveCount; - } - else if (aCurv.Value < -THE_CURV_TOL) - { - ++aNegativeCount; - } - } - // Should be all one sign (no inflection in a quadratic). - EXPECT_TRUE(aPositiveCount == 0 || aNegativeCount == 0); -} - -TEST(Geom2dProp_BezierCurveTest, Curvature_CubicInflection) -{ - // S-shaped cubic should have curvature near zero at inflection point. - occ::handle aBezier = makeCubicSBezier(); - Geom2dProp_Curve aProp(aBezier); - - // Find parameter where curvature is closest to zero. - double aMinAbsCurv = 1.0e30; - double aMinCurvParam = 0.0; - for (double t = 0.01; t <= 0.99; t += 0.01) - { - const Geom2dProp::CurvatureResult aCurv = aProp.Curvature(t, THE_LIN_TOL); - if (aCurv.IsDefined && std::abs(aCurv.Value) < aMinAbsCurv) - { - aMinAbsCurv = std::abs(aCurv.Value); - aMinCurvParam = t; - } - } - // Curvature at inflection should be near zero. - EXPECT_LT(aMinAbsCurv, 1.0) << "Inflection not found, min curvature at t=" << aMinCurvParam; -} - -TEST(Geom2dProp_BezierCurveTest, Normal_Cubic) -{ - // Normal should be defined where curvature is non-zero. - occ::handle aBezier = makeCubicSBezier(); - Geom2dProp_Curve aProp(aBezier); - - // At t=0, curvature should be non-zero so normal is defined. - const Geom2dProp::CurvatureResult aCurv = aProp.Curvature(0.0, THE_LIN_TOL); - ASSERT_TRUE(aCurv.IsDefined); - if (std::abs(aCurv.Value) > THE_LIN_TOL) - { - const Geom2dProp::NormalResult aNorm = aProp.Normal(0.0, THE_LIN_TOL); - ASSERT_TRUE(aNorm.IsDefined); - - // Normal should be perpendicular to tangent. - const Geom2dProp::TangentResult aTan = aProp.Tangent(0.0, THE_LIN_TOL); - ASSERT_TRUE(aTan.IsDefined); - const double aDot = - aNorm.Direction.X() * aTan.Direction.X() + aNorm.Direction.Y() * aTan.Direction.Y(); - EXPECT_NEAR(std::abs(aDot), 0.0, THE_DIR_TOL); - } -} - -TEST(Geom2dProp_BezierCurveTest, Centre_Cubic) -{ - // Centre of curvature should be defined where curvature is non-zero. - occ::handle aBezier = makeCubicSBezier(); - Geom2dProp_Curve aProp(aBezier); - - const Geom2dProp::CurvatureResult aCurv = aProp.Curvature(0.2, THE_LIN_TOL); - ASSERT_TRUE(aCurv.IsDefined); - if (std::abs(aCurv.Value) > THE_LIN_TOL) - { - const Geom2dProp::CentreResult aCentre = aProp.CentreOfCurvature(0.2, THE_LIN_TOL); - ASSERT_TRUE(aCentre.IsDefined); - - // Radius of curvature should be 1/|k|. - gp_Pnt2d aPnt; - aBezier->D0(0.2, aPnt); - const double aDist = - std::sqrt((aCentre.Centre.X() - aPnt.X()) * (aCentre.Centre.X() - aPnt.X()) - + (aCentre.Centre.Y() - aPnt.Y()) * (aCentre.Centre.Y() - aPnt.Y())); - const double anExpRadius = 1.0 / std::abs(aCurv.Value); - EXPECT_NEAR(aDist, anExpRadius, THE_POINT_TOL); - } -} - -TEST(Geom2dProp_BezierCurveTest, FindCurvatureExtrema_Cubic) -{ - // Cubic S-shaped Bezier should have at least one curvature extremum. - occ::handle aBezier = makeCubicSBezier(); - Geom2dProp_Curve aProp(aBezier); - - const Geom2dProp::CurveAnalysis aExtrema = aProp.FindCurvatureExtrema(); - ASSERT_TRUE(aExtrema.IsDone); - EXPECT_GE(aExtrema.Points.Length(), 1); -} - -TEST(Geom2dProp_BezierCurveTest, FindInflections_CubicS) -{ - // S-shaped cubic should have at least one inflection point. - occ::handle aBezier = makeCubicSBezier(); - Geom2dProp_Curve aProp(aBezier); - - const Geom2dProp::CurveAnalysis aInflections = aProp.FindInflections(); - ASSERT_TRUE(aInflections.IsDone); - EXPECT_GE(aInflections.Points.Length(), 1); - - // Inflection parameters should be in [0, 1]. - for (int i = 0; i < aInflections.Points.Length(); ++i) - { - EXPECT_GE(aInflections.Points.Value(i).Parameter, 0.0); - EXPECT_LE(aInflections.Points.Value(i).Parameter, 1.0); - EXPECT_EQ(aInflections.Points.Value(i).Type, Geom2dProp::CIType::Inflection); - } -} - -TEST(Geom2dProp_BezierCurveTest, FindInflections_QuadraticNone) -{ - // Quadratic Bezier has no inflection points. - occ::handle aBezier = makeQuadraticBezier(); - Geom2dProp_Curve aProp(aBezier); - - const Geom2dProp::CurveAnalysis aInflections = aProp.FindInflections(); - ASSERT_TRUE(aInflections.IsDone); - EXPECT_EQ(aInflections.Points.Length(), 0); -} - -TEST(Geom2dProp_BezierCurveTest, FindCurvatureExtrema_Quadratic) -{ - // Quadratic Bezier should have curvature extrema. - occ::handle aBezier = makeQuadraticBezier(); - Geom2dProp_Curve aProp(aBezier); - - const Geom2dProp::CurveAnalysis aExtrema = aProp.FindCurvatureExtrema(); - ASSERT_TRUE(aExtrema.IsDone); - EXPECT_GE(aExtrema.Points.Length(), 1); -} - -TEST(Geom2dProp_BezierCurveTest, GetType_IsBezier) -{ - occ::handle aBezier = makeQuadraticBezier(); - Geom2dProp_Curve aProp(aBezier); - - EXPECT_EQ(aProp.GetType(), GeomAbs_BezierCurve); -} - -TEST(Geom2dProp_BezierCurveTest, VsCLProps2d_CubicS) -{ - // Cross-validate against deprecated CLProps2d for cubic S-curve. - occ::handle aBezier = makeCubicSBezier(); - - Geom2dProp_Curve aProp(aBezier); - Geom2dLProp_CLProps2d aOld(aBezier, 2, THE_LIN_TOL); - - compareAll(aProp, aOld, 0.0, 1.0, 10); -} - -TEST(Geom2dProp_BezierCurveTest, VsCLProps2d_Quadratic) -{ - // Cross-validate against deprecated CLProps2d for quadratic. - occ::handle aBezier = makeQuadraticBezier(); - - Geom2dProp_Curve aProp(aBezier); - Geom2dLProp_CLProps2d aOld(aBezier, 2, THE_LIN_TOL); - - compareAll(aProp, aOld, 0.0, 1.0, 10); -} - -TEST(Geom2dProp_BezierCurveTest, VsCLProps2d_HighDegree) -{ - // Cross-validate against deprecated CLProps2d for degree 5. - occ::handle aBezier = makeDegree5Bezier(); - - Geom2dProp_Curve aProp(aBezier); - Geom2dLProp_CLProps2d aOld(aBezier, 2, THE_LIN_TOL); - - compareAll(aProp, aOld, 0.0, 1.0, 20); -} - -TEST(Geom2dProp_BezierCurveTest, VsCLProps2d_AllProperties_Cubic) -{ - // Dense comparison for cubic S-curve. - occ::handle aBezier = makeCubicSBezier(); - - Geom2dProp_Curve aProp(aBezier); - Geom2dLProp_CLProps2d aOld(aBezier, 2, THE_LIN_TOL); - - compareAll(aProp, aOld, 0.0, 1.0, 40); -} - -TEST(Geom2dProp_BezierCurveTest, VsCLProps2d_AllProperties_Degree5) -{ - // Dense comparison for degree 5 curve. - occ::handle aBezier = makeDegree5Bezier(); - - Geom2dProp_Curve aProp(aBezier); - Geom2dLProp_CLProps2d aOld(aBezier, 2, THE_LIN_TOL); - - compareAll(aProp, aOld, 0.0, 1.0, 40); -} - -TEST(Geom2dProp_BezierCurveTest, Curvature_LinearBezier) -{ - // Linear Bezier (degree 1) should have zero curvature everywhere. - occ::handle aBezier = makeLinearBezier(); - Geom2dProp_Curve aProp(aBezier); - - for (double t = 0.0; t <= 1.0; t += 0.1) - { - const Geom2dProp::CurvatureResult aCurv = aProp.Curvature(t, THE_LIN_TOL); - ASSERT_TRUE(aCurv.IsDefined); - EXPECT_NEAR(aCurv.Value, 0.0, THE_CURV_TOL) << "Non-zero curvature at t=" << t; - } -} - -TEST(Geom2dProp_BezierCurveTest, Tangent_LinearBezier) -{ - // Linear Bezier should have constant tangent along P1->P2. - occ::handle aBezier = makeLinearBezier(); - Geom2dProp_Curve aProp(aBezier); - - const gp_Dir2d anExpDir(1.0, 0.0); // P1(0,0)->P2(4,0) = (4,0) normalized = (1,0) - for (double t = 0.0; t <= 1.0; t += 0.1) - { - const Geom2dProp::TangentResult aTan = aProp.Tangent(t, THE_LIN_TOL); - ASSERT_TRUE(aTan.IsDefined); - const double aDot = aTan.Direction.X() * anExpDir.X() + aTan.Direction.Y() * anExpDir.Y(); - EXPECT_NEAR(std::abs(aDot), 1.0, THE_DIR_TOL) << "Tangent not constant at t=" << t; - } -} - -TEST(Geom2dProp_BezierCurveTest, VsCurAndInf2d_CubicS_Inflections) -{ - // Compare inflection results with deprecated CurAndInf2d. - occ::handle aBezier = makeCubicSBezier(); - - Geom2dLProp_CurAndInf2d anOld; - anOld.PerformInf(aBezier); - ASSERT_TRUE(anOld.IsDone()); - - Geom2dProp_Curve aProp(aBezier); - const Geom2dProp::CurveAnalysis aNew = aProp.FindInflections(); - ASSERT_TRUE(aNew.IsDone); - - compareExtrema(aNew, anOld); -} - -TEST(Geom2dProp_BezierCurveTest, VsCurAndInf2d_CubicS_Extrema) -{ - // Compare curvature extrema with deprecated CurAndInf2d. - occ::handle aBezier = makeCubicSBezier(); - - Geom2dLProp_CurAndInf2d anOld; - anOld.PerformCurExt(aBezier); - ASSERT_TRUE(anOld.IsDone()); - - Geom2dProp_Curve aProp(aBezier); - const Geom2dProp::CurveAnalysis aNew = aProp.FindCurvatureExtrema(); - ASSERT_TRUE(aNew.IsDone); - - compareExtrema(aNew, anOld); -} - -TEST(Geom2dProp_BezierCurveTest, VsCurAndInf2d_HighDegree_FullPerform) -{ - // Compare full perform (extrema + inflections) with deprecated CurAndInf2d for degree 5. - occ::handle aBezier = makeDegree5Bezier(); - - Geom2dLProp_CurAndInf2d anOld; - anOld.Perform(aBezier); - ASSERT_TRUE(anOld.IsDone()); - - Geom2dProp_Curve aProp(aBezier); - const Geom2dProp::CurveAnalysis aNewExt = aProp.FindCurvatureExtrema(); - const Geom2dProp::CurveAnalysis aNewInfl = aProp.FindInflections(); - ASSERT_TRUE(aNewExt.IsDone); - ASSERT_TRUE(aNewInfl.IsDone); - - const int aNewTotal = aNewExt.Points.Length() + aNewInfl.Points.Length(); - EXPECT_EQ(aNewTotal, anOld.NbPoints()); -} - -TEST(Geom2dProp_BezierCurveTest, VsCLProps2d_CriticalPoints) -{ - NCollection_Array1 aPoles(1, 4); - aPoles(1) = gp_Pnt2d(0.0, 0.0); - aPoles(2) = gp_Pnt2d(1.0, 2.0); - aPoles(3) = gp_Pnt2d(3.0, -1.0); - aPoles(4) = gp_Pnt2d(4.0, 0.0); - occ::handle aBezier = new Geom2d_BezierCurve(aPoles); - Geom2dProp_Curve aProp(aBezier); - Geom2dLProp_CLProps2d aOld(aBezier, 2, THE_LIN_TOL); - const double aParams[] = - {0.0, 1.0e-10, 1.0e-6, 0.01, 0.25, 0.5, 0.75, 0.99, 1.0 - 1.0e-6, 1.0 - 1.0e-10, 1.0}; - for (const double aParam : aParams) - { - compareTangent(aProp, aOld, aParam); - compareCurvature(aProp, aOld, aParam); - compareNormal(aProp, aOld, aParam); - compareCentre(aProp, aOld, aParam); - } -} diff --git a/src/ModelingData/TKG2d/GTests/Geom2dProp_Circle_Test.cxx b/src/ModelingData/TKG2d/GTests/Geom2dProp_Circle_Test.cxx deleted file mode 100644 index 082e690f15..0000000000 --- a/src/ModelingData/TKG2d/GTests/Geom2dProp_Circle_Test.cxx +++ /dev/null @@ -1,444 +0,0 @@ -// 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. - -// Tests for Geom2dProp_Curve local differential properties on 2D circles. -// Circles have constant curvature 1/R, tangent perpendicular to radius, -// normal pointing to center, and centre of curvature at the circle center. - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -namespace -{ -constexpr double THE_LIN_TOL = Precision::PConfusion(); -constexpr double THE_CURV_TOL = 1.0e-8; -constexpr double THE_DIR_TOL = 1.0e-6; -constexpr double THE_POINT_TOL = 1.0e-6; - -void compareTangent(Geom2dProp_Curve& theProp, Geom2dLProp_CLProps2d& theOld, const double theParam) -{ - theOld.SetParameter(theParam); - const Geom2dProp::TangentResult aNew = theProp.Tangent(theParam, THE_LIN_TOL); - if (theOld.IsTangentDefined()) - { - ASSERT_TRUE(aNew.IsDefined); - gp_Dir2d anOldDir; - theOld.Tangent(anOldDir); - const double aDot = aNew.Direction.X() * anOldDir.X() + aNew.Direction.Y() * anOldDir.Y(); - EXPECT_NEAR(std::abs(aDot), 1.0, THE_DIR_TOL); - } -} - -void compareCurvature(Geom2dProp_Curve& theProp, - Geom2dLProp_CLProps2d& theOld, - const double theParam) -{ - theOld.SetParameter(theParam); - const Geom2dProp::CurvatureResult aNew = theProp.Curvature(theParam, THE_LIN_TOL); - const double aOldCurv = theOld.Curvature(); - if (aNew.IsDefined && !aNew.IsInfinite) - { - EXPECT_NEAR(aNew.Value, aOldCurv, THE_CURV_TOL); - } -} - -void compareNormal(Geom2dProp_Curve& theProp, Geom2dLProp_CLProps2d& theOld, const double theParam) -{ - theOld.SetParameter(theParam); - const Geom2dProp::NormalResult aNew = theProp.Normal(theParam, THE_LIN_TOL); - const double aOldCurv = theOld.Curvature(); - if (std::abs(aOldCurv) < THE_LIN_TOL) - { - return; - } - if (aNew.IsDefined) - { - gp_Dir2d anOldNorm; - theOld.Normal(anOldNorm); - const double aDot = aNew.Direction.X() * anOldNorm.X() + aNew.Direction.Y() * anOldNorm.Y(); - EXPECT_NEAR(std::abs(aDot), 1.0, THE_DIR_TOL); - } -} - -void compareCentre(Geom2dProp_Curve& theProp, Geom2dLProp_CLProps2d& theOld, const double theParam) -{ - theOld.SetParameter(theParam); - const Geom2dProp::CentreResult aNew = theProp.CentreOfCurvature(theParam, THE_LIN_TOL); - const double aOldCurv = theOld.Curvature(); - if (std::abs(aOldCurv) < THE_LIN_TOL) - { - return; - } - if (aNew.IsDefined) - { - gp_Pnt2d anOldCentre; - theOld.CentreOfCurvature(anOldCentre); - EXPECT_NEAR(aNew.Centre.X(), anOldCentre.X(), THE_POINT_TOL); - EXPECT_NEAR(aNew.Centre.Y(), anOldCentre.Y(), THE_POINT_TOL); - } -} - -void compareAll(Geom2dProp_Curve& theProp, - Geom2dLProp_CLProps2d& theOld, - const double theFirst, - const double theLast, - const int theNbSamples = 10) -{ - const double aStep = (theLast - theFirst) / theNbSamples; - for (int i = 0; i <= theNbSamples; ++i) - { - const double aParam = theFirst + i * aStep; - compareTangent(theProp, theOld, aParam); - compareCurvature(theProp, theOld, aParam); - compareNormal(theProp, theOld, aParam); - compareCentre(theProp, theOld, aParam); - } -} -} // namespace - -// Test 1: Curvature is constant 1/R -TEST(Geom2dProp_CircleTest, Curvature_IsConstant) -{ - const double aRadius = 5.0; - gp_Circ2d aCirc(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), aRadius); - occ::handle aCircle = new Geom2d_Circle(aCirc); - Geom2dProp_Curve aProp(aCircle); - - const Geom2dProp::CurvatureResult aCurv = aProp.Curvature(0.0, THE_LIN_TOL); - ASSERT_TRUE(aCurv.IsDefined); - EXPECT_NEAR(std::abs(aCurv.Value), 1.0 / aRadius, THE_CURV_TOL); -} - -// Test 2: Curvature constant at 12 equally spaced params -TEST(Geom2dProp_CircleTest, Curvature_AllParams) -{ - const double aRadius = 7.0; - gp_Circ2d aCirc(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), aRadius); - occ::handle aCircle = new Geom2d_Circle(aCirc); - Geom2dProp_Curve aProp(aCircle); - - for (int i = 0; i < 12; ++i) - { - const double u = i * M_PI / 6.0; - const Geom2dProp::CurvatureResult aCurv = aProp.Curvature(u, THE_LIN_TOL); - ASSERT_TRUE(aCurv.IsDefined) << "at u=" << u; - EXPECT_NEAR(std::abs(aCurv.Value), 1.0 / aRadius, THE_CURV_TOL) << "at u=" << u; - } -} - -// Test 3: Curvature for small radius -TEST(Geom2dProp_CircleTest, Curvature_SmallRadius) -{ - const double aRadius = 0.01; - gp_Circ2d aCirc(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), aRadius); - occ::handle aCircle = new Geom2d_Circle(aCirc); - Geom2dProp_Curve aProp(aCircle); - - const Geom2dProp::CurvatureResult aCurv = aProp.Curvature(0.0, THE_LIN_TOL); - ASSERT_TRUE(aCurv.IsDefined); - EXPECT_NEAR(std::abs(aCurv.Value), 100.0, THE_CURV_TOL); -} - -// Test 4: Curvature for large radius -TEST(Geom2dProp_CircleTest, Curvature_LargeRadius) -{ - const double aRadius = 1000.0; - gp_Circ2d aCirc(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), aRadius); - occ::handle aCircle = new Geom2d_Circle(aCirc); - Geom2dProp_Curve aProp(aCircle); - - const Geom2dProp::CurvatureResult aCurv = aProp.Curvature(0.0, THE_LIN_TOL); - ASSERT_TRUE(aCurv.IsDefined); - EXPECT_NEAR(std::abs(aCurv.Value), 0.001, THE_CURV_TOL); -} - -// Test 5: Tangent at param=0 -TEST(Geom2dProp_CircleTest, Tangent_AtZero) -{ - gp_Circ2d aCirc(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 5.0); - occ::handle aCircle = new Geom2d_Circle(aCirc); - Geom2dProp_Curve aProp(aCircle); - - const Geom2dProp::TangentResult aTan = aProp.Tangent(0.0, THE_LIN_TOL); - ASSERT_TRUE(aTan.IsDefined); - // At param=0, point is on positive X axis, tangent should be along Y - EXPECT_NEAR(std::abs(aTan.Direction.Y()), 1.0, THE_DIR_TOL); - EXPECT_NEAR(aTan.Direction.X(), 0.0, THE_DIR_TOL); -} - -// Test 6: Tangent at PI/2 -TEST(Geom2dProp_CircleTest, Tangent_AtPiOver2) -{ - gp_Circ2d aCirc(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 5.0); - occ::handle aCircle = new Geom2d_Circle(aCirc); - Geom2dProp_Curve aProp(aCircle); - - const Geom2dProp::TangentResult aTan = aProp.Tangent(M_PI / 2.0, THE_LIN_TOL); - ASSERT_TRUE(aTan.IsDefined); - // At PI/2, point is on positive Y axis, tangent should be along -X - EXPECT_NEAR(std::abs(aTan.Direction.X()), 1.0, THE_DIR_TOL); - EXPECT_NEAR(aTan.Direction.Y(), 0.0, THE_DIR_TOL); -} - -// Test 7: Tangent at PI -TEST(Geom2dProp_CircleTest, Tangent_AtPi) -{ - gp_Circ2d aCirc(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 5.0); - occ::handle aCircle = new Geom2d_Circle(aCirc); - Geom2dProp_Curve aProp(aCircle); - - const Geom2dProp::TangentResult aTan = aProp.Tangent(M_PI, THE_LIN_TOL); - ASSERT_TRUE(aTan.IsDefined); - // At PI, point is on negative X axis, tangent should be along -Y - EXPECT_NEAR(aTan.Direction.X(), 0.0, THE_DIR_TOL); - EXPECT_NEAR(std::abs(aTan.Direction.Y()), 1.0, THE_DIR_TOL); -} - -// Test 8: Normal points toward center at param=0 -TEST(Geom2dProp_CircleTest, Normal_PointsToCenter) -{ - const gp_Pnt2d aCenter(0.0, 0.0); - gp_Circ2d aCirc(gp_Ax2d(aCenter, gp_Dir2d(1.0, 0.0)), 5.0); - occ::handle aCircle = new Geom2d_Circle(aCirc); - Geom2dProp_Curve aProp(aCircle); - - const Geom2dProp::NormalResult aNorm = aProp.Normal(0.0, THE_LIN_TOL); - ASSERT_TRUE(aNorm.IsDefined); - // At param=0, point is at (5,0), normal toward center (0,0) is (-1,0) - EXPECT_NEAR(std::abs(aNorm.Direction.X()), 1.0, THE_DIR_TOL); - EXPECT_NEAR(aNorm.Direction.Y(), 0.0, THE_DIR_TOL); -} - -// Test 9: Normal always points toward center at all params -TEST(Geom2dProp_CircleTest, Normal_AllParams) -{ - const gp_Pnt2d aCenter(0.0, 0.0); - const double aRadius = 5.0; - gp_Circ2d aCirc(gp_Ax2d(aCenter, gp_Dir2d(1.0, 0.0)), aRadius); - occ::handle aCircle = new Geom2d_Circle(aCirc); - Geom2dProp_Curve aProp(aCircle); - - for (int i = 0; i < 12; ++i) - { - const double u = i * M_PI / 6.0; - const Geom2dProp::NormalResult aNorm = aProp.Normal(u, THE_LIN_TOL); - ASSERT_TRUE(aNorm.IsDefined) << "at u=" << u; - - // Point on circle - const double aPx = aRadius * std::cos(u); - const double aPy = aRadius * std::sin(u); - // Direction from point to center - const double aDx = aCenter.X() - aPx; - const double aDy = aCenter.Y() - aPy; - const double aLen = std::sqrt(aDx * aDx + aDy * aDy); - // Normal should be parallel to this direction - const double aDot = aNorm.Direction.X() * (aDx / aLen) + aNorm.Direction.Y() * (aDy / aLen); - EXPECT_NEAR(std::abs(aDot), 1.0, THE_DIR_TOL) << "at u=" << u; - } -} - -// Test 10: Centre of curvature is the circle center at all params -TEST(Geom2dProp_CircleTest, Centre_IsCircleCenter) -{ - const gp_Pnt2d aCenter(0.0, 0.0); - gp_Circ2d aCirc(gp_Ax2d(aCenter, gp_Dir2d(1.0, 0.0)), 5.0); - occ::handle aCircle = new Geom2d_Circle(aCirc); - Geom2dProp_Curve aProp(aCircle); - - for (int i = 0; i < 12; ++i) - { - const double u = i * M_PI / 6.0; - const Geom2dProp::CentreResult aCentre = aProp.CentreOfCurvature(u, THE_LIN_TOL); - ASSERT_TRUE(aCentre.IsDefined) << "at u=" << u; - EXPECT_NEAR(aCentre.Centre.X(), aCenter.X(), THE_POINT_TOL) << "at u=" << u; - EXPECT_NEAR(aCentre.Centre.Y(), aCenter.Y(), THE_POINT_TOL) << "at u=" << u; - } -} - -// Test 11: Centre of curvature for off-center circle -TEST(Geom2dProp_CircleTest, Centre_OffCenter) -{ - const gp_Pnt2d aCenter(3.0, 4.0); - gp_Circ2d aCirc(gp_Ax2d(aCenter, gp_Dir2d(1.0, 0.0)), 5.0); - occ::handle aCircle = new Geom2d_Circle(aCirc); - Geom2dProp_Curve aProp(aCircle); - - for (int i = 0; i < 8; ++i) - { - const double u = i * M_PI / 4.0; - const Geom2dProp::CentreResult aCentre = aProp.CentreOfCurvature(u, THE_LIN_TOL); - ASSERT_TRUE(aCentre.IsDefined) << "at u=" << u; - EXPECT_NEAR(aCentre.Centre.X(), aCenter.X(), THE_POINT_TOL) << "at u=" << u; - EXPECT_NEAR(aCentre.Centre.Y(), aCenter.Y(), THE_POINT_TOL) << "at u=" << u; - } -} - -// Test 12: FindCurvatureExtrema returns empty (constant curvature) -TEST(Geom2dProp_CircleTest, FindCurvatureExtrema_Empty) -{ - gp_Circ2d aCirc(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 5.0); - occ::handle aCircle = new Geom2d_Circle(aCirc); - Geom2dProp_Curve aProp(aCircle); - - const Geom2dProp::CurveAnalysis aAnalysis = aProp.FindCurvatureExtrema(); - ASSERT_TRUE(aAnalysis.IsDone); - EXPECT_EQ(aAnalysis.Points.Length(), 0); -} - -// Test 13: FindInflections returns empty -TEST(Geom2dProp_CircleTest, FindInflections_Empty) -{ - gp_Circ2d aCirc(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 5.0); - occ::handle aCircle = new Geom2d_Circle(aCirc); - Geom2dProp_Curve aProp(aCircle); - - const Geom2dProp::CurveAnalysis aAnalysis = aProp.FindInflections(); - ASSERT_TRUE(aAnalysis.IsDone); - EXPECT_EQ(aAnalysis.Points.Length(), 0); -} - -// Test 14: GetType returns GeomAbs_Circle -TEST(Geom2dProp_CircleTest, GetType_IsCircle) -{ - gp_Circ2d aCirc(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 5.0); - occ::handle aCircle = new Geom2d_Circle(aCirc); - Geom2dProp_Curve aProp(aCircle); - - EXPECT_EQ(aProp.GetType(), GeomAbs_Circle); -} - -// Test 15: Full circle comparison vs CLProps2d -TEST(Geom2dProp_CircleTest, VsCLProps2d_AllProperties) -{ - gp_Circ2d aCirc(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 5.0); - occ::handle aCircle = new Geom2d_Circle(aCirc); - - Geom2dProp_Curve aProp(aCircle); - Geom2dLProp_CLProps2d aOld(aCircle, 2, THE_LIN_TOL); - - compareAll(aProp, aOld, 0.0, 2.0 * M_PI, 24); -} - -// Test 16: Small radius comparison vs CLProps2d -TEST(Geom2dProp_CircleTest, VsCLProps2d_SmallRadius) -{ - gp_Circ2d aCirc(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 0.01); - occ::handle aCircle = new Geom2d_Circle(aCirc); - - Geom2dProp_Curve aProp(aCircle); - Geom2dLProp_CLProps2d aOld(aCircle, 2, THE_LIN_TOL); - - compareAll(aProp, aOld, 0.0, 2.0 * M_PI, 12); -} - -// Test 17: Large radius comparison vs CLProps2d -TEST(Geom2dProp_CircleTest, VsCLProps2d_LargeRadius) -{ - gp_Circ2d aCirc(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 1000.0); - occ::handle aCircle = new Geom2d_Circle(aCirc); - - Geom2dProp_Curve aProp(aCircle); - Geom2dLProp_CLProps2d aOld(aCircle, 2, THE_LIN_TOL); - - compareAll(aProp, aOld, 0.0, 2.0 * M_PI, 12); -} - -// Test 18: Off-center circle comparison vs CLProps2d -TEST(Geom2dProp_CircleTest, VsCLProps2d_OffCenter) -{ - gp_Circ2d aCirc(gp_Ax2d(gp_Pnt2d(3.0, 4.0), gp_Dir2d(1.0, 0.0)), 7.0); - occ::handle aCircle = new Geom2d_Circle(aCirc); - - Geom2dProp_Curve aProp(aCircle); - Geom2dLProp_CLProps2d aOld(aCircle, 2, THE_LIN_TOL); - - compareAll(aProp, aOld, 0.0, 2.0 * M_PI, 12); -} - -// Test 19: Tangent is perpendicular to radius direction -TEST(Geom2dProp_CircleTest, Tangent_Perpendicular) -{ - const gp_Pnt2d aCenter(0.0, 0.0); - const double aRadius = 5.0; - gp_Circ2d aCirc(gp_Ax2d(aCenter, gp_Dir2d(1.0, 0.0)), aRadius); - occ::handle aCircle = new Geom2d_Circle(aCirc); - Geom2dProp_Curve aProp(aCircle); - - for (int i = 0; i < 12; ++i) - { - const double u = i * M_PI / 6.0; - const Geom2dProp::TangentResult aTan = aProp.Tangent(u, THE_LIN_TOL); - ASSERT_TRUE(aTan.IsDefined) << "at u=" << u; - - // Radius direction at this point - const double aRx = std::cos(u); - const double aRy = std::sin(u); - // Tangent should be perpendicular to radius: dot product ~= 0 - const double aDot = aTan.Direction.X() * aRx + aTan.Direction.Y() * aRy; - EXPECT_NEAR(aDot, 0.0, THE_DIR_TOL) << "at u=" << u; - } -} - -// Test 20: Compare FindCurvatureExtrema vs old CurAndInf2d -TEST(Geom2dProp_CircleTest, VsCurAndInf2d_NoExtrema) -{ - gp_Circ2d aCirc(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 5.0); - occ::handle aCircle = new Geom2d_Circle(aCirc); - - Geom2dLProp_CurAndInf2d anOld; - anOld.PerformCurExt(aCircle); - ASSERT_TRUE(anOld.IsDone()); - EXPECT_EQ(anOld.NbPoints(), 0); - - Geom2dProp_Curve aProp(aCircle); - const Geom2dProp::CurveAnalysis aNew = aProp.FindCurvatureExtrema(); - ASSERT_TRUE(aNew.IsDone); - EXPECT_EQ(aNew.Points.Length(), 0); -} - -TEST(Geom2dProp_CircleTest, VsCLProps2d_CriticalPoints) -{ - occ::handle aCircle = - new Geom2d_Circle(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 5.0); - Geom2dProp_Curve aProp(aCircle); - Geom2dLProp_CLProps2d aOld(aCircle, 2, THE_LIN_TOL); - const double aParams[] = {0.0, - 1.0e-10, - M_PI / 4.0, - M_PI / 2.0, - M_PI, - 3.0 * M_PI / 2.0, - 2.0 * M_PI - 1.0e-10, - M_PI / 2.0 + 1.0e-6, - M_PI / 2.0 - 1.0e-6}; - for (const double aParam : aParams) - { - compareTangent(aProp, aOld, aParam); - compareCurvature(aProp, aOld, aParam); - compareNormal(aProp, aOld, aParam); - compareCentre(aProp, aOld, aParam); - } -} diff --git a/src/ModelingData/TKG2d/GTests/Geom2dProp_Ellipse_Test.cxx b/src/ModelingData/TKG2d/GTests/Geom2dProp_Ellipse_Test.cxx deleted file mode 100644 index f2a88630a9..0000000000 --- a/src/ModelingData/TKG2d/GTests/Geom2dProp_Ellipse_Test.cxx +++ /dev/null @@ -1,496 +0,0 @@ -// 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. - -// Tests for Geom2dProp_Curve local differential properties on 2D ellipses. -// Ellipse with semi-axes a (major) and b (minor): -// - Curvature at major vertex (param=0): k = a / b^2 -// - Curvature at minor vertex (param=PI/2): k = b / a^2 -// - Analytical curvature: k(t) = a*b / (a^2*sin^2(t) + b^2*cos^2(t))^(3/2) -// - 4 curvature extrema, no inflections - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -namespace -{ -constexpr double THE_LIN_TOL = Precision::PConfusion(); -constexpr double THE_CURV_TOL = 1.0e-8; -constexpr double THE_DIR_TOL = 1.0e-6; -constexpr double THE_POINT_TOL = 1.0e-6; - -void compareTangent(Geom2dProp_Curve& theProp, Geom2dLProp_CLProps2d& theOld, const double theParam) -{ - theOld.SetParameter(theParam); - const Geom2dProp::TangentResult aNew = theProp.Tangent(theParam, THE_LIN_TOL); - if (theOld.IsTangentDefined()) - { - ASSERT_TRUE(aNew.IsDefined); - gp_Dir2d anOldDir; - theOld.Tangent(anOldDir); - const double aDot = aNew.Direction.X() * anOldDir.X() + aNew.Direction.Y() * anOldDir.Y(); - EXPECT_NEAR(std::abs(aDot), 1.0, THE_DIR_TOL); - } -} - -void compareCurvature(Geom2dProp_Curve& theProp, - Geom2dLProp_CLProps2d& theOld, - const double theParam) -{ - theOld.SetParameter(theParam); - const Geom2dProp::CurvatureResult aNew = theProp.Curvature(theParam, THE_LIN_TOL); - const double aOldCurv = theOld.Curvature(); - if (aNew.IsDefined && !aNew.IsInfinite) - { - EXPECT_NEAR(aNew.Value, aOldCurv, THE_CURV_TOL); - } -} - -void compareNormal(Geom2dProp_Curve& theProp, Geom2dLProp_CLProps2d& theOld, const double theParam) -{ - theOld.SetParameter(theParam); - const Geom2dProp::NormalResult aNew = theProp.Normal(theParam, THE_LIN_TOL); - const double aOldCurv = theOld.Curvature(); - if (std::abs(aOldCurv) < THE_LIN_TOL) - { - return; - } - if (aNew.IsDefined) - { - gp_Dir2d anOldNorm; - theOld.Normal(anOldNorm); - const double aDot = aNew.Direction.X() * anOldNorm.X() + aNew.Direction.Y() * anOldNorm.Y(); - EXPECT_NEAR(std::abs(aDot), 1.0, THE_DIR_TOL); - } -} - -void compareCentre(Geom2dProp_Curve& theProp, Geom2dLProp_CLProps2d& theOld, const double theParam) -{ - theOld.SetParameter(theParam); - const Geom2dProp::CentreResult aNew = theProp.CentreOfCurvature(theParam, THE_LIN_TOL); - const double aOldCurv = theOld.Curvature(); - if (std::abs(aOldCurv) < THE_LIN_TOL) - { - return; - } - if (aNew.IsDefined) - { - gp_Pnt2d anOldCentre; - theOld.CentreOfCurvature(anOldCentre); - EXPECT_NEAR(aNew.Centre.X(), anOldCentre.X(), THE_POINT_TOL); - EXPECT_NEAR(aNew.Centre.Y(), anOldCentre.Y(), THE_POINT_TOL); - } -} - -void compareAll(Geom2dProp_Curve& theProp, - Geom2dLProp_CLProps2d& theOld, - const double theFirst, - const double theLast, - const int theNbSamples = 10) -{ - const double aStep = (theLast - theFirst) / theNbSamples; - for (int i = 0; i <= theNbSamples; ++i) - { - const double aParam = theFirst + i * aStep; - compareTangent(theProp, theOld, aParam); - compareCurvature(theProp, theOld, aParam); - compareNormal(theProp, theOld, aParam); - compareCentre(theProp, theOld, aParam); - } -} - -//! Map LProp_CIType to Geom2dProp::CIType for comparison. -Geom2dProp::CIType mapLPropType(const LProp_CIType theType) -{ - switch (theType) - { - case LProp_Inflection: - return Geom2dProp::CIType::Inflection; - case LProp_MinCur: - return Geom2dProp::CIType::MinCurvature; - case LProp_MaxCur: - return Geom2dProp::CIType::MaxCurvature; - } - return Geom2dProp::CIType::Inflection; -} - -//! Compare extrema results from old and new APIs. -void compareExtrema(const Geom2dProp::CurveAnalysis& theNew, - const Geom2dLProp_CurAndInf2d& theOld, - const double theTol = 1.0e-4) -{ - EXPECT_EQ(theNew.Points.Length(), theOld.NbPoints()); - const int aNb = std::min(theNew.Points.Length(), theOld.NbPoints()); - for (int i = 0; i < aNb; ++i) - { - EXPECT_NEAR(theNew.Points.Value(i).Parameter, theOld.Parameter(i + 1), theTol) - << "Parameter mismatch at index " << i; - EXPECT_EQ(theNew.Points.Value(i).Type, mapLPropType(theOld.Type(i + 1))) - << "Type mismatch at index " << i; - } -} -} // namespace - -// Test 1: Curvature at major vertex (param=0): k = a/b^2 -TEST(Geom2dProp_EllipseTest, Curvature_AtMajorVertex) -{ - const double a = 10.0; - const double b = 5.0; - gp_Elips2d anElips(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), a, b); - occ::handle anEllipse = new Geom2d_Ellipse(anElips); - Geom2dProp_Curve aProp(anEllipse); - - const Geom2dProp::CurvatureResult aCurv = aProp.Curvature(0.0, THE_LIN_TOL); - ASSERT_TRUE(aCurv.IsDefined); - EXPECT_NEAR(std::abs(aCurv.Value), a / (b * b), THE_CURV_TOL); -} - -// Test 2: Curvature at minor vertex (param=PI/2): k = b/a^2 -TEST(Geom2dProp_EllipseTest, Curvature_AtMinorVertex) -{ - const double a = 10.0; - const double b = 5.0; - gp_Elips2d anElips(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), a, b); - occ::handle anEllipse = new Geom2d_Ellipse(anElips); - Geom2dProp_Curve aProp(anEllipse); - - const Geom2dProp::CurvatureResult aCurv = aProp.Curvature(M_PI / 2.0, THE_LIN_TOL); - ASSERT_TRUE(aCurv.IsDefined); - EXPECT_NEAR(std::abs(aCurv.Value), b / (a * a), THE_CURV_TOL); -} - -// Test 3: Curvature symmetry: k(t) = k(-t) -TEST(Geom2dProp_EllipseTest, Curvature_Symmetry) -{ - const double a = 10.0; - const double b = 5.0; - gp_Elips2d anElips(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), a, b); - occ::handle anEllipse = new Geom2d_Ellipse(anElips); - Geom2dProp_Curve aProp(anEllipse); - - for (double t = 0.1; t < M_PI; t += 0.3) - { - const Geom2dProp::CurvatureResult aCurvPos = aProp.Curvature(t, THE_LIN_TOL); - const Geom2dProp::CurvatureResult aCurvNeg = aProp.Curvature(-t, THE_LIN_TOL); - ASSERT_TRUE(aCurvPos.IsDefined); - ASSERT_TRUE(aCurvNeg.IsDefined); - EXPECT_NEAR(std::abs(aCurvPos.Value), std::abs(aCurvNeg.Value), THE_CURV_TOL) << "at t=" << t; - } -} - -// Test 4: Tangent at major vertex is perpendicular to major axis -TEST(Geom2dProp_EllipseTest, Tangent_AtMajorVertex) -{ - gp_Elips2d anElips(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 10.0, 5.0); - occ::handle anEllipse = new Geom2d_Ellipse(anElips); - Geom2dProp_Curve aProp(anEllipse); - - const Geom2dProp::TangentResult aTan = aProp.Tangent(0.0, THE_LIN_TOL); - ASSERT_TRUE(aTan.IsDefined); - // At param=0, tangent perpendicular to major axis (1,0) => tangent along Y - EXPECT_NEAR(aTan.Direction.X(), 0.0, THE_DIR_TOL); - EXPECT_NEAR(std::abs(aTan.Direction.Y()), 1.0, THE_DIR_TOL); -} - -// Test 5: Tangent at minor vertex is perpendicular to minor axis -TEST(Geom2dProp_EllipseTest, Tangent_AtMinorVertex) -{ - gp_Elips2d anElips(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 10.0, 5.0); - occ::handle anEllipse = new Geom2d_Ellipse(anElips); - Geom2dProp_Curve aProp(anEllipse); - - const Geom2dProp::TangentResult aTan = aProp.Tangent(M_PI / 2.0, THE_LIN_TOL); - ASSERT_TRUE(aTan.IsDefined); - // At param=PI/2, tangent perpendicular to minor axis (0,1) => tangent along X - EXPECT_NEAR(std::abs(aTan.Direction.X()), 1.0, THE_DIR_TOL); - EXPECT_NEAR(aTan.Direction.Y(), 0.0, THE_DIR_TOL); -} - -// Test 6: Normal at major vertex is along major axis toward center -TEST(Geom2dProp_EllipseTest, Normal_AtMajorVertex) -{ - gp_Elips2d anElips(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 10.0, 5.0); - occ::handle anEllipse = new Geom2d_Ellipse(anElips); - Geom2dProp_Curve aProp(anEllipse); - - const Geom2dProp::NormalResult aNorm = aProp.Normal(0.0, THE_LIN_TOL); - ASSERT_TRUE(aNorm.IsDefined); - // At param=0, point is at (a,0), normal toward center => (-1,0) - EXPECT_NEAR(std::abs(aNorm.Direction.X()), 1.0, THE_DIR_TOL); - EXPECT_NEAR(aNorm.Direction.Y(), 0.0, THE_DIR_TOL); -} - -// Test 7: Normal at minor vertex is along minor axis toward center -TEST(Geom2dProp_EllipseTest, Normal_AtMinorVertex) -{ - gp_Elips2d anElips(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 10.0, 5.0); - occ::handle anEllipse = new Geom2d_Ellipse(anElips); - Geom2dProp_Curve aProp(anEllipse); - - const Geom2dProp::NormalResult aNorm = aProp.Normal(M_PI / 2.0, THE_LIN_TOL); - ASSERT_TRUE(aNorm.IsDefined); - // At param=PI/2, point is at (0,b), normal toward center => (0,-1) - EXPECT_NEAR(aNorm.Direction.X(), 0.0, THE_DIR_TOL); - EXPECT_NEAR(std::abs(aNorm.Direction.Y()), 1.0, THE_DIR_TOL); -} - -// Test 8: Centre at major vertex: radius of curvature = b^2/a -TEST(Geom2dProp_EllipseTest, Centre_AtMajorVertex) -{ - const double a = 10.0; - const double b = 5.0; - gp_Elips2d anElips(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), a, b); - occ::handle anEllipse = new Geom2d_Ellipse(anElips); - Geom2dProp_Curve aProp(anEllipse); - - const Geom2dProp::CentreResult aCentre = aProp.CentreOfCurvature(0.0, THE_LIN_TOL); - ASSERT_TRUE(aCentre.IsDefined); - // Centre is at distance b^2/a from the point along the normal toward center - // Point at (a,0), centre at (a - b^2/a, 0) - const double aExpectedX = a - (b * b) / a; - EXPECT_NEAR(aCentre.Centre.X(), aExpectedX, THE_POINT_TOL); - EXPECT_NEAR(aCentre.Centre.Y(), 0.0, THE_POINT_TOL); -} - -// Test 9: Centre at minor vertex: radius of curvature = a^2/b -TEST(Geom2dProp_EllipseTest, Centre_AtMinorVertex) -{ - const double a = 10.0; - const double b = 5.0; - gp_Elips2d anElips(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), a, b); - occ::handle anEllipse = new Geom2d_Ellipse(anElips); - Geom2dProp_Curve aProp(anEllipse); - - const Geom2dProp::CentreResult aCentre = aProp.CentreOfCurvature(M_PI / 2.0, THE_LIN_TOL); - ASSERT_TRUE(aCentre.IsDefined); - // Point at (0,b), centre at (0, b - a^2/b) - const double aExpectedY = b - (a * a) / b; - EXPECT_NEAR(aCentre.Centre.X(), 0.0, THE_POINT_TOL); - EXPECT_NEAR(aCentre.Centre.Y(), aExpectedY, THE_POINT_TOL); -} - -// Test 10: FindCurvatureExtrema returns 4 points -TEST(Geom2dProp_EllipseTest, FindCurvatureExtrema_FourPoints) -{ - gp_Elips2d anElips(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 10.0, 5.0); - occ::handle anEllipse = new Geom2d_Ellipse(anElips); - Geom2dProp_Curve aProp(anEllipse); - - const Geom2dProp::CurveAnalysis aAnalysis = aProp.FindCurvatureExtrema(); - ASSERT_TRUE(aAnalysis.IsDone); - EXPECT_EQ(aAnalysis.Points.Length(), 4); -} - -// Test 11: FindInflections returns empty (no inflections) -TEST(Geom2dProp_EllipseTest, FindInflections_Empty) -{ - gp_Elips2d anElips(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 10.0, 5.0); - occ::handle anEllipse = new Geom2d_Ellipse(anElips); - Geom2dProp_Curve aProp(anEllipse); - - const Geom2dProp::CurveAnalysis aAnalysis = aProp.FindInflections(); - ASSERT_TRUE(aAnalysis.IsDone); - EXPECT_EQ(aAnalysis.Points.Length(), 0); -} - -// Test 12: GetType returns GeomAbs_Ellipse -TEST(Geom2dProp_EllipseTest, GetType_IsEllipse) -{ - gp_Elips2d anElips(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 10.0, 5.0); - occ::handle anEllipse = new Geom2d_Ellipse(anElips); - Geom2dProp_Curve aProp(anEllipse); - - EXPECT_EQ(aProp.GetType(), GeomAbs_Ellipse); -} - -// Test 13: Curvature for high eccentricity ellipse (a=100, b=1) -TEST(Geom2dProp_EllipseTest, Curvature_HighEccentricity) -{ - const double a = 100.0; - const double b = 1.0; - gp_Elips2d anElips(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), a, b); - occ::handle anEllipse = new Geom2d_Ellipse(anElips); - Geom2dProp_Curve aProp(anEllipse); - - // At major vertex: k = a/b^2 = 100 - const Geom2dProp::CurvatureResult aCurvMaj = aProp.Curvature(0.0, THE_LIN_TOL); - ASSERT_TRUE(aCurvMaj.IsDefined); - EXPECT_NEAR(std::abs(aCurvMaj.Value), a / (b * b), 1.0e-6); - - // At minor vertex: k = b/a^2 = 0.0001 - const Geom2dProp::CurvatureResult aCurvMin = aProp.Curvature(M_PI / 2.0, THE_LIN_TOL); - ASSERT_TRUE(aCurvMin.IsDefined); - EXPECT_NEAR(std::abs(aCurvMin.Value), b / (a * a), 1.0e-10); -} - -// Test 14: Curvature for nearly circular ellipse (a=5, b=4.99) -TEST(Geom2dProp_EllipseTest, Curvature_NearlyCircular) -{ - const double a = 5.0; - const double b = 4.99; - gp_Elips2d anElips(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), a, b); - occ::handle anEllipse = new Geom2d_Ellipse(anElips); - Geom2dProp_Curve aProp(anEllipse); - - const Geom2dProp::CurvatureResult aCurvMaj = aProp.Curvature(0.0, THE_LIN_TOL); - const Geom2dProp::CurvatureResult aCurvMin = aProp.Curvature(M_PI / 2.0, THE_LIN_TOL); - ASSERT_TRUE(aCurvMaj.IsDefined); - ASSERT_TRUE(aCurvMin.IsDefined); - // For nearly circular, curvatures at vertices should be close - EXPECT_NEAR(std::abs(aCurvMaj.Value), a / (b * b), THE_CURV_TOL); - EXPECT_NEAR(std::abs(aCurvMin.Value), b / (a * a), THE_CURV_TOL); -} - -// Test 15: Standard ellipse (a=10, b=5) comparison vs CLProps2d -TEST(Geom2dProp_EllipseTest, VsCLProps2d_Standard) -{ - gp_Elips2d anElips(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 10.0, 5.0); - occ::handle anEllipse = new Geom2d_Ellipse(anElips); - - Geom2dProp_Curve aProp(anEllipse); - Geom2dLProp_CLProps2d aOld(anEllipse, 2, THE_LIN_TOL); - - compareAll(aProp, aOld, 0.0, 2.0 * M_PI, 24); -} - -// Test 16: High eccentricity (a=100, b=1) comparison vs CLProps2d -TEST(Geom2dProp_EllipseTest, VsCLProps2d_HighEccentricity) -{ - gp_Elips2d anElips(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 100.0, 1.0); - occ::handle anEllipse = new Geom2d_Ellipse(anElips); - - Geom2dProp_Curve aProp(anEllipse); - Geom2dLProp_CLProps2d aOld(anEllipse, 2, THE_LIN_TOL); - - compareAll(aProp, aOld, 0.0, 2.0 * M_PI, 24); -} - -// Test 17: Dense comparison of all properties vs CLProps2d -TEST(Geom2dProp_EllipseTest, VsCLProps2d_AllProperties) -{ - gp_Elips2d anElips(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 10.0, 5.0); - occ::handle anEllipse = new Geom2d_Ellipse(anElips); - - Geom2dProp_Curve aProp(anEllipse); - Geom2dLProp_CLProps2d aOld(anEllipse, 2, THE_LIN_TOL); - - compareAll(aProp, aOld, 0.0, 2.0 * M_PI, 48); -} - -// Test 18: Off-center ellipse comparison vs CLProps2d -TEST(Geom2dProp_EllipseTest, VsCLProps2d_OffCenter) -{ - gp_Elips2d anElips(gp_Ax2d(gp_Pnt2d(100.0, -50.0), gp_Dir2d(1.0, 0.0)), 8.0, 3.0); - occ::handle anEllipse = new Geom2d_Ellipse(anElips); - - Geom2dProp_Curve aProp(anEllipse); - Geom2dLProp_CLProps2d aOld(anEllipse, 2, THE_LIN_TOL); - - compareAll(aProp, aOld, 0.0, 2.0 * M_PI, 24); -} - -// Test 19: Compare FindCurvatureExtrema vs old CurAndInf2d -TEST(Geom2dProp_EllipseTest, VsCurAndInf2d_Extrema) -{ - gp_Elips2d anElips(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 10.0, 5.0); - occ::handle anEllipse = new Geom2d_Ellipse(anElips); - - Geom2dLProp_CurAndInf2d anOld; - anOld.PerformCurExt(anEllipse); - ASSERT_TRUE(anOld.IsDone()); - - Geom2dProp_Curve aProp(anEllipse); - const Geom2dProp::CurveAnalysis aNew = aProp.FindCurvatureExtrema(); - ASSERT_TRUE(aNew.IsDone); - - compareExtrema(aNew, anOld, 1.0e-6); -} - -// Test 20: Compare FindInflections vs old CurAndInf2d (no inflections) -TEST(Geom2dProp_EllipseTest, VsCurAndInf2d_NoInflections) -{ - gp_Elips2d anElips(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 10.0, 5.0); - occ::handle anEllipse = new Geom2d_Ellipse(anElips); - - Geom2dLProp_CurAndInf2d anOld; - anOld.PerformInf(anEllipse); - ASSERT_TRUE(anOld.IsDone()); - EXPECT_EQ(anOld.NbPoints(), 0); - - Geom2dProp_Curve aProp(anEllipse); - const Geom2dProp::CurveAnalysis aNew = aProp.FindInflections(); - ASSERT_TRUE(aNew.IsDone); - EXPECT_EQ(aNew.Points.Length(), 0); -} - -// Test 21: Curvature matches analytical formula k(t) = ab/(a^2*sin^2(t) + b^2*cos^2(t))^(3/2) -TEST(Geom2dProp_EllipseTest, Curvature_MatchesAnalytical) -{ - const double a = 10.0; - const double b = 5.0; - gp_Elips2d anElips(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), a, b); - occ::handle anEllipse = new Geom2d_Ellipse(anElips); - Geom2dProp_Curve aProp(anEllipse); - - for (double t = 0.0; t < 2.0 * M_PI; t += M_PI / 12.0) - { - const double aSin = std::sin(t); - const double aCos = std::cos(t); - const double aDenom = a * a * aSin * aSin + b * b * aCos * aCos; - const double aExpectedK = (a * b) / (aDenom * std::sqrt(aDenom)); - - const Geom2dProp::CurvatureResult aCurv = aProp.Curvature(t, THE_LIN_TOL); - ASSERT_TRUE(aCurv.IsDefined) << "at t=" << t; - EXPECT_NEAR(std::abs(aCurv.Value), aExpectedK, THE_CURV_TOL) << "at t=" << t; - } -} - -TEST(Geom2dProp_EllipseTest, VsCLProps2d_CriticalPoints) -{ - gp_Elips2d anElips(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 10.0, 3.0); - occ::handle anEllipse = new Geom2d_Ellipse(anElips); - Geom2dProp_Curve aProp(anEllipse); - Geom2dLProp_CLProps2d aOld(anEllipse, 2, THE_LIN_TOL); - const double aParams[] = {0.0, - 1.0e-10, - -1.0e-10, - M_PI / 2.0, - M_PI / 2.0 + 1.0e-10, - M_PI / 2.0 - 1.0e-10, - M_PI, - M_PI + 1.0e-6, - 3.0 * M_PI / 2.0, - 3.0 * M_PI / 2.0 + 1.0e-6, - M_PI / 4.0, - 3.0 * M_PI / 4.0, - 2.0 * M_PI - 1.0e-10}; - for (const double aParam : aParams) - { - compareTangent(aProp, aOld, aParam); - compareCurvature(aProp, aOld, aParam); - compareNormal(aProp, aOld, aParam); - compareCentre(aProp, aOld, aParam); - } -} diff --git a/src/ModelingData/TKG2d/GTests/Geom2dProp_Hyperbola_Test.cxx b/src/ModelingData/TKG2d/GTests/Geom2dProp_Hyperbola_Test.cxx deleted file mode 100644 index ad436a4592..0000000000 --- a/src/ModelingData/TKG2d/GTests/Geom2dProp_Hyperbola_Test.cxx +++ /dev/null @@ -1,481 +0,0 @@ -// 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -namespace -{ -constexpr double THE_LIN_TOL = Precision::PConfusion(); -constexpr double THE_CURV_TOL = 1.0e-8; -constexpr double THE_DIR_TOL = 1.0e-6; -constexpr double THE_POINT_TOL = 1.0e-6; - -void compareTangent(Geom2dProp_Curve& theProp, Geom2dLProp_CLProps2d& theOld, const double theParam) -{ - theOld.SetParameter(theParam); - const Geom2dProp::TangentResult aNew = theProp.Tangent(theParam, THE_LIN_TOL); - if (theOld.IsTangentDefined()) - { - ASSERT_TRUE(aNew.IsDefined); - gp_Dir2d anOldDir; - theOld.Tangent(anOldDir); - const double aDot = aNew.Direction.X() * anOldDir.X() + aNew.Direction.Y() * anOldDir.Y(); - EXPECT_NEAR(std::abs(aDot), 1.0, THE_DIR_TOL); - } -} - -void compareCurvature(Geom2dProp_Curve& theProp, - Geom2dLProp_CLProps2d& theOld, - const double theParam) -{ - theOld.SetParameter(theParam); - const Geom2dProp::CurvatureResult aNew = theProp.Curvature(theParam, THE_LIN_TOL); - const double aOldCurv = theOld.Curvature(); - if (aNew.IsDefined && !aNew.IsInfinite) - { - EXPECT_NEAR(aNew.Value, aOldCurv, THE_CURV_TOL); - } -} - -void compareNormal(Geom2dProp_Curve& theProp, Geom2dLProp_CLProps2d& theOld, const double theParam) -{ - theOld.SetParameter(theParam); - const Geom2dProp::NormalResult aNew = theProp.Normal(theParam, THE_LIN_TOL); - const double aOldCurv = theOld.Curvature(); - if (std::abs(aOldCurv) < THE_LIN_TOL) - { - return; - } - if (aNew.IsDefined) - { - gp_Dir2d anOldNorm; - theOld.Normal(anOldNorm); - const double aDot = aNew.Direction.X() * anOldNorm.X() + aNew.Direction.Y() * anOldNorm.Y(); - EXPECT_NEAR(std::abs(aDot), 1.0, THE_DIR_TOL); - } -} - -void compareCentre(Geom2dProp_Curve& theProp, Geom2dLProp_CLProps2d& theOld, const double theParam) -{ - theOld.SetParameter(theParam); - const Geom2dProp::CentreResult aNew = theProp.CentreOfCurvature(theParam, THE_LIN_TOL); - const double aOldCurv = theOld.Curvature(); - if (std::abs(aOldCurv) < THE_LIN_TOL) - { - return; - } - if (aNew.IsDefined) - { - gp_Pnt2d anOldCentre; - theOld.CentreOfCurvature(anOldCentre); - EXPECT_NEAR(aNew.Centre.X(), anOldCentre.X(), THE_POINT_TOL); - EXPECT_NEAR(aNew.Centre.Y(), anOldCentre.Y(), THE_POINT_TOL); - } -} - -void compareAll(Geom2dProp_Curve& theProp, - Geom2dLProp_CLProps2d& theOld, - const double theFirst, - const double theLast, - const int theNbSamples = 10) -{ - const double aStep = (theLast - theFirst) / theNbSamples; - for (int i = 0; i <= theNbSamples; ++i) - { - const double aParam = theFirst + i * aStep; - compareTangent(theProp, theOld, aParam); - compareCurvature(theProp, theOld, aParam); - compareNormal(theProp, theOld, aParam); - compareCentre(theProp, theOld, aParam); - } -} - -Geom2dProp::CIType mapLPropType(const LProp_CIType theType) -{ - switch (theType) - { - case LProp_Inflection: - return Geom2dProp::CIType::Inflection; - case LProp_MinCur: - return Geom2dProp::CIType::MinCurvature; - case LProp_MaxCur: - return Geom2dProp::CIType::MaxCurvature; - } - return Geom2dProp::CIType::Inflection; -} - -void compareExtrema(const Geom2dProp::CurveAnalysis& theNew, - const Geom2dLProp_CurAndInf2d& theOld, - const double theTol = 1.0e-4) -{ - EXPECT_EQ(theNew.Points.Length(), theOld.NbPoints()); - const int aNb = std::min(theNew.Points.Length(), theOld.NbPoints()); - for (int i = 0; i < aNb; ++i) - { - EXPECT_NEAR(theNew.Points.Value(i).Parameter, theOld.Parameter(i + 1), theTol) - << "Parameter mismatch at index " << i; - EXPECT_EQ(theNew.Points.Value(i).Type, mapLPropType(theOld.Type(i + 1))) - << "Type mismatch at index " << i; - } -} - -} // namespace - -TEST(Geom2dProp_HyperbolaTest, Curvature_AtVertex) -{ - // For hyperbola with semi-axes a (real) and b (imaginary), - // curvature at vertex (t=0) is k = a / b^2. - const double anA = 6.0; - const double aB = 3.0; - gp_Hypr2d anHypr(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), anA, aB); - occ::handle aHyperbola = new Geom2d_Hyperbola(anHypr); - - Geom2dProp_Curve aProp(aHyperbola); - const Geom2dProp::CurvatureResult aCurv = aProp.Curvature(0.0, THE_LIN_TOL); - - ASSERT_TRUE(aCurv.IsDefined); - ASSERT_FALSE(aCurv.IsInfinite); - const double anExpected = anA / (aB * aB); - EXPECT_NEAR(aCurv.Value, anExpected, THE_CURV_TOL); -} - -TEST(Geom2dProp_HyperbolaTest, Curvature_Symmetric) -{ - // k(t) = k(-t) for a centered hyperbola. - const double anA = 5.0; - const double aB = 2.0; - gp_Hypr2d anHypr(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), anA, aB); - occ::handle aHyperbola = new Geom2d_Hyperbola(anHypr); - - Geom2dProp_Curve aProp(aHyperbola); - for (double t = 0.1; t <= 2.0; t += 0.3) - { - const Geom2dProp::CurvatureResult aCurvPos = aProp.Curvature(t, THE_LIN_TOL); - const Geom2dProp::CurvatureResult aCurvNeg = aProp.Curvature(-t, THE_LIN_TOL); - ASSERT_TRUE(aCurvPos.IsDefined); - ASSERT_TRUE(aCurvNeg.IsDefined); - EXPECT_NEAR(aCurvPos.Value, aCurvNeg.Value, THE_CURV_TOL) << "Asymmetry at t=" << t; - } -} - -TEST(Geom2dProp_HyperbolaTest, Curvature_DecreasesFromVertex) -{ - // Curvature magnitude decreases as |t| increases from vertex. - const double anA = 8.0; - const double aB = 4.0; - gp_Hypr2d anHypr(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), anA, aB); - occ::handle aHyperbola = new Geom2d_Hyperbola(anHypr); - - Geom2dProp_Curve aProp(aHyperbola); - double aPrevCurv = 1.0e30; - for (double t = 0.0; t <= 3.0; t += 0.5) - { - const Geom2dProp::CurvatureResult aCurv = aProp.Curvature(t, THE_LIN_TOL); - ASSERT_TRUE(aCurv.IsDefined); - const double anAbsCurv = std::abs(aCurv.Value); - EXPECT_LE(anAbsCurv, aPrevCurv + THE_CURV_TOL) << "Curvature not decreasing at t=" << t; - aPrevCurv = anAbsCurv; - } -} - -TEST(Geom2dProp_HyperbolaTest, Tangent_AtVertex) -{ - // At vertex (t=0), tangent is perpendicular to the real axis. - gp_Hypr2d anHypr(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 6.0, 3.0); - occ::handle aHyperbola = new Geom2d_Hyperbola(anHypr); - - Geom2dProp_Curve aProp(aHyperbola); - const Geom2dProp::TangentResult aTan = aProp.Tangent(0.0, THE_LIN_TOL); - - ASSERT_TRUE(aTan.IsDefined); - // Tangent at vertex should be along Y axis (perpendicular to real axis X). - const double aDotX = aTan.Direction.X() * 1.0 + aTan.Direction.Y() * 0.0; - EXPECT_NEAR(std::abs(aDotX), 0.0, THE_DIR_TOL); -} - -TEST(Geom2dProp_HyperbolaTest, Tangent_Symmetric) -{ - // Tangent at t and -t: X-components equal, Y-components opposite (or vice versa). - gp_Hypr2d anHypr(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 5.0, 3.0); - occ::handle aHyperbola = new Geom2d_Hyperbola(anHypr); - - Geom2dProp_Curve aProp(aHyperbola); - for (double t = 0.2; t <= 2.0; t += 0.4) - { - const Geom2dProp::TangentResult aTanPos = aProp.Tangent(t, THE_LIN_TOL); - const Geom2dProp::TangentResult aTanNeg = aProp.Tangent(-t, THE_LIN_TOL); - ASSERT_TRUE(aTanPos.IsDefined); - ASSERT_TRUE(aTanNeg.IsDefined); - // For hyperbola (a*cosh(t), b*sinh(t)), derivative is (a*sinh(t), b*cosh(t)). - // At -t: (-a*sinh(t), b*cosh(t)), so X-components are opposite, Y-components are equal. - EXPECT_NEAR(aTanPos.Direction.X(), -aTanNeg.Direction.X(), THE_DIR_TOL); - EXPECT_NEAR(aTanPos.Direction.Y(), aTanNeg.Direction.Y(), THE_DIR_TOL); - } -} - -TEST(Geom2dProp_HyperbolaTest, Normal_AtVertex) -{ - // At vertex, normal should be along real axis toward center. - gp_Hypr2d anHypr(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 6.0, 3.0); - occ::handle aHyperbola = new Geom2d_Hyperbola(anHypr); - - Geom2dProp_Curve aProp(aHyperbola); - const Geom2dProp::NormalResult aNorm = aProp.Normal(0.0, THE_LIN_TOL); - - ASSERT_TRUE(aNorm.IsDefined); - // Normal at vertex should be along X axis (toward center at origin). - const double aDotX = aNorm.Direction.X() * 1.0 + aNorm.Direction.Y() * 0.0; - EXPECT_NEAR(std::abs(aDotX), 1.0, THE_DIR_TOL); -} - -TEST(Geom2dProp_HyperbolaTest, Centre_AtVertex) -{ - // Centre of curvature at vertex is at distance 1/k = b^2/a from vertex along axis. - const double anA = 6.0; - const double aB = 3.0; - gp_Hypr2d anHypr(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), anA, aB); - occ::handle aHyperbola = new Geom2d_Hyperbola(anHypr); - - Geom2dProp_Curve aProp(aHyperbola); - const Geom2dProp::CentreResult aCentre = aProp.CentreOfCurvature(0.0, THE_LIN_TOL); - - ASSERT_TRUE(aCentre.IsDefined); - // Vertex is at (a, 0). Radius of curvature = b^2/a. - // The centre of curvature is on the convex side (away from hyperbola center), - // so centre is at (a + b^2/a, 0) = ((a^2 + b^2)/a, 0). - const double anExpectedX = (anA * anA + aB * aB) / anA; - EXPECT_NEAR(aCentre.Centre.X(), anExpectedX, THE_POINT_TOL); - EXPECT_NEAR(aCentre.Centre.Y(), 0.0, THE_POINT_TOL); -} - -TEST(Geom2dProp_HyperbolaTest, FindCurvatureExtrema_OnePoint) -{ - // Hyperbola has exactly one curvature extremum at vertex (t=0). - gp_Hypr2d anHypr(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 6.0, 3.0); - occ::handle aHyperbola = new Geom2d_Hyperbola(anHypr); - - Geom2dProp_Curve aProp(aHyperbola); - const Geom2dProp::CurveAnalysis aExtrema = aProp.FindCurvatureExtrema(); - - ASSERT_TRUE(aExtrema.IsDone); - EXPECT_EQ(aExtrema.Points.Length(), 1); - if (aExtrema.Points.Length() == 1) - { - EXPECT_NEAR(aExtrema.Points.Value(0).Parameter, 0.0, 1.0e-6); - } -} - -TEST(Geom2dProp_HyperbolaTest, FindInflections_Empty) -{ - // Hyperbola has no inflection points. - gp_Hypr2d anHypr(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 6.0, 3.0); - occ::handle aHyperbola = new Geom2d_Hyperbola(anHypr); - - Geom2dProp_Curve aProp(aHyperbola); - const Geom2dProp::CurveAnalysis aInflections = aProp.FindInflections(); - - ASSERT_TRUE(aInflections.IsDone); - EXPECT_EQ(aInflections.Points.Length(), 0); -} - -TEST(Geom2dProp_HyperbolaTest, GetType_IsHyperbola) -{ - gp_Hypr2d anHypr(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 6.0, 3.0); - occ::handle aHyperbola = new Geom2d_Hyperbola(anHypr); - - Geom2dProp_Curve aProp(aHyperbola); - EXPECT_EQ(aProp.GetType(), GeomAbs_Hyperbola); -} - -TEST(Geom2dProp_HyperbolaTest, Curvature_LargeParam) -{ - // Curvature approaches 0 for large |t|. - gp_Hypr2d anHypr(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 6.0, 3.0); - occ::handle aHyperbola = new Geom2d_Hyperbola(anHypr); - - Geom2dProp_Curve aProp(aHyperbola); - const Geom2dProp::CurvatureResult aCurv = aProp.Curvature(10.0, THE_LIN_TOL); - - ASSERT_TRUE(aCurv.IsDefined); - EXPECT_LT(std::abs(aCurv.Value), 0.01); -} - -TEST(Geom2dProp_HyperbolaTest, VsCLProps2d_Standard) -{ - // Cross-validate against deprecated CLProps2d with a=6, b=3. - gp_Hypr2d anHypr(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 6.0, 3.0); - occ::handle aHyperbola = new Geom2d_Hyperbola(anHypr); - - Geom2dProp_Curve aProp(aHyperbola); - Geom2dLProp_CLProps2d aOld(aHyperbola, 2, THE_LIN_TOL); - - compareAll(aProp, aOld, -2.0, 2.0, 10); -} - -TEST(Geom2dProp_HyperbolaTest, VsCLProps2d_AllProperties) -{ - // Dense comparison over [-2, 2]. - gp_Hypr2d anHypr(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 6.0, 3.0); - occ::handle aHyperbola = new Geom2d_Hyperbola(anHypr); - - Geom2dProp_Curve aProp(aHyperbola); - Geom2dLProp_CLProps2d aOld(aHyperbola, 2, THE_LIN_TOL); - - compareAll(aProp, aOld, -2.0, 2.0, 40); -} - -TEST(Geom2dProp_HyperbolaTest, VsCLProps2d_LargeAxes) -{ - // Cross-validate with a=100, b=50. - gp_Hypr2d anHypr(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 100.0, 50.0); - occ::handle aHyperbola = new Geom2d_Hyperbola(anHypr); - - Geom2dProp_Curve aProp(aHyperbola); - Geom2dLProp_CLProps2d aOld(aHyperbola, 2, THE_LIN_TOL); - - compareAll(aProp, aOld, -2.0, 2.0, 10); -} - -TEST(Geom2dProp_HyperbolaTest, VsCLProps2d_SmallAxes) -{ - // Cross-validate with a=0.5, b=0.3. - gp_Hypr2d anHypr(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 0.5, 0.3); - occ::handle aHyperbola = new Geom2d_Hyperbola(anHypr); - - Geom2dProp_Curve aProp(aHyperbola); - Geom2dLProp_CLProps2d aOld(aHyperbola, 2, THE_LIN_TOL); - - compareAll(aProp, aOld, -2.0, 2.0, 10); -} - -TEST(Geom2dProp_HyperbolaTest, VsCLProps2d_AsymmetricAxes) -{ - // Cross-validate with a=10, b=1. - gp_Hypr2d anHypr(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 10.0, 1.0); - occ::handle aHyperbola = new Geom2d_Hyperbola(anHypr); - - Geom2dProp_Curve aProp(aHyperbola); - Geom2dLProp_CLProps2d aOld(aHyperbola, 2, THE_LIN_TOL); - - compareAll(aProp, aOld, -2.0, 2.0, 10); -} - -TEST(Geom2dProp_HyperbolaTest, Curvature_NearVertex) -{ - // Fine-grained curvature check near vertex. - const double anA = 6.0; - const double aB = 3.0; - gp_Hypr2d anHypr(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), anA, aB); - occ::handle aHyperbola = new Geom2d_Hyperbola(anHypr); - - Geom2dProp_Curve aProp(aHyperbola); - const double anExpectedMax = anA / (aB * aB); - - for (double t = -0.5; t <= 0.5; t += 0.05) - { - const Geom2dProp::CurvatureResult aCurv = aProp.Curvature(t, THE_LIN_TOL); - ASSERT_TRUE(aCurv.IsDefined); - EXPECT_LE(std::abs(aCurv.Value), anExpectedMax + THE_CURV_TOL) - << "Curvature exceeds vertex maximum at t=" << t; - } -} - -TEST(Geom2dProp_HyperbolaTest, VsCLProps2d_OffCenter) -{ - // Cross-validate hyperbola centered at (5,5). - gp_Hypr2d anHypr(gp_Ax2d(gp_Pnt2d(5.0, 5.0), gp_Dir2d(1.0, 0.0)), 6.0, 3.0); - occ::handle aHyperbola = new Geom2d_Hyperbola(anHypr); - - Geom2dProp_Curve aProp(aHyperbola); - Geom2dLProp_CLProps2d aOld(aHyperbola, 2, THE_LIN_TOL); - - compareAll(aProp, aOld, -2.0, 2.0, 10); -} - -TEST(Geom2dProp_HyperbolaTest, VsCurAndInf2d_Extrema) -{ - // Compare curvature extrema with deprecated CurAndInf2d. - gp_Hypr2d anHypr(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 6.0, 3.0); - occ::handle aHyperbola = new Geom2d_Hyperbola(anHypr); - - Geom2dLProp_CurAndInf2d anOld; - anOld.PerformCurExt(aHyperbola); - ASSERT_TRUE(anOld.IsDone()); - - Geom2dProp_Curve aProp(aHyperbola); - const Geom2dProp::CurveAnalysis aNew = aProp.FindCurvatureExtrema(); - ASSERT_TRUE(aNew.IsDone); - - compareExtrema(aNew, anOld, 1.0e-6); -} - -TEST(Geom2dProp_HyperbolaTest, VsCurAndInf2d_NoInflections) -{ - // Compare inflection results with deprecated CurAndInf2d. - gp_Hypr2d anHypr(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 6.0, 3.0); - occ::handle aHyperbola = new Geom2d_Hyperbola(anHypr); - - Geom2dLProp_CurAndInf2d anOld; - anOld.PerformInf(aHyperbola); - ASSERT_TRUE(anOld.IsDone()); - EXPECT_EQ(anOld.NbPoints(), 0); - - Geom2dProp_Curve aProp(aHyperbola); - const Geom2dProp::CurveAnalysis aNew = aProp.FindInflections(); - ASSERT_TRUE(aNew.IsDone); - EXPECT_EQ(aNew.Points.Length(), 0); -} - -TEST(Geom2dProp_HyperbolaTest, VsCLProps2d_CriticalPoints) -{ - gp_Hypr2d aHypr(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 5.0, 3.0); - occ::handle aHyperbola = new Geom2d_Hyperbola(aHypr); - Geom2dProp_Curve aProp(aHyperbola); - Geom2dLProp_CLProps2d aOld(aHyperbola, 2, THE_LIN_TOL); - const double aParams[] = {0.0, - 1.0e-10, - -1.0e-10, - 1.0e-6, - -1.0e-6, - 0.1, - -0.1, - 0.5, - -0.5, - 1.0, - -1.0, - 3.0, - -3.0, - 5.0, - -5.0}; - for (const double aParam : aParams) - { - compareTangent(aProp, aOld, aParam); - compareCurvature(aProp, aOld, aParam); - compareNormal(aProp, aOld, aParam); - compareCentre(aProp, aOld, aParam); - } -} diff --git a/src/ModelingData/TKG2d/GTests/Geom2dProp_Line_Test.cxx b/src/ModelingData/TKG2d/GTests/Geom2dProp_Line_Test.cxx deleted file mode 100644 index 59e90dd308..0000000000 --- a/src/ModelingData/TKG2d/GTests/Geom2dProp_Line_Test.cxx +++ /dev/null @@ -1,400 +0,0 @@ -// 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. - -// Tests for Geom2dProp_Curve local differential properties on 2D lines. -// Lines have zero curvature, constant tangent, and no normal or centre of curvature. - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -namespace -{ -constexpr double THE_LIN_TOL = Precision::PConfusion(); -constexpr double THE_CURV_TOL = 1.0e-8; -constexpr double THE_DIR_TOL = 1.0e-6; -constexpr double THE_POINT_TOL = 1.0e-6; - -void compareTangent(Geom2dProp_Curve& theProp, Geom2dLProp_CLProps2d& theOld, const double theParam) -{ - theOld.SetParameter(theParam); - const Geom2dProp::TangentResult aNew = theProp.Tangent(theParam, THE_LIN_TOL); - if (theOld.IsTangentDefined()) - { - ASSERT_TRUE(aNew.IsDefined); - gp_Dir2d anOldDir; - theOld.Tangent(anOldDir); - const double aDot = aNew.Direction.X() * anOldDir.X() + aNew.Direction.Y() * anOldDir.Y(); - EXPECT_NEAR(std::abs(aDot), 1.0, THE_DIR_TOL); - } -} - -void compareCurvature(Geom2dProp_Curve& theProp, - Geom2dLProp_CLProps2d& theOld, - const double theParam) -{ - theOld.SetParameter(theParam); - const Geom2dProp::CurvatureResult aNew = theProp.Curvature(theParam, THE_LIN_TOL); - const double aOldCurv = theOld.Curvature(); - if (aNew.IsDefined && !aNew.IsInfinite) - { - EXPECT_NEAR(aNew.Value, aOldCurv, THE_CURV_TOL); - } -} - -void compareNormal(Geom2dProp_Curve& theProp, Geom2dLProp_CLProps2d& theOld, const double theParam) -{ - theOld.SetParameter(theParam); - const Geom2dProp::NormalResult aNew = theProp.Normal(theParam, THE_LIN_TOL); - const double aOldCurv = theOld.Curvature(); - if (std::abs(aOldCurv) < THE_LIN_TOL) - { - return; - } - if (aNew.IsDefined) - { - gp_Dir2d anOldNorm; - theOld.Normal(anOldNorm); - const double aDot = aNew.Direction.X() * anOldNorm.X() + aNew.Direction.Y() * anOldNorm.Y(); - EXPECT_NEAR(std::abs(aDot), 1.0, THE_DIR_TOL); - } -} - -void compareCentre(Geom2dProp_Curve& theProp, Geom2dLProp_CLProps2d& theOld, const double theParam) -{ - theOld.SetParameter(theParam); - const Geom2dProp::CentreResult aNew = theProp.CentreOfCurvature(theParam, THE_LIN_TOL); - const double aOldCurv = theOld.Curvature(); - if (std::abs(aOldCurv) < THE_LIN_TOL) - { - return; - } - if (aNew.IsDefined) - { - gp_Pnt2d anOldCentre; - theOld.CentreOfCurvature(anOldCentre); - EXPECT_NEAR(aNew.Centre.X(), anOldCentre.X(), THE_POINT_TOL); - EXPECT_NEAR(aNew.Centre.Y(), anOldCentre.Y(), THE_POINT_TOL); - } -} - -void compareAll(Geom2dProp_Curve& theProp, - Geom2dLProp_CLProps2d& theOld, - const double theFirst, - const double theLast, - const int theNbSamples = 10) -{ - const double aStep = (theLast - theFirst) / theNbSamples; - for (int i = 0; i <= theNbSamples; ++i) - { - const double aParam = theFirst + i * aStep; - compareTangent(theProp, theOld, aParam); - compareCurvature(theProp, theOld, aParam); - compareNormal(theProp, theOld, aParam); - compareCentre(theProp, theOld, aParam); - } -} -} // namespace - -// Test 1: Tangent along X axis -TEST(Geom2dProp_LineTest, Tangent_AlongX) -{ - gp_Lin2d aLin(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)); - occ::handle aLine = new Geom2d_Line(aLin); - Geom2dProp_Curve aProp(aLine); - - const Geom2dProp::TangentResult aTan = aProp.Tangent(0.0, THE_LIN_TOL); - ASSERT_TRUE(aTan.IsDefined); - EXPECT_NEAR(aTan.Direction.X(), 1.0, THE_DIR_TOL); - EXPECT_NEAR(aTan.Direction.Y(), 0.0, THE_DIR_TOL); -} - -// Test 2: Tangent along diagonal (1,1) -TEST(Geom2dProp_LineTest, Tangent_AlongDiagonal) -{ - gp_Lin2d aLin(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 1.0)); - occ::handle aLine = new Geom2d_Line(aLin); - Geom2dProp_Curve aProp(aLine); - - const Geom2dProp::TangentResult aTan = aProp.Tangent(5.0, THE_LIN_TOL); - ASSERT_TRUE(aTan.IsDefined); - const double aSqrt2Inv = 1.0 / std::sqrt(2.0); - EXPECT_NEAR(aTan.Direction.X(), aSqrt2Inv, THE_DIR_TOL); - EXPECT_NEAR(aTan.Direction.Y(), aSqrt2Inv, THE_DIR_TOL); -} - -// Test 3: Tangent at negative parameter - same as positive -TEST(Geom2dProp_LineTest, Tangent_NegativeParam) -{ - gp_Lin2d aLin(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)); - occ::handle aLine = new Geom2d_Line(aLin); - Geom2dProp_Curve aProp(aLine); - - const Geom2dProp::TangentResult aTanNeg = aProp.Tangent(-10.0, THE_LIN_TOL); - const Geom2dProp::TangentResult aTanPos = aProp.Tangent(10.0, THE_LIN_TOL); - ASSERT_TRUE(aTanNeg.IsDefined); - ASSERT_TRUE(aTanPos.IsDefined); - EXPECT_NEAR(aTanNeg.Direction.X(), aTanPos.Direction.X(), THE_DIR_TOL); - EXPECT_NEAR(aTanNeg.Direction.Y(), aTanPos.Direction.Y(), THE_DIR_TOL); -} - -// Test 4: Tangent at origin (param=0) -TEST(Geom2dProp_LineTest, Tangent_AtOrigin) -{ - gp_Lin2d aLin(gp_Pnt2d(5.0, 5.0), gp_Dir2d(0.0, 1.0)); - occ::handle aLine = new Geom2d_Line(aLin); - Geom2dProp_Curve aProp(aLine); - - const Geom2dProp::TangentResult aTan = aProp.Tangent(0.0, THE_LIN_TOL); - ASSERT_TRUE(aTan.IsDefined); - EXPECT_NEAR(aTan.Direction.X(), 0.0, THE_DIR_TOL); - EXPECT_NEAR(aTan.Direction.Y(), 1.0, THE_DIR_TOL); -} - -// Test 5: Curvature is zero -TEST(Geom2dProp_LineTest, Curvature_IsZero) -{ - gp_Lin2d aLin(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)); - occ::handle aLine = new Geom2d_Line(aLin); - Geom2dProp_Curve aProp(aLine); - - const Geom2dProp::CurvatureResult aCurv = aProp.Curvature(0.0, THE_LIN_TOL); - ASSERT_TRUE(aCurv.IsDefined); - EXPECT_NEAR(aCurv.Value, 0.0, THE_CURV_TOL); -} - -// Test 6: Curvature is zero at multiple params -TEST(Geom2dProp_LineTest, Curvature_MultipleParams) -{ - gp_Lin2d aLin(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 1.0)); - occ::handle aLine = new Geom2d_Line(aLin); - Geom2dProp_Curve aProp(aLine); - - for (double u = -50.0; u <= 50.0; u += 10.0) - { - const Geom2dProp::CurvatureResult aCurv = aProp.Curvature(u, THE_LIN_TOL); - ASSERT_TRUE(aCurv.IsDefined) << "at u=" << u; - EXPECT_NEAR(aCurv.Value, 0.0, THE_CURV_TOL) << "at u=" << u; - } -} - -// Test 7: Normal is undefined for a line -TEST(Geom2dProp_LineTest, Normal_Undefined) -{ - gp_Lin2d aLin(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)); - occ::handle aLine = new Geom2d_Line(aLin); - Geom2dProp_Curve aProp(aLine); - - const Geom2dProp::NormalResult aNorm = aProp.Normal(0.0, THE_LIN_TOL); - EXPECT_FALSE(aNorm.IsDefined); -} - -// Test 8: Centre of curvature is undefined for a line -TEST(Geom2dProp_LineTest, Centre_Undefined) -{ - gp_Lin2d aLin(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)); - occ::handle aLine = new Geom2d_Line(aLin); - Geom2dProp_Curve aProp(aLine); - - const Geom2dProp::CentreResult aCentre = aProp.CentreOfCurvature(0.0, THE_LIN_TOL); - EXPECT_FALSE(aCentre.IsDefined); -} - -// Test 9: FindCurvatureExtrema returns empty -TEST(Geom2dProp_LineTest, FindCurvatureExtrema_Empty) -{ - gp_Lin2d aLin(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)); - occ::handle aLine = new Geom2d_Line(aLin); - Geom2dProp_Curve aProp(aLine); - - const Geom2dProp::CurveAnalysis aAnalysis = aProp.FindCurvatureExtrema(); - ASSERT_TRUE(aAnalysis.IsDone); - EXPECT_EQ(aAnalysis.Points.Length(), 0); -} - -// Test 10: FindInflections returns empty -TEST(Geom2dProp_LineTest, FindInflections_Empty) -{ - gp_Lin2d aLin(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)); - occ::handle aLine = new Geom2d_Line(aLin); - Geom2dProp_Curve aProp(aLine); - - const Geom2dProp::CurveAnalysis aAnalysis = aProp.FindInflections(); - ASSERT_TRUE(aAnalysis.IsDone); - EXPECT_EQ(aAnalysis.Points.Length(), 0); -} - -// Test 11: GetType returns GeomAbs_Line -TEST(Geom2dProp_LineTest, GetType_IsLine) -{ - gp_Lin2d aLin(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)); - occ::handle aLine = new Geom2d_Line(aLin); - Geom2dProp_Curve aProp(aLine); - - EXPECT_EQ(aProp.GetType(), GeomAbs_Line); -} - -// Test 12: Tangent comparison vs CLProps2d at 11 params -TEST(Geom2dProp_LineTest, VsCLProps2d_Tangent) -{ - gp_Lin2d aLin(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)); - occ::handle aLine = new Geom2d_Line(aLin); - - Geom2dProp_Curve aProp(aLine); - Geom2dLProp_CLProps2d aOld(aLine, 2, THE_LIN_TOL); - - for (double u = -5.0; u <= 5.0; u += 1.0) - { - compareTangent(aProp, aOld, u); - } -} - -// Test 13: Curvature comparison vs CLProps2d at 11 params -TEST(Geom2dProp_LineTest, VsCLProps2d_Curvature) -{ - gp_Lin2d aLin(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)); - occ::handle aLine = new Geom2d_Line(aLin); - - Geom2dProp_Curve aProp(aLine); - Geom2dLProp_CLProps2d aOld(aLine, 2, THE_LIN_TOL); - - for (double u = -5.0; u <= 5.0; u += 1.0) - { - compareCurvature(aProp, aOld, u); - } -} - -// Test 14: All properties comparison vs CLProps2d (dense) -TEST(Geom2dProp_LineTest, VsCLProps2d_AllProperties) -{ - gp_Lin2d aLin(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)); - occ::handle aLine = new Geom2d_Line(aLin); - - Geom2dProp_Curve aProp(aLine); - Geom2dLProp_CLProps2d aOld(aLine, 2, THE_LIN_TOL); - - compareAll(aProp, aOld, -10.0, 10.0, 20); -} - -// Test 15: Line not at origin -TEST(Geom2dProp_LineTest, Line_OffCenter) -{ - gp_Lin2d aLin(gp_Pnt2d(10.0, 20.0), gp_Dir2d(1.0, 0.0)); - occ::handle aLine = new Geom2d_Line(aLin); - Geom2dProp_Curve aProp(aLine); - - const Geom2dProp::TangentResult aTan = aProp.Tangent(0.0, THE_LIN_TOL); - ASSERT_TRUE(aTan.IsDefined); - EXPECT_NEAR(aTan.Direction.X(), 1.0, THE_DIR_TOL); - EXPECT_NEAR(aTan.Direction.Y(), 0.0, THE_DIR_TOL); - - const Geom2dProp::CurvatureResult aCurv = aProp.Curvature(5.0, THE_LIN_TOL); - ASSERT_TRUE(aCurv.IsDefined); - EXPECT_NEAR(aCurv.Value, 0.0, THE_CURV_TOL); -} - -// Test 16: Line with arbitrary direction (3,4) -TEST(Geom2dProp_LineTest, Line_ArbitraryDirection) -{ - gp_Lin2d aLin(gp_Pnt2d(0.0, 0.0), gp_Dir2d(3.0, 4.0)); - occ::handle aLine = new Geom2d_Line(aLin); - Geom2dProp_Curve aProp(aLine); - - const Geom2dProp::TangentResult aTan = aProp.Tangent(0.0, THE_LIN_TOL); - ASSERT_TRUE(aTan.IsDefined); - EXPECT_NEAR(aTan.Direction.X(), 3.0 / 5.0, THE_DIR_TOL); - EXPECT_NEAR(aTan.Direction.Y(), 4.0 / 5.0, THE_DIR_TOL); -} - -// Test 17: Line at large parameters -TEST(Geom2dProp_LineTest, Line_LargeParams) -{ - gp_Lin2d aLin(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)); - occ::handle aLine = new Geom2d_Line(aLin); - Geom2dProp_Curve aProp(aLine); - - const Geom2dProp::TangentResult aTan = aProp.Tangent(1000.0, THE_LIN_TOL); - ASSERT_TRUE(aTan.IsDefined); - EXPECT_NEAR(aTan.Direction.X(), 1.0, THE_DIR_TOL); - EXPECT_NEAR(aTan.Direction.Y(), 0.0, THE_DIR_TOL); - - const Geom2dProp::CurvatureResult aCurv = aProp.Curvature(1000.0, THE_LIN_TOL); - ASSERT_TRUE(aCurv.IsDefined); - EXPECT_NEAR(aCurv.Value, 0.0, THE_CURV_TOL); -} - -// Test 18: Tangent sign is consistent with line direction -TEST(Geom2dProp_LineTest, Tangent_ConsistentSign) -{ - gp_Dir2d aDir(3.0, 4.0); - gp_Lin2d aLin(gp_Pnt2d(0.0, 0.0), aDir); - occ::handle aLine = new Geom2d_Line(aLin); - Geom2dProp_Curve aProp(aLine); - - for (double u = -10.0; u <= 10.0; u += 2.0) - { - const Geom2dProp::TangentResult aTan = aProp.Tangent(u, THE_LIN_TOL); - ASSERT_TRUE(aTan.IsDefined); - const double aDot = aTan.Direction.X() * aDir.X() + aTan.Direction.Y() * aDir.Y(); - EXPECT_NEAR(std::abs(aDot), 1.0, THE_DIR_TOL) << "at u=" << u; - } -} - -// Test 19: Curvature is exactly zero (not just near-zero) -TEST(Geom2dProp_LineTest, Curvature_ExactlyZero) -{ - gp_Lin2d aLin(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)); - occ::handle aLine = new Geom2d_Line(aLin); - Geom2dProp_Curve aProp(aLine); - - const Geom2dProp::CurvatureResult aCurv = aProp.Curvature(0.0, THE_LIN_TOL); - ASSERT_TRUE(aCurv.IsDefined); - EXPECT_EQ(aCurv.Value, 0.0); -} - -// Test 20: All properties comparison vs CLProps2d for off-center line -TEST(Geom2dProp_LineTest, VsCLProps2d_OffCenter) -{ - gp_Lin2d aLin(gp_Pnt2d(10.0, 20.0), gp_Dir2d(3.0, 4.0)); - occ::handle aLine = new Geom2d_Line(aLin); - - Geom2dProp_Curve aProp(aLine); - Geom2dLProp_CLProps2d aOld(aLine, 2, THE_LIN_TOL); - - compareAll(aProp, aOld, -10.0, 10.0, 20); -} - -TEST(Geom2dProp_LineTest, VsCLProps2d_CriticalPoints) -{ - gp_Lin2d aLin(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 1.0)); - occ::handle aLine = new Geom2d_Line(aLin); - Geom2dProp_Curve aProp(aLine); - Geom2dLProp_CLProps2d aOld(aLine, 2, THE_LIN_TOL); - const double aParams[] = {0.0, 1.0e-10, -1.0e-10, 1.0e-6, -1.0e-6, 1.0e6, -1.0e6, 0.5, -0.5}; - for (const double aParam : aParams) - { - compareTangent(aProp, aOld, aParam); - compareCurvature(aProp, aOld, aParam); - compareNormal(aProp, aOld, aParam); - compareCentre(aProp, aOld, aParam); - } -} diff --git a/src/ModelingData/TKG2d/GTests/Geom2dProp_OffsetCurve_Test.cxx b/src/ModelingData/TKG2d/GTests/Geom2dProp_OffsetCurve_Test.cxx deleted file mode 100644 index f0782799df..0000000000 --- a/src/ModelingData/TKG2d/GTests/Geom2dProp_OffsetCurve_Test.cxx +++ /dev/null @@ -1,525 +0,0 @@ -// 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. - -// Tests for Geom2dProp_Curve with 2D offset curves: local differential -// properties and global curve analysis for offset circles and offset ellipses. - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -namespace -{ -constexpr double THE_LIN_TOL = Precision::PConfusion(); -constexpr double THE_CURV_TOL = 1.0e-8; -constexpr double THE_DIR_TOL = 1.0e-6; -constexpr double THE_POINT_TOL = 1.0e-6; -constexpr double THE_PARAM_TOL = 1.0e-4; - -void compareTangent(Geom2dProp_Curve& theProp, Geom2dLProp_CLProps2d& theOld, const double theParam) -{ - theOld.SetParameter(theParam); - const Geom2dProp::TangentResult aNew = theProp.Tangent(theParam, THE_LIN_TOL); - if (theOld.IsTangentDefined()) - { - ASSERT_TRUE(aNew.IsDefined) << "Tangent undefined at U=" << theParam; - gp_Dir2d anOldDir; - theOld.Tangent(anOldDir); - const double aDot = aNew.Direction.X() * anOldDir.X() + aNew.Direction.Y() * anOldDir.Y(); - EXPECT_NEAR(std::abs(aDot), 1.0, THE_DIR_TOL) << "Tangent mismatch at U=" << theParam; - } -} - -void compareCurvature(Geom2dProp_Curve& theProp, - Geom2dLProp_CLProps2d& theOld, - const double theParam) -{ - theOld.SetParameter(theParam); - const Geom2dProp::CurvatureResult aNew = theProp.Curvature(theParam, THE_LIN_TOL); - const double aOldCurv = theOld.Curvature(); - if (aNew.IsDefined && !aNew.IsInfinite) - { - EXPECT_NEAR(aNew.Value, aOldCurv, THE_CURV_TOL) << "Curvature mismatch at U=" << theParam; - } -} - -void compareNormal(Geom2dProp_Curve& theProp, Geom2dLProp_CLProps2d& theOld, const double theParam) -{ - theOld.SetParameter(theParam); - const Geom2dProp::NormalResult aNew = theProp.Normal(theParam, THE_LIN_TOL); - const double aOldCurv = theOld.Curvature(); - if (std::abs(aOldCurv) < THE_LIN_TOL) - { - return; - } - if (aNew.IsDefined) - { - gp_Dir2d anOldNorm; - theOld.Normal(anOldNorm); - const double aDot = aNew.Direction.X() * anOldNorm.X() + aNew.Direction.Y() * anOldNorm.Y(); - EXPECT_NEAR(std::abs(aDot), 1.0, THE_DIR_TOL) << "Normal mismatch at U=" << theParam; - } -} - -void compareCentre(Geom2dProp_Curve& theProp, Geom2dLProp_CLProps2d& theOld, const double theParam) -{ - theOld.SetParameter(theParam); - const Geom2dProp::CentreResult aNew = theProp.CentreOfCurvature(theParam, THE_LIN_TOL); - const double aOldCurv = theOld.Curvature(); - if (std::abs(aOldCurv) < THE_LIN_TOL) - { - return; - } - if (aNew.IsDefined) - { - gp_Pnt2d anOldCentre; - theOld.CentreOfCurvature(anOldCentre); - EXPECT_NEAR(aNew.Centre.X(), anOldCentre.X(), THE_POINT_TOL) - << "Centre X mismatch at U=" << theParam; - EXPECT_NEAR(aNew.Centre.Y(), anOldCentre.Y(), THE_POINT_TOL) - << "Centre Y mismatch at U=" << theParam; - } -} - -void compareAll(Geom2dProp_Curve& theProp, - Geom2dLProp_CLProps2d& theOld, - const double theFirst, - const double theLast, - const int theNbSamples = 10) -{ - const double aStep = (theLast - theFirst) / theNbSamples; - for (int i = 0; i <= theNbSamples; ++i) - { - const double aParam = theFirst + i * aStep; - compareTangent(theProp, theOld, aParam); - compareCurvature(theProp, theOld, aParam); - compareNormal(theProp, theOld, aParam); - compareCentre(theProp, theOld, aParam); - } -} - -Geom2dProp::CIType mapLPropType(const LProp_CIType theType) -{ - switch (theType) - { - case LProp_Inflection: - return Geom2dProp::CIType::Inflection; - case LProp_MinCur: - return Geom2dProp::CIType::MinCurvature; - case LProp_MaxCur: - return Geom2dProp::CIType::MaxCurvature; - } - return Geom2dProp::CIType::Inflection; -} - -void compareExtrema(const Geom2dProp::CurveAnalysis& theNew, - const Geom2dLProp_CurAndInf2d& theOld, - const double theTol = THE_PARAM_TOL) -{ - EXPECT_EQ(theNew.Points.Length(), theOld.NbPoints()); - const int aNb = std::min(theNew.Points.Length(), theOld.NbPoints()); - for (int i = 0; i < aNb; ++i) - { - EXPECT_NEAR(theNew.Points.Value(i).Parameter, theOld.Parameter(i + 1), theTol) - << "Parameter mismatch at index " << i; - EXPECT_EQ(theNew.Points.Value(i).Type, mapLPropType(theOld.Type(i + 1))) - << "Type mismatch at index " << i; - } -} - -// Helper: create offset circle with given radius and offset distance. -occ::handle makeOffsetCircle(const double theRadius, const double theOffset) -{ - gp_Circ2d aCirc(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), theRadius); - occ::handle aCircle = new Geom2d_Circle(aCirc); - return new Geom2d_OffsetCurve(aCircle, theOffset); -} - -// Helper: create offset ellipse. -occ::handle makeOffsetEllipse(const double theMajor, - const double theMinor, - const double theOffset) -{ - gp_Elips2d anElips(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), theMajor, theMinor); - occ::handle anEllipse = new Geom2d_Ellipse(anElips); - return new Geom2d_OffsetCurve(anEllipse, theOffset); -} - -} // namespace - -// ============================================================================ -// Offset circle: curvature tests -// ============================================================================ - -TEST(Geom2dProp_OffsetCurveTest, Curvature_OffsetCircle_Constant) -{ - const double aRadius = 5.0; - const double anOffset = 2.0; - occ::handle aCurve = makeOffsetCircle(aRadius, anOffset); - Geom2dProp_Curve aProp(aCurve); - - // Offset of circle by d gives circle with radius R+d, curvature = 1/(R+d) - const double aExpectedCurv = 1.0 / (aRadius + anOffset); - - for (double u = 0.0; u < 2.0 * M_PI; u += M_PI / 4.0) - { - const Geom2dProp::CurvatureResult aCurv = aProp.Curvature(u, THE_LIN_TOL); - ASSERT_TRUE(aCurv.IsDefined) << "Curvature undefined at U=" << u; - EXPECT_NEAR(aCurv.Value, aExpectedCurv, THE_CURV_TOL) << "Curvature mismatch at U=" << u; - } -} - -TEST(Geom2dProp_OffsetCurveTest, Curvature_OffsetCircle_Positive) -{ - const double aRadius = 3.0; - const double anOffset = 5.0; - occ::handle aCurve = makeOffsetCircle(aRadius, anOffset); - Geom2dProp_Curve aProp(aCurve); - - const double aExpectedCurv = 1.0 / (aRadius + anOffset); - const Geom2dProp::CurvatureResult aCurv = aProp.Curvature(0.0, THE_LIN_TOL); - ASSERT_TRUE(aCurv.IsDefined); - EXPECT_NEAR(aCurv.Value, aExpectedCurv, THE_CURV_TOL); -} - -TEST(Geom2dProp_OffsetCurveTest, Curvature_OffsetCircle_Negative) -{ - const double aRadius = 10.0; - const double anOffset = -3.0; - occ::handle aCurve = makeOffsetCircle(aRadius, anOffset); - Geom2dProp_Curve aProp(aCurve); - - // Negative offset reduces effective radius - const double aExpectedCurv = 1.0 / (aRadius + anOffset); - const Geom2dProp::CurvatureResult aCurv = aProp.Curvature(M_PI / 3.0, THE_LIN_TOL); - ASSERT_TRUE(aCurv.IsDefined); - EXPECT_NEAR(aCurv.Value, aExpectedCurv, THE_CURV_TOL); -} - -// ============================================================================ -// Offset circle: tangent, normal, centre -// ============================================================================ - -TEST(Geom2dProp_OffsetCurveTest, Tangent_OffsetCircle) -{ - occ::handle aCurve = makeOffsetCircle(5.0, 2.0); - Geom2dProp_Curve aProp(aCurve); - - // At u=0 on a standard circle, tangent is in Y direction - const Geom2dProp::TangentResult aTan = aProp.Tangent(0.0, THE_LIN_TOL); - ASSERT_TRUE(aTan.IsDefined); - // Tangent should be roughly (0, 1) or (0, -1) at u=0 - EXPECT_NEAR(std::abs(aTan.Direction.Y()), 1.0, THE_DIR_TOL); -} - -TEST(Geom2dProp_OffsetCurveTest, Normal_OffsetCircle) -{ - occ::handle aCurve = makeOffsetCircle(5.0, 2.0); - Geom2dProp_Curve aProp(aCurve); - - for (double u = 0.0; u < 2.0 * M_PI; u += M_PI / 4.0) - { - const Geom2dProp::NormalResult aNorm = aProp.Normal(u, THE_LIN_TOL); - ASSERT_TRUE(aNorm.IsDefined) << "Normal undefined at U=" << u; - // Normal should be perpendicular to tangent - const Geom2dProp::TangentResult aTan = aProp.Tangent(u, THE_LIN_TOL); - ASSERT_TRUE(aTan.IsDefined); - const double aDot = - aNorm.Direction.X() * aTan.Direction.X() + aNorm.Direction.Y() * aTan.Direction.Y(); - EXPECT_NEAR(aDot, 0.0, THE_DIR_TOL); - } -} - -TEST(Geom2dProp_OffsetCurveTest, Centre_OffsetCircle) -{ - occ::handle aCurve = makeOffsetCircle(5.0, 2.0); - Geom2dProp_Curve aProp(aCurve); - - // Centre of curvature for offset circle should be the circle center (0,0) - for (double u = 0.0; u < 2.0 * M_PI; u += M_PI / 4.0) - { - const Geom2dProp::CentreResult aCentre = aProp.CentreOfCurvature(u, THE_LIN_TOL); - ASSERT_TRUE(aCentre.IsDefined) << "Centre undefined at U=" << u; - EXPECT_NEAR(aCentre.Centre.X(), 0.0, THE_POINT_TOL); - EXPECT_NEAR(aCentre.Centre.Y(), 0.0, THE_POINT_TOL); - } -} - -// ============================================================================ -// Offset circle: global analysis -// ============================================================================ - -TEST(Geom2dProp_OffsetCurveTest, FindCurvatureExtrema_OffsetCircle) -{ - occ::handle aCurve = makeOffsetCircle(5.0, 2.0); - Geom2dProp_Curve aProp(aCurve); - - const Geom2dProp::CurveAnalysis aResult = aProp.FindCurvatureExtrema(); - ASSERT_TRUE(aResult.IsDone); - // Constant curvature means no extrema - EXPECT_EQ(aResult.Points.Length(), 0); -} - -TEST(Geom2dProp_OffsetCurveTest, FindInflections_OffsetCircle) -{ - occ::handle aCurve = makeOffsetCircle(5.0, 2.0); - Geom2dProp_Curve aProp(aCurve); - - const Geom2dProp::CurveAnalysis aResult = aProp.FindInflections(); - ASSERT_TRUE(aResult.IsDone); - // Circle has no inflections - EXPECT_EQ(aResult.Points.Length(), 0); -} - -// ============================================================================ -// GetType test -// ============================================================================ - -TEST(Geom2dProp_OffsetCurveTest, GetType_IsOffsetCurve) -{ - occ::handle aCurve = makeOffsetCircle(5.0, 2.0); - Geom2dProp_Curve aProp(aCurve); - EXPECT_EQ(aProp.GetType(), GeomAbs_OffsetCurve); -} - -// ============================================================================ -// Cross-validation vs CLProps2d: offset circle -// ============================================================================ - -TEST(Geom2dProp_OffsetCurveTest, VsCLProps2d_OffsetCircle) -{ - occ::handle aCurve = makeOffsetCircle(5.0, 2.0); - Geom2dProp_Curve aProp(aCurve); - Geom2dLProp_CLProps2d aOld(aCurve, 2, THE_LIN_TOL); - - for (double u = 0.0; u < 2.0 * M_PI; u += M_PI / 6.0) - { - compareTangent(aProp, aOld, u); - compareCurvature(aProp, aOld, u); - } -} - -TEST(Geom2dProp_OffsetCurveTest, VsCLProps2d_AllProperties_OffsetCircle) -{ - occ::handle aCurve = makeOffsetCircle(5.0, 2.0); - Geom2dProp_Curve aProp(aCurve); - Geom2dLProp_CLProps2d aOld(aCurve, 2, THE_LIN_TOL); - - compareAll(aProp, aOld, 0.0, 2.0 * M_PI - 0.01, 20); -} - -// ============================================================================ -// Offset ellipse tests -// ============================================================================ - -TEST(Geom2dProp_OffsetCurveTest, Curvature_OffsetEllipse) -{ - occ::handle aCurve = makeOffsetEllipse(10.0, 5.0, 1.0); - Geom2dProp_Curve aProp(aCurve); - - // Curvature should vary along the ellipse offset - const Geom2dProp::CurvatureResult aCurv0 = aProp.Curvature(0.0, THE_LIN_TOL); - const Geom2dProp::CurvatureResult aCurvPi = aProp.Curvature(M_PI / 2.0, THE_LIN_TOL); - ASSERT_TRUE(aCurv0.IsDefined); - ASSERT_TRUE(aCurvPi.IsDefined); - EXPECT_NE(aCurv0.Value, aCurvPi.Value); -} - -TEST(Geom2dProp_OffsetCurveTest, FindCurvatureExtrema_OffsetEllipse) -{ - occ::handle aCurve = makeOffsetEllipse(10.0, 5.0, 1.0); - Geom2dProp_Curve aProp(aCurve); - - const Geom2dProp::CurveAnalysis aResult = aProp.FindCurvatureExtrema(); - ASSERT_TRUE(aResult.IsDone); - // Offset ellipse should have curvature extrema - EXPECT_GT(aResult.Points.Length(), 0); -} - -TEST(Geom2dProp_OffsetCurveTest, FindInflections_OffsetEllipse) -{ - occ::handle aCurve = makeOffsetEllipse(10.0, 5.0, 1.0); - Geom2dProp_Curve aProp(aCurve); - - const Geom2dProp::CurveAnalysis aResult = aProp.FindInflections(); - ASSERT_TRUE(aResult.IsDone); - // Offset of ellipse by small offset: no inflections expected - for (int i = 0; i < aResult.Points.Length(); ++i) - { - EXPECT_EQ(aResult.Points.Value(i).Type, Geom2dProp::CIType::Inflection); - } -} - -TEST(Geom2dProp_OffsetCurveTest, Tangent_OffsetEllipse) -{ - occ::handle aCurve = makeOffsetEllipse(10.0, 5.0, 1.0); - Geom2dProp_Curve aProp(aCurve); - - for (double u = 0.0; u < 2.0 * M_PI; u += M_PI / 4.0) - { - const Geom2dProp::TangentResult aTan = aProp.Tangent(u, THE_LIN_TOL); - EXPECT_TRUE(aTan.IsDefined) << "Tangent undefined at U=" << u; - } -} - -TEST(Geom2dProp_OffsetCurveTest, Normal_OffsetEllipse) -{ - occ::handle aCurve = makeOffsetEllipse(10.0, 5.0, 1.0); - Geom2dProp_Curve aProp(aCurve); - - for (double u = 0.0; u < 2.0 * M_PI; u += M_PI / 4.0) - { - const Geom2dProp::NormalResult aNorm = aProp.Normal(u, THE_LIN_TOL); - if (aNorm.IsDefined) - { - const Geom2dProp::TangentResult aTan = aProp.Tangent(u, THE_LIN_TOL); - ASSERT_TRUE(aTan.IsDefined); - const double aDot = - aNorm.Direction.X() * aTan.Direction.X() + aNorm.Direction.Y() * aTan.Direction.Y(); - EXPECT_NEAR(aDot, 0.0, THE_DIR_TOL) << "Normal not perpendicular at U=" << u; - } - } -} - -// ============================================================================ -// Cross-validation vs CLProps2d: offset ellipse -// ============================================================================ - -TEST(Geom2dProp_OffsetCurveTest, VsCLProps2d_OffsetEllipse) -{ - occ::handle aCurve = makeOffsetEllipse(10.0, 5.0, 1.0); - Geom2dProp_Curve aProp(aCurve); - Geom2dLProp_CLProps2d aOld(aCurve, 2, THE_LIN_TOL); - - for (double u = 0.0; u < 2.0 * M_PI; u += M_PI / 6.0) - { - compareTangent(aProp, aOld, u); - compareCurvature(aProp, aOld, u); - } -} - -TEST(Geom2dProp_OffsetCurveTest, VsCLProps2d_AllProperties_OffsetEllipse) -{ - occ::handle aCurve = makeOffsetEllipse(10.0, 5.0, 1.0); - Geom2dProp_Curve aProp(aCurve); - Geom2dLProp_CLProps2d aOld(aCurve, 2, THE_LIN_TOL); - - compareAll(aProp, aOld, 0.0, 2.0 * M_PI - 0.01, 20); -} - -// ============================================================================ -// Cross-validation vs CurAndInf2d -// ============================================================================ - -TEST(Geom2dProp_OffsetCurveTest, VsCurAndInf2d_OffsetEllipse_Extrema) -{ - occ::handle aCurve = makeOffsetEllipse(10.0, 5.0, 1.0); - - Geom2dLProp_CurAndInf2d anOld; - anOld.PerformCurExt(aCurve); - ASSERT_TRUE(anOld.IsDone()); - - Geom2dProp_Curve aProp(aCurve); - const Geom2dProp::CurveAnalysis aNew = aProp.FindCurvatureExtrema(); - ASSERT_TRUE(aNew.IsDone); - - compareExtrema(aNew, anOld); -} - -TEST(Geom2dProp_OffsetCurveTest, VsCurAndInf2d_OffsetCircle_NoExtrema) -{ - occ::handle aCurve = makeOffsetCircle(5.0, 2.0); - - Geom2dLProp_CurAndInf2d anOld; - anOld.PerformCurExt(aCurve); - ASSERT_TRUE(anOld.IsDone()); - - Geom2dProp_Curve aProp(aCurve); - const Geom2dProp::CurveAnalysis aNew = aProp.FindCurvatureExtrema(); - ASSERT_TRUE(aNew.IsDone); - - EXPECT_EQ(aNew.Points.Length(), anOld.NbPoints()); -} - -TEST(Geom2dProp_OffsetCurveTest, VsCLProps2d_CriticalPoints) -{ - occ::handle aCircle = - new Geom2d_Circle(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 5.0); - occ::handle anOffset = new Geom2d_OffsetCurve(aCircle, 2.0); - Geom2dProp_Curve aProp(anOffset); - Geom2dLProp_CLProps2d aOld(anOffset, 2, THE_LIN_TOL); - const double aParams[] = {0.0, - 1.0e-10, - M_PI / 4.0, - M_PI / 2.0, - M_PI / 2.0 + 1.0e-6, - M_PI, - 3.0 * M_PI / 2.0, - 2.0 * M_PI - 1.0e-10, - M_PI / 6.0, - 5.0 * M_PI / 6.0}; - for (const double aParam : aParams) - { - compareTangent(aProp, aOld, aParam); - compareCurvature(aProp, aOld, aParam); - compareNormal(aProp, aOld, aParam); - compareCentre(aProp, aOld, aParam); - } -} - -TEST(Geom2dProp_OffsetCurveTest, RepeatedCalls_SameParameter_AreStable) -{ - occ::handle aCurve = makeOffsetEllipse(10.0, 5.0, 1.0); - Geom2dProp_Curve aProp(aCurve); - Geom2dProp_Curve aFreshProp(aCurve); - const double aParam = M_PI / 3.0; - - const Geom2dProp::TangentResult aTangent = aProp.Tangent(aParam, THE_LIN_TOL); - const Geom2dProp::CurvatureResult aCurv = aProp.Curvature(aParam, THE_LIN_TOL); - const Geom2dProp::NormalResult aNorm = aProp.Normal(aParam, THE_LIN_TOL); - const Geom2dProp::CentreResult aCentre = aProp.CentreOfCurvature(aParam, THE_LIN_TOL); - - const Geom2dProp::CurvatureResult aFreshCurv = aFreshProp.Curvature(aParam, THE_LIN_TOL); - const Geom2dProp::NormalResult aFreshNorm = aFreshProp.Normal(aParam, THE_LIN_TOL); - const Geom2dProp::CentreResult aFreshCentre = aFreshProp.CentreOfCurvature(aParam, THE_LIN_TOL); - - ASSERT_TRUE(aTangent.IsDefined); - ASSERT_TRUE(aCurv.IsDefined); - ASSERT_TRUE(aNorm.IsDefined); - ASSERT_TRUE(aCentre.IsDefined); - ASSERT_TRUE(aFreshCurv.IsDefined); - ASSERT_TRUE(aFreshNorm.IsDefined); - ASSERT_TRUE(aFreshCentre.IsDefined); - - EXPECT_NEAR(aCurv.Value, aFreshCurv.Value, THE_CURV_TOL); - const double aNormDot = - aNorm.Direction.X() * aFreshNorm.Direction.X() + aNorm.Direction.Y() * aFreshNorm.Direction.Y(); - EXPECT_NEAR(std::abs(aNormDot), 1.0, THE_DIR_TOL); - EXPECT_NEAR(aCentre.Centre.X(), aFreshCentre.Centre.X(), THE_POINT_TOL); - EXPECT_NEAR(aCentre.Centre.Y(), aFreshCentre.Centre.Y(), THE_POINT_TOL); -} diff --git a/src/ModelingData/TKG2d/GTests/Geom2dProp_OtherCurve_Test.cxx b/src/ModelingData/TKG2d/GTests/Geom2dProp_OtherCurve_Test.cxx deleted file mode 100644 index 98da77b3c1..0000000000 --- a/src/ModelingData/TKG2d/GTests/Geom2dProp_OtherCurve_Test.cxx +++ /dev/null @@ -1,516 +0,0 @@ -// 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. - -// Tests for Geom2dProp_Curve with trimmed curves and other non-standard 2D -// curve types: local differential properties and global curve analysis. - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -namespace -{ -constexpr double THE_LIN_TOL = Precision::PConfusion(); -constexpr double THE_CURV_TOL = 1.0e-8; -constexpr double THE_DIR_TOL = 1.0e-6; -constexpr double THE_POINT_TOL = 1.0e-6; -constexpr double THE_PARAM_TOL = 1.0e-4; - -void compareTangent(Geom2dProp_Curve& theProp, Geom2dLProp_CLProps2d& theOld, const double theParam) -{ - theOld.SetParameter(theParam); - const Geom2dProp::TangentResult aNew = theProp.Tangent(theParam, THE_LIN_TOL); - if (theOld.IsTangentDefined()) - { - ASSERT_TRUE(aNew.IsDefined) << "Tangent undefined at U=" << theParam; - gp_Dir2d anOldDir; - theOld.Tangent(anOldDir); - const double aDot = aNew.Direction.X() * anOldDir.X() + aNew.Direction.Y() * anOldDir.Y(); - EXPECT_NEAR(std::abs(aDot), 1.0, THE_DIR_TOL) << "Tangent mismatch at U=" << theParam; - } -} - -void compareCurvature(Geom2dProp_Curve& theProp, - Geom2dLProp_CLProps2d& theOld, - const double theParam) -{ - theOld.SetParameter(theParam); - const Geom2dProp::CurvatureResult aNew = theProp.Curvature(theParam, THE_LIN_TOL); - const double aOldCurv = theOld.Curvature(); - if (aNew.IsDefined && !aNew.IsInfinite) - { - EXPECT_NEAR(aNew.Value, aOldCurv, THE_CURV_TOL) << "Curvature mismatch at U=" << theParam; - } -} - -void compareNormal(Geom2dProp_Curve& theProp, Geom2dLProp_CLProps2d& theOld, const double theParam) -{ - theOld.SetParameter(theParam); - const Geom2dProp::NormalResult aNew = theProp.Normal(theParam, THE_LIN_TOL); - const double aOldCurv = theOld.Curvature(); - if (std::abs(aOldCurv) < THE_LIN_TOL) - { - return; - } - if (aNew.IsDefined) - { - gp_Dir2d anOldNorm; - theOld.Normal(anOldNorm); - const double aDot = aNew.Direction.X() * anOldNorm.X() + aNew.Direction.Y() * anOldNorm.Y(); - EXPECT_NEAR(std::abs(aDot), 1.0, THE_DIR_TOL) << "Normal mismatch at U=" << theParam; - } -} - -void compareCentre(Geom2dProp_Curve& theProp, Geom2dLProp_CLProps2d& theOld, const double theParam) -{ - theOld.SetParameter(theParam); - const Geom2dProp::CentreResult aNew = theProp.CentreOfCurvature(theParam, THE_LIN_TOL); - const double aOldCurv = theOld.Curvature(); - if (std::abs(aOldCurv) < THE_LIN_TOL) - { - return; - } - if (aNew.IsDefined) - { - gp_Pnt2d anOldCentre; - theOld.CentreOfCurvature(anOldCentre); - EXPECT_NEAR(aNew.Centre.X(), anOldCentre.X(), THE_POINT_TOL) - << "Centre X mismatch at U=" << theParam; - EXPECT_NEAR(aNew.Centre.Y(), anOldCentre.Y(), THE_POINT_TOL) - << "Centre Y mismatch at U=" << theParam; - } -} - -void compareAll(Geom2dProp_Curve& theProp, - Geom2dLProp_CLProps2d& theOld, - const double theFirst, - const double theLast, - const int theNbSamples = 10) -{ - const double aStep = (theLast - theFirst) / theNbSamples; - for (int i = 0; i <= theNbSamples; ++i) - { - const double aParam = theFirst + i * aStep; - compareTangent(theProp, theOld, aParam); - compareCurvature(theProp, theOld, aParam); - compareNormal(theProp, theOld, aParam); - compareCentre(theProp, theOld, aParam); - } -} - -Geom2dProp::CIType mapLPropType(const LProp_CIType theType) -{ - switch (theType) - { - case LProp_Inflection: - return Geom2dProp::CIType::Inflection; - case LProp_MinCur: - return Geom2dProp::CIType::MinCurvature; - case LProp_MaxCur: - return Geom2dProp::CIType::MaxCurvature; - } - return Geom2dProp::CIType::Inflection; -} - -void compareExtrema(const Geom2dProp::CurveAnalysis& theNew, - const Geom2dLProp_CurAndInf2d& theOld, - const double theTol = THE_PARAM_TOL) -{ - EXPECT_EQ(theNew.Points.Length(), theOld.NbPoints()); - const int aNb = std::min(theNew.Points.Length(), theOld.NbPoints()); - for (int i = 0; i < aNb; ++i) - { - EXPECT_NEAR(theNew.Points.Value(i).Parameter, theOld.Parameter(i + 1), theTol) - << "Parameter mismatch at index " << i; - EXPECT_EQ(theNew.Points.Value(i).Type, mapLPropType(theOld.Type(i + 1))) - << "Type mismatch at index " << i; - } -} - -// Helper: create trimmed circle. -occ::handle makeTrimmedCircle(const double theRadius, - const double theFirst, - const double theLast) -{ - gp_Circ2d aCirc(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), theRadius); - occ::handle aCircle = new Geom2d_Circle(aCirc); - return new Geom2d_TrimmedCurve(aCircle, theFirst, theLast); -} - -// Helper: create trimmed ellipse. -occ::handle makeTrimmedEllipse(const double theMajor, - const double theMinor, - const double theFirst, - const double theLast) -{ - gp_Elips2d anElips(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), theMajor, theMinor); - occ::handle anEllipse = new Geom2d_Ellipse(anElips); - return new Geom2d_TrimmedCurve(anEllipse, theFirst, theLast); -} - -// Helper: create cubic S-shaped Bezier for trimming. -occ::handle makeSBezier() -{ - NCollection_Array1 aPoles(1, 4); - aPoles(1) = gp_Pnt2d(0.0, 0.0); - aPoles(2) = gp_Pnt2d(1.0, 3.0); - aPoles(3) = gp_Pnt2d(3.0, -1.0); - aPoles(4) = gp_Pnt2d(4.0, 1.0); - return new Geom2d_BezierCurve(aPoles); -} - -} // namespace - -// ============================================================================ -// Trimmed circle tests -// ============================================================================ - -TEST(Geom2dProp_OtherCurveTest, Tangent_TrimmedCircle) -{ - const double aRadius = 5.0; - occ::handle aCurve = makeTrimmedCircle(aRadius, 0.5, 2.5); - Geom2dProp_Curve aProp(aCurve); - - for (double u = 0.5; u <= 2.5; u += 0.5) - { - const Geom2dProp::TangentResult aTan = aProp.Tangent(u, THE_LIN_TOL); - ASSERT_TRUE(aTan.IsDefined) << "Tangent undefined at U=" << u; - } -} - -TEST(Geom2dProp_OtherCurveTest, Curvature_TrimmedCircle) -{ - const double aRadius = 5.0; - occ::handle aCurve = makeTrimmedCircle(aRadius, 0.5, 2.5); - Geom2dProp_Curve aProp(aCurve); - - const double aExpectedCurv = 1.0 / aRadius; - for (double u = 0.5; u <= 2.5; u += 0.5) - { - const Geom2dProp::CurvatureResult aCurv = aProp.Curvature(u, THE_LIN_TOL); - ASSERT_TRUE(aCurv.IsDefined) << "Curvature undefined at U=" << u; - EXPECT_NEAR(aCurv.Value, aExpectedCurv, THE_CURV_TOL) << "Curvature mismatch at U=" << u; - } -} - -TEST(Geom2dProp_OtherCurveTest, Normal_TrimmedCircle) -{ - const double aRadius = 5.0; - occ::handle aCurve = makeTrimmedCircle(aRadius, 0.5, 2.5); - Geom2dProp_Curve aProp(aCurve); - - for (double u = 0.5; u <= 2.5; u += 0.5) - { - const Geom2dProp::NormalResult aNorm = aProp.Normal(u, THE_LIN_TOL); - ASSERT_TRUE(aNorm.IsDefined) << "Normal undefined at U=" << u; - // Normal should point toward center (0,0) - // Point on circle: (R*cos(u), R*sin(u)), so normal toward center is (-cos(u), -sin(u)) - const double aExpX = -std::cos(u); - const double aExpY = -std::sin(u); - const double aDot = aNorm.Direction.X() * aExpX + aNorm.Direction.Y() * aExpY; - EXPECT_NEAR(std::abs(aDot), 1.0, THE_DIR_TOL) << "Normal direction mismatch at U=" << u; - } -} - -TEST(Geom2dProp_OtherCurveTest, Centre_TrimmedCircle) -{ - occ::handle aCurve = makeTrimmedCircle(5.0, 0.5, 2.5); - Geom2dProp_Curve aProp(aCurve); - - for (double u = 0.5; u <= 2.5; u += 0.5) - { - const Geom2dProp::CentreResult aCentre = aProp.CentreOfCurvature(u, THE_LIN_TOL); - ASSERT_TRUE(aCentre.IsDefined) << "Centre undefined at U=" << u; - EXPECT_NEAR(aCentre.Centre.X(), 0.0, THE_POINT_TOL); - EXPECT_NEAR(aCentre.Centre.Y(), 0.0, THE_POINT_TOL); - } -} - -TEST(Geom2dProp_OtherCurveTest, FindCurvatureExtrema_TrimmedCircle) -{ - occ::handle aCurve = makeTrimmedCircle(5.0, 0.5, 2.5); - Geom2dProp_Curve aProp(aCurve); - - const Geom2dProp::CurveAnalysis aResult = aProp.FindCurvatureExtrema(); - ASSERT_TRUE(aResult.IsDone); - EXPECT_EQ(aResult.Points.Length(), 0); -} - -TEST(Geom2dProp_OtherCurveTest, FindInflections_TrimmedCircle) -{ - occ::handle aCurve = makeTrimmedCircle(5.0, 0.5, 2.5); - Geom2dProp_Curve aProp(aCurve); - - const Geom2dProp::CurveAnalysis aResult = aProp.FindInflections(); - ASSERT_TRUE(aResult.IsDone); - EXPECT_EQ(aResult.Points.Length(), 0); -} - -// ============================================================================ -// Trimmed ellipse tests -// ============================================================================ - -TEST(Geom2dProp_OtherCurveTest, Tangent_TrimmedEllipse) -{ - occ::handle aCurve = makeTrimmedEllipse(10.0, 5.0, 0.0, M_PI); - Geom2dProp_Curve aProp(aCurve); - - for (double u = 0.0; u <= M_PI; u += M_PI / 6.0) - { - const Geom2dProp::TangentResult aTan = aProp.Tangent(u, THE_LIN_TOL); - EXPECT_TRUE(aTan.IsDefined) << "Tangent undefined at U=" << u; - } -} - -TEST(Geom2dProp_OtherCurveTest, Curvature_TrimmedEllipse) -{ - occ::handle aCurve = makeTrimmedEllipse(10.0, 5.0, 0.0, M_PI); - Geom2dProp_Curve aProp(aCurve); - - // Curvature at u=0 (major vertex) and u=pi/2 (minor vertex) should differ - const Geom2dProp::CurvatureResult aCurv0 = aProp.Curvature(0.0, THE_LIN_TOL); - const Geom2dProp::CurvatureResult aCurvHalf = aProp.Curvature(M_PI / 2.0, THE_LIN_TOL); - ASSERT_TRUE(aCurv0.IsDefined); - ASSERT_TRUE(aCurvHalf.IsDefined); - EXPECT_NE(aCurv0.Value, aCurvHalf.Value); -} - -TEST(Geom2dProp_OtherCurveTest, FindCurvatureExtrema_TrimmedEllipse) -{ - occ::handle aCurve = makeTrimmedEllipse(10.0, 5.0, 0.0, M_PI); - Geom2dProp_Curve aProp(aCurve); - - const Geom2dProp::CurveAnalysis aResult = aProp.FindCurvatureExtrema(); - ASSERT_TRUE(aResult.IsDone); - // Half-ellipse should have extrema (at major and minor vertices) - EXPECT_GT(aResult.Points.Length(), 0); - - for (int i = 0; i < aResult.Points.Length(); ++i) - { - EXPECT_GE(aResult.Points.Value(i).Parameter, 0.0); - EXPECT_LE(aResult.Points.Value(i).Parameter, M_PI); - } -} - -TEST(Geom2dProp_OtherCurveTest, FindInflections_TrimmedEllipse) -{ - occ::handle aCurve = makeTrimmedEllipse(10.0, 5.0, 0.0, M_PI); - Geom2dProp_Curve aProp(aCurve); - - const Geom2dProp::CurveAnalysis aResult = aProp.FindInflections(); - ASSERT_TRUE(aResult.IsDone); - // Ellipse has no inflections - EXPECT_EQ(aResult.Points.Length(), 0); -} - -// ============================================================================ -// GetType test -// ============================================================================ - -TEST(Geom2dProp_OtherCurveTest, GetType_IsOtherCurve) -{ - occ::handle aCurve = makeTrimmedCircle(5.0, 0.5, 2.5); - Geom2dProp_Curve aProp(aCurve); - // Trimmed curves typically resolve to OtherCurve or the underlying type - // depending on adaptor resolution. Check that it returns a valid type. - const GeomAbs_CurveType aType = aProp.GetType(); - // Trimmed circle should be recognized as Circle by the adaptor - EXPECT_EQ(aType, GeomAbs_Circle); -} - -// ============================================================================ -// Cross-validation vs CLProps2d -// ============================================================================ - -TEST(Geom2dProp_OtherCurveTest, VsCLProps2d_TrimmedCircle) -{ - occ::handle aCurve = makeTrimmedCircle(5.0, 0.5, 2.5); - Geom2dProp_Curve aProp(aCurve); - Geom2dLProp_CLProps2d aOld(aCurve, 2, THE_LIN_TOL); - - for (double u = 0.5; u <= 2.5; u += 0.25) - { - compareTangent(aProp, aOld, u); - compareCurvature(aProp, aOld, u); - } -} - -TEST(Geom2dProp_OtherCurveTest, VsCLProps2d_TrimmedEllipse) -{ - occ::handle aCurve = makeTrimmedEllipse(10.0, 5.0, 0.0, M_PI); - Geom2dProp_Curve aProp(aCurve); - Geom2dLProp_CLProps2d aOld(aCurve, 2, THE_LIN_TOL); - - for (double u = 0.0; u <= M_PI; u += M_PI / 8.0) - { - compareTangent(aProp, aOld, u); - compareCurvature(aProp, aOld, u); - } -} - -TEST(Geom2dProp_OtherCurveTest, VsCLProps2d_TrimmedBezier) -{ - occ::handle aBezier = makeSBezier(); - occ::handle aTrimmed = new Geom2d_TrimmedCurve(aBezier, 0.2, 0.8); - - Geom2dProp_Curve aProp(aTrimmed); - Geom2dLProp_CLProps2d aOld(aTrimmed, 2, THE_LIN_TOL); - - for (double u = 0.2; u <= 0.8; u += 0.1) - { - compareTangent(aProp, aOld, u); - compareCurvature(aProp, aOld, u); - } -} - -TEST(Geom2dProp_OtherCurveTest, VsCLProps2d_AllProperties_TrimmedCircle) -{ - occ::handle aCurve = makeTrimmedCircle(5.0, 0.5, 2.5); - Geom2dProp_Curve aProp(aCurve); - Geom2dLProp_CLProps2d aOld(aCurve, 2, THE_LIN_TOL); - - compareAll(aProp, aOld, 0.5, 2.5, 20); -} - -TEST(Geom2dProp_OtherCurveTest, VsCLProps2d_AllProperties_TrimmedEllipse) -{ - occ::handle aCurve = makeTrimmedEllipse(10.0, 5.0, 0.0, M_PI); - Geom2dProp_Curve aProp(aCurve); - Geom2dLProp_CLProps2d aOld(aCurve, 2, THE_LIN_TOL); - - compareAll(aProp, aOld, 0.0, M_PI, 20); -} - -TEST(Geom2dProp_OtherCurveTest, VsCLProps2d_AllProperties_TrimmedBezier) -{ - occ::handle aBezier = makeSBezier(); - occ::handle aTrimmed = new Geom2d_TrimmedCurve(aBezier, 0.2, 0.8); - - Geom2dProp_Curve aProp(aTrimmed); - Geom2dLProp_CLProps2d aOld(aTrimmed, 2, THE_LIN_TOL); - - compareAll(aProp, aOld, 0.2, 0.8, 20); -} - -// ============================================================================ -// Trimmed hyperbola -// ============================================================================ - -TEST(Geom2dProp_OtherCurveTest, Curvature_TrimmedHyperbola) -{ - gp_Hypr2d anHypr(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 6.0, 3.0); - occ::handle aHyperbola = new Geom2d_Hyperbola(anHypr); - occ::handle aTrimmed = new Geom2d_TrimmedCurve(aHyperbola, -1.0, 1.0); - - Geom2dProp_Curve aProp(aTrimmed); - - // Curvature at vertex (u=0) should be maximum for hyperbola - const Geom2dProp::CurvatureResult aCurvVertex = aProp.Curvature(0.0, THE_LIN_TOL); - ASSERT_TRUE(aCurvVertex.IsDefined); - EXPECT_GT(std::abs(aCurvVertex.Value), 0.0); - - // Curvature should decrease away from vertex - const Geom2dProp::CurvatureResult aCurvAway = aProp.Curvature(0.8, THE_LIN_TOL); - ASSERT_TRUE(aCurvAway.IsDefined); - EXPECT_LT(std::abs(aCurvAway.Value), std::abs(aCurvVertex.Value)); -} - -// ============================================================================ -// Cross-validation vs CurAndInf2d -// ============================================================================ - -TEST(Geom2dProp_OtherCurveTest, VsCurAndInf2d_TrimmedEllipse_Extrema) -{ - occ::handle aCurve = makeTrimmedEllipse(10.0, 5.0, 0.0, M_PI); - - Geom2dLProp_CurAndInf2d anOld; - anOld.PerformCurExt(aCurve); - ASSERT_TRUE(anOld.IsDone()); - - Geom2dProp_Curve aProp(aCurve); - const Geom2dProp::CurveAnalysis aNew = aProp.FindCurvatureExtrema(); - ASSERT_TRUE(aNew.IsDone); - - compareExtrema(aNew, anOld, 1.0e-6); -} - -// ============================================================================ -// Trimmed Bezier inflections (S-curve) -// ============================================================================ - -TEST(Geom2dProp_OtherCurveTest, FindInflections_TrimmedBezier) -{ - occ::handle aBezier = makeSBezier(); - occ::handle aTrimmed = new Geom2d_TrimmedCurve(aBezier, 0.1, 0.9); - - Geom2dProp_Curve aProp(aTrimmed); - - const Geom2dProp::CurveAnalysis aResult = aProp.FindInflections(); - ASSERT_TRUE(aResult.IsDone); - - // S-shaped Bezier should have inflection(s) within [0.1, 0.9] - for (int i = 0; i < aResult.Points.Length(); ++i) - { - EXPECT_GE(aResult.Points.Value(i).Parameter, 0.1); - EXPECT_LE(aResult.Points.Value(i).Parameter, 0.9); - EXPECT_EQ(aResult.Points.Value(i).Type, Geom2dProp::CIType::Inflection); - } -} - -TEST(Geom2dProp_OtherCurveTest, VsCLProps2d_CriticalPoints) -{ - occ::handle aCircle = - new Geom2d_Circle(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 5.0); - occ::handle aTrimmed = - new Geom2d_TrimmedCurve(aCircle, M_PI / 4.0, 3.0 * M_PI / 4.0); - Geom2dProp_Curve aProp(aTrimmed); - Geom2dLProp_CLProps2d aOld(aTrimmed, 2, THE_LIN_TOL); - const double aFirst = aTrimmed->FirstParameter(); - const double aLast = aTrimmed->LastParameter(); - const double aMid = (aFirst + aLast) / 2.0; - const double aParams[] = {aFirst, - aFirst + 1.0e-10, - aFirst + 1.0e-6, - aMid, - aMid + 1.0e-6, - aMid - 1.0e-6, - aLast - 1.0e-6, - aLast - 1.0e-10, - aLast}; - for (const double aParam : aParams) - { - compareTangent(aProp, aOld, aParam); - compareCurvature(aProp, aOld, aParam); - compareNormal(aProp, aOld, aParam); - compareCentre(aProp, aOld, aParam); - } -} diff --git a/src/ModelingData/TKG2d/GTests/Geom2dProp_Parabola_Test.cxx b/src/ModelingData/TKG2d/GTests/Geom2dProp_Parabola_Test.cxx deleted file mode 100644 index 3ae7993875..0000000000 --- a/src/ModelingData/TKG2d/GTests/Geom2dProp_Parabola_Test.cxx +++ /dev/null @@ -1,482 +0,0 @@ -// 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -namespace -{ -constexpr double THE_LIN_TOL = Precision::PConfusion(); -constexpr double THE_CURV_TOL = 1.0e-8; -constexpr double THE_DIR_TOL = 1.0e-6; -constexpr double THE_POINT_TOL = 1.0e-6; - -void compareTangent(Geom2dProp_Curve& theProp, Geom2dLProp_CLProps2d& theOld, const double theParam) -{ - theOld.SetParameter(theParam); - const Geom2dProp::TangentResult aNew = theProp.Tangent(theParam, THE_LIN_TOL); - if (theOld.IsTangentDefined()) - { - ASSERT_TRUE(aNew.IsDefined); - gp_Dir2d anOldDir; - theOld.Tangent(anOldDir); - const double aDot = aNew.Direction.X() * anOldDir.X() + aNew.Direction.Y() * anOldDir.Y(); - EXPECT_NEAR(std::abs(aDot), 1.0, THE_DIR_TOL); - } -} - -void compareCurvature(Geom2dProp_Curve& theProp, - Geom2dLProp_CLProps2d& theOld, - const double theParam) -{ - theOld.SetParameter(theParam); - const Geom2dProp::CurvatureResult aNew = theProp.Curvature(theParam, THE_LIN_TOL); - const double aOldCurv = theOld.Curvature(); - if (aNew.IsDefined && !aNew.IsInfinite) - { - EXPECT_NEAR(aNew.Value, aOldCurv, THE_CURV_TOL); - } -} - -void compareNormal(Geom2dProp_Curve& theProp, Geom2dLProp_CLProps2d& theOld, const double theParam) -{ - theOld.SetParameter(theParam); - const Geom2dProp::NormalResult aNew = theProp.Normal(theParam, THE_LIN_TOL); - const double aOldCurv = theOld.Curvature(); - if (std::abs(aOldCurv) < THE_LIN_TOL) - { - return; - } - if (aNew.IsDefined) - { - gp_Dir2d anOldNorm; - theOld.Normal(anOldNorm); - const double aDot = aNew.Direction.X() * anOldNorm.X() + aNew.Direction.Y() * anOldNorm.Y(); - EXPECT_NEAR(std::abs(aDot), 1.0, THE_DIR_TOL); - } -} - -void compareCentre(Geom2dProp_Curve& theProp, Geom2dLProp_CLProps2d& theOld, const double theParam) -{ - theOld.SetParameter(theParam); - const Geom2dProp::CentreResult aNew = theProp.CentreOfCurvature(theParam, THE_LIN_TOL); - const double aOldCurv = theOld.Curvature(); - if (std::abs(aOldCurv) < THE_LIN_TOL) - { - return; - } - if (aNew.IsDefined) - { - gp_Pnt2d anOldCentre; - theOld.CentreOfCurvature(anOldCentre); - EXPECT_NEAR(aNew.Centre.X(), anOldCentre.X(), THE_POINT_TOL); - EXPECT_NEAR(aNew.Centre.Y(), anOldCentre.Y(), THE_POINT_TOL); - } -} - -void compareAll(Geom2dProp_Curve& theProp, - Geom2dLProp_CLProps2d& theOld, - const double theFirst, - const double theLast, - const int theNbSamples = 10) -{ - const double aStep = (theLast - theFirst) / theNbSamples; - for (int i = 0; i <= theNbSamples; ++i) - { - const double aParam = theFirst + i * aStep; - compareTangent(theProp, theOld, aParam); - compareCurvature(theProp, theOld, aParam); - compareNormal(theProp, theOld, aParam); - compareCentre(theProp, theOld, aParam); - } -} - -Geom2dProp::CIType mapLPropType(const LProp_CIType theType) -{ - switch (theType) - { - case LProp_Inflection: - return Geom2dProp::CIType::Inflection; - case LProp_MinCur: - return Geom2dProp::CIType::MinCurvature; - case LProp_MaxCur: - return Geom2dProp::CIType::MaxCurvature; - } - return Geom2dProp::CIType::Inflection; -} - -void compareExtrema(const Geom2dProp::CurveAnalysis& theNew, - const Geom2dLProp_CurAndInf2d& theOld, - const double theTol = 1.0e-4) -{ - EXPECT_EQ(theNew.Points.Length(), theOld.NbPoints()); - const int aNb = std::min(theNew.Points.Length(), theOld.NbPoints()); - for (int i = 0; i < aNb; ++i) - { - EXPECT_NEAR(theNew.Points.Value(i).Parameter, theOld.Parameter(i + 1), theTol) - << "Parameter mismatch at index " << i; - EXPECT_EQ(theNew.Points.Value(i).Type, mapLPropType(theOld.Type(i + 1))) - << "Type mismatch at index " << i; - } -} - -} // namespace - -TEST(Geom2dProp_ParabolaTest, Curvature_AtVertex) -{ - // For parabola with focal distance f, curvature at vertex (t=0) is k = 1/(2f). - const double aFocal = 2.0; - gp_Parab2d aParab(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), aFocal); - occ::handle aParabola = new Geom2d_Parabola(aParab); - - Geom2dProp_Curve aProp(aParabola); - const Geom2dProp::CurvatureResult aCurv = aProp.Curvature(0.0, THE_LIN_TOL); - - ASSERT_TRUE(aCurv.IsDefined); - ASSERT_FALSE(aCurv.IsInfinite); - const double anExpected = 1.0 / (2.0 * aFocal); - EXPECT_NEAR(aCurv.Value, anExpected, THE_CURV_TOL); -} - -TEST(Geom2dProp_ParabolaTest, Curvature_Symmetric) -{ - // k(t) = k(-t) for a centered parabola. - const double aFocal = 3.0; - gp_Parab2d aParab(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), aFocal); - occ::handle aParabola = new Geom2d_Parabola(aParab); - - Geom2dProp_Curve aProp(aParabola); - for (double t = 0.5; t <= 5.0; t += 0.5) - { - const Geom2dProp::CurvatureResult aCurvPos = aProp.Curvature(t, THE_LIN_TOL); - const Geom2dProp::CurvatureResult aCurvNeg = aProp.Curvature(-t, THE_LIN_TOL); - ASSERT_TRUE(aCurvPos.IsDefined); - ASSERT_TRUE(aCurvNeg.IsDefined); - EXPECT_NEAR(aCurvPos.Value, aCurvNeg.Value, THE_CURV_TOL) << "Asymmetry at t=" << t; - } -} - -TEST(Geom2dProp_ParabolaTest, Curvature_DecreasesFromVertex) -{ - // Curvature magnitude decreases as |t| increases from vertex. - const double aFocal = 2.0; - gp_Parab2d aParab(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), aFocal); - occ::handle aParabola = new Geom2d_Parabola(aParab); - - Geom2dProp_Curve aProp(aParabola); - double aPrevCurv = 1.0e30; - for (double t = 0.0; t <= 5.0; t += 0.5) - { - const Geom2dProp::CurvatureResult aCurv = aProp.Curvature(t, THE_LIN_TOL); - ASSERT_TRUE(aCurv.IsDefined); - const double anAbsCurv = std::abs(aCurv.Value); - EXPECT_LE(anAbsCurv, aPrevCurv + THE_CURV_TOL) << "Curvature not decreasing at t=" << t; - aPrevCurv = anAbsCurv; - } -} - -TEST(Geom2dProp_ParabolaTest, Tangent_AtVertex) -{ - // At vertex (t=0), tangent is perpendicular to the axis. - gp_Parab2d aParab(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 2.0); - occ::handle aParabola = new Geom2d_Parabola(aParab); - - Geom2dProp_Curve aProp(aParabola); - const Geom2dProp::TangentResult aTan = aProp.Tangent(0.0, THE_LIN_TOL); - - ASSERT_TRUE(aTan.IsDefined); - // Tangent at vertex should be along Y axis (perpendicular to axis direction X). - const double aDotX = aTan.Direction.X() * 1.0 + aTan.Direction.Y() * 0.0; - EXPECT_NEAR(std::abs(aDotX), 0.0, THE_DIR_TOL); -} - -TEST(Geom2dProp_ParabolaTest, Normal_AtVertex) -{ - // At vertex, normal should be along axis. - gp_Parab2d aParab(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 2.0); - occ::handle aParabola = new Geom2d_Parabola(aParab); - - Geom2dProp_Curve aProp(aParabola); - const Geom2dProp::NormalResult aNorm = aProp.Normal(0.0, THE_LIN_TOL); - - ASSERT_TRUE(aNorm.IsDefined); - // Normal at vertex should be along X axis. - const double aDotX = aNorm.Direction.X() * 1.0 + aNorm.Direction.Y() * 0.0; - EXPECT_NEAR(std::abs(aDotX), 1.0, THE_DIR_TOL); -} - -TEST(Geom2dProp_ParabolaTest, Centre_AtVertex) -{ - // Centre of curvature at vertex is at distance 1/k = 2f from vertex. - const double aFocal = 2.0; - gp_Parab2d aParab(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), aFocal); - occ::handle aParabola = new Geom2d_Parabola(aParab); - - Geom2dProp_Curve aProp(aParabola); - const Geom2dProp::CentreResult aCentre = aProp.CentreOfCurvature(0.0, THE_LIN_TOL); - - ASSERT_TRUE(aCentre.IsDefined); - // For gp_Parab2d, the vertex is at the axis origin (0, 0). - // Curvature at vertex = 1/(2f), so radius of curvature = 2f. - // Centre of curvature is at (2f, 0) along the axis from the vertex. - const double anExpectedX = 2.0 * aFocal; - EXPECT_NEAR(aCentre.Centre.X(), anExpectedX, THE_POINT_TOL); - EXPECT_NEAR(aCentre.Centre.Y(), 0.0, THE_POINT_TOL); -} - -TEST(Geom2dProp_ParabolaTest, FindCurvatureExtrema_OnePoint) -{ - // Parabola has exactly one curvature extremum at vertex (t=0). - gp_Parab2d aParab(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 2.0); - occ::handle aParabola = new Geom2d_Parabola(aParab); - - Geom2dProp_Curve aProp(aParabola); - const Geom2dProp::CurveAnalysis aExtrema = aProp.FindCurvatureExtrema(); - - ASSERT_TRUE(aExtrema.IsDone); - EXPECT_EQ(aExtrema.Points.Length(), 1); - if (aExtrema.Points.Length() == 1) - { - EXPECT_NEAR(aExtrema.Points.Value(0).Parameter, 0.0, 1.0e-6); - } -} - -TEST(Geom2dProp_ParabolaTest, FindInflections_Empty) -{ - // Parabola has no inflection points. - gp_Parab2d aParab(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 2.0); - occ::handle aParabola = new Geom2d_Parabola(aParab); - - Geom2dProp_Curve aProp(aParabola); - const Geom2dProp::CurveAnalysis aInflections = aProp.FindInflections(); - - ASSERT_TRUE(aInflections.IsDone); - EXPECT_EQ(aInflections.Points.Length(), 0); -} - -TEST(Geom2dProp_ParabolaTest, GetType_IsParabola) -{ - gp_Parab2d aParab(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 2.0); - occ::handle aParabola = new Geom2d_Parabola(aParab); - - Geom2dProp_Curve aProp(aParabola); - EXPECT_EQ(aProp.GetType(), GeomAbs_Parabola); -} - -TEST(Geom2dProp_ParabolaTest, Curvature_LargeParam) -{ - // Curvature approaches 0 for large |t|. - gp_Parab2d aParab(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 2.0); - occ::handle aParabola = new Geom2d_Parabola(aParab); - - Geom2dProp_Curve aProp(aParabola); - const Geom2dProp::CurvatureResult aCurv = aProp.Curvature(50.0, THE_LIN_TOL); - - ASSERT_TRUE(aCurv.IsDefined); - EXPECT_LT(std::abs(aCurv.Value), 0.001); -} - -TEST(Geom2dProp_ParabolaTest, VsCLProps2d_Standard) -{ - // Cross-validate against deprecated CLProps2d with f=2. - gp_Parab2d aParab(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 2.0); - occ::handle aParabola = new Geom2d_Parabola(aParab); - - Geom2dProp_Curve aProp(aParabola); - Geom2dLProp_CLProps2d aOld(aParabola, 2, THE_LIN_TOL); - - compareAll(aProp, aOld, -5.0, 5.0, 10); -} - -TEST(Geom2dProp_ParabolaTest, VsCLProps2d_AllProperties) -{ - // Dense comparison over [-5, 5]. - gp_Parab2d aParab(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 2.0); - occ::handle aParabola = new Geom2d_Parabola(aParab); - - Geom2dProp_Curve aProp(aParabola); - Geom2dLProp_CLProps2d aOld(aParabola, 2, THE_LIN_TOL); - - compareAll(aProp, aOld, -5.0, 5.0, 40); -} - -TEST(Geom2dProp_ParabolaTest, VsCLProps2d_SmallFocal) -{ - // Cross-validate with f=0.1. - gp_Parab2d aParab(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 0.1); - occ::handle aParabola = new Geom2d_Parabola(aParab); - - Geom2dProp_Curve aProp(aParabola); - Geom2dLProp_CLProps2d aOld(aParabola, 2, THE_LIN_TOL); - - compareAll(aProp, aOld, -3.0, 3.0, 10); -} - -TEST(Geom2dProp_ParabolaTest, VsCLProps2d_LargeFocal) -{ - // Cross-validate with f=50. - gp_Parab2d aParab(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 50.0); - occ::handle aParabola = new Geom2d_Parabola(aParab); - - Geom2dProp_Curve aProp(aParabola); - Geom2dLProp_CLProps2d aOld(aParabola, 2, THE_LIN_TOL); - - compareAll(aProp, aOld, -10.0, 10.0, 10); -} - -TEST(Geom2dProp_ParabolaTest, VsCLProps2d_OffCenter) -{ - // Cross-validate parabola centered at (3,4). - gp_Parab2d aParab(gp_Ax2d(gp_Pnt2d(3.0, 4.0), gp_Dir2d(1.0, 0.0)), 2.0); - occ::handle aParabola = new Geom2d_Parabola(aParab); - - Geom2dProp_Curve aProp(aParabola); - Geom2dLProp_CLProps2d aOld(aParabola, 2, THE_LIN_TOL); - - compareAll(aProp, aOld, -5.0, 5.0, 10); -} - -TEST(Geom2dProp_ParabolaTest, Tangent_LargeParam) -{ - // For large |t|, tangent approaches the axis direction. - gp_Parab2d aParab(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 2.0); - occ::handle aParabola = new Geom2d_Parabola(aParab); - - Geom2dProp_Curve aProp(aParabola); - const Geom2dProp::TangentResult aTan = aProp.Tangent(100.0, THE_LIN_TOL); - - ASSERT_TRUE(aTan.IsDefined); - // For large positive t, the parabola y^2 = 4fx goes mostly in the +X direction. - // The tangent should be nearly along (1, 0) for large t. - const double aDotX = aTan.Direction.X() * 1.0 + aTan.Direction.Y() * 0.0; - EXPECT_GT(std::abs(aDotX), 0.99); -} - -TEST(Geom2dProp_ParabolaTest, Centre_MovesAway) -{ - // Centre of curvature moves away from vertex as |t| increases. - const double aFocal = 2.0; - gp_Parab2d aParab(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), aFocal); - occ::handle aParabola = new Geom2d_Parabola(aParab); - - Geom2dProp_Curve aProp(aParabola); - double aPrevDist = 0.0; - for (double t = 0.0; t <= 5.0; t += 1.0) - { - const Geom2dProp::CentreResult aCentre = aProp.CentreOfCurvature(t, THE_LIN_TOL); - ASSERT_TRUE(aCentre.IsDefined); - const double aDist = - std::sqrt(aCentre.Centre.X() * aCentre.Centre.X() + aCentre.Centre.Y() * aCentre.Centre.Y()); - if (t > 0.0) - { - EXPECT_GT(aDist, aPrevDist - THE_POINT_TOL) << "Centre not moving away at t=" << t; - } - aPrevDist = aDist; - } -} - -TEST(Geom2dProp_ParabolaTest, Curvature_NearVertex) -{ - // Fine-grained curvature check near vertex. - const double aFocal = 2.0; - gp_Parab2d aParab(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), aFocal); - occ::handle aParabola = new Geom2d_Parabola(aParab); - - Geom2dProp_Curve aProp(aParabola); - const double anExpectedMax = 1.0 / (2.0 * aFocal); - - for (double t = -0.5; t <= 0.5; t += 0.05) - { - const Geom2dProp::CurvatureResult aCurv = aProp.Curvature(t, THE_LIN_TOL); - ASSERT_TRUE(aCurv.IsDefined); - EXPECT_LE(std::abs(aCurv.Value), anExpectedMax + THE_CURV_TOL) - << "Curvature exceeds vertex maximum at t=" << t; - } -} - -TEST(Geom2dProp_ParabolaTest, VsCurAndInf2d_Extrema) -{ - // Compare curvature extrema with deprecated CurAndInf2d. - gp_Parab2d aParab(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 2.0); - occ::handle aParabola = new Geom2d_Parabola(aParab); - - Geom2dLProp_CurAndInf2d anOld; - anOld.PerformCurExt(aParabola); - ASSERT_TRUE(anOld.IsDone()); - - Geom2dProp_Curve aProp(aParabola); - const Geom2dProp::CurveAnalysis aNew = aProp.FindCurvatureExtrema(); - ASSERT_TRUE(aNew.IsDone); - - compareExtrema(aNew, anOld, 1.0e-6); -} - -TEST(Geom2dProp_ParabolaTest, VsCurAndInf2d_NoInflections) -{ - // Compare inflection results with deprecated CurAndInf2d. - gp_Parab2d aParab(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 2.0); - occ::handle aParabola = new Geom2d_Parabola(aParab); - - Geom2dLProp_CurAndInf2d anOld; - anOld.PerformInf(aParabola); - ASSERT_TRUE(anOld.IsDone()); - EXPECT_EQ(anOld.NbPoints(), 0); - - Geom2dProp_Curve aProp(aParabola); - const Geom2dProp::CurveAnalysis aNew = aProp.FindInflections(); - ASSERT_TRUE(aNew.IsDone); - EXPECT_EQ(aNew.Points.Length(), 0); -} - -TEST(Geom2dProp_ParabolaTest, VsCLProps2d_CriticalPoints) -{ - gp_Parab2d aParab(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 5.0); - occ::handle aParabola = new Geom2d_Parabola(aParab); - Geom2dProp_Curve aProp(aParabola); - Geom2dLProp_CLProps2d aOld(aParabola, 2, THE_LIN_TOL); - const double aParams[] = {0.0, - 1.0e-10, - -1.0e-10, - 1.0e-6, - -1.0e-6, - 0.1, - -0.1, - 0.5, - -0.5, - 1.0, - -1.0, - 5.0, - -5.0, - 10.0, - -10.0}; - for (const double aParam : aParams) - { - compareTangent(aProp, aOld, aParam); - compareCurvature(aProp, aOld, aParam); - compareNormal(aProp, aOld, aParam); - compareCentre(aProp, aOld, aParam); - } -} diff --git a/src/ModelingData/TKG2d/GTests/Geom2dProp_Test.cxx b/src/ModelingData/TKG2d/GTests/Geom2dProp_Test.cxx deleted file mode 100644 index 50183ddd20..0000000000 --- a/src/ModelingData/TKG2d/GTests/Geom2dProp_Test.cxx +++ /dev/null @@ -1,1586 +0,0 @@ -// 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include - -// ============================================================================ -// Free functions tests (Geom2dProp namespace) -// ============================================================================ - -TEST(Geom2dPropTest, ComputeTangent_FromD1) -{ - const gp_Vec2d aD1(3.0, 4.0); - const gp_Vec2d aD2(0.0, 0.0); - const gp_Vec2d aD3(0.0, 0.0); - - const Geom2dProp::TangentResult aRes = Geom2dProp::ComputeTangent(aD1, aD2, aD3, 1.0e-7); - ASSERT_TRUE(aRes.IsDefined); - EXPECT_NEAR(aRes.Direction.X(), 3.0 / 5.0, Precision::Confusion()); - EXPECT_NEAR(aRes.Direction.Y(), 4.0 / 5.0, Precision::Confusion()); -} - -TEST(Geom2dPropTest, ComputeTangent_FallbackToD2) -{ - const gp_Vec2d aD1(0.0, 0.0); - const gp_Vec2d aD2(1.0, 0.0); - const gp_Vec2d aD3(0.0, 0.0); - - const Geom2dProp::TangentResult aRes = Geom2dProp::ComputeTangent(aD1, aD2, aD3, 1.0e-7); - ASSERT_TRUE(aRes.IsDefined); - EXPECT_NEAR(aRes.Direction.X(), 1.0, Precision::Confusion()); - EXPECT_NEAR(aRes.Direction.Y(), 0.0, Precision::Confusion()); -} - -TEST(Geom2dPropTest, ComputeTangent_FallbackToD3) -{ - const gp_Vec2d aD1(0.0, 0.0); - const gp_Vec2d aD2(0.0, 0.0); - const gp_Vec2d aD3(0.0, 5.0); - - const Geom2dProp::TangentResult aRes = Geom2dProp::ComputeTangent(aD1, aD2, aD3, 1.0e-7); - ASSERT_TRUE(aRes.IsDefined); - EXPECT_NEAR(aRes.Direction.X(), 0.0, Precision::Confusion()); - EXPECT_NEAR(aRes.Direction.Y(), 1.0, Precision::Confusion()); -} - -TEST(Geom2dPropTest, ComputeTangent_Undefined) -{ - const gp_Vec2d aZero(0.0, 0.0); - const Geom2dProp::TangentResult aRes = Geom2dProp::ComputeTangent(aZero, aZero, aZero, 1.0e-7); - EXPECT_FALSE(aRes.IsDefined); -} - -TEST(Geom2dPropTest, ComputeTangent_NegativeDirection) -{ - const gp_Vec2d aD1(-7.0, 0.0); - const gp_Vec2d aD2(0.0, 0.0); - const gp_Vec2d aD3(0.0, 0.0); - - const Geom2dProp::TangentResult aRes = Geom2dProp::ComputeTangent(aD1, aD2, aD3, 1.0e-7); - ASSERT_TRUE(aRes.IsDefined); - EXPECT_NEAR(aRes.Direction.X(), -1.0, Precision::Confusion()); - EXPECT_NEAR(aRes.Direction.Y(), 0.0, Precision::Confusion()); -} - -TEST(Geom2dPropTest, ComputeCurvature_Circle) -{ - // For a unit circle at param=0: D1=(0,1), D2=(-1,0) - const gp_Vec2d aD1(0.0, 1.0); - const gp_Vec2d aD2(-1.0, 0.0); - - const Geom2dProp::CurvatureResult aRes = - Geom2dProp::ComputeCurvature(aD1, aD2, Precision::Confusion()); - ASSERT_TRUE(aRes.IsDefined); - EXPECT_FALSE(aRes.IsInfinite); - EXPECT_NEAR(aRes.Value, 1.0, 1.0e-10); -} - -TEST(Geom2dPropTest, ComputeCurvature_LargerCircle) -{ - // For circle R=5 at param=0: D1=(0,5), D2=(-5,0) - const gp_Vec2d aD1(0.0, 5.0); - const gp_Vec2d aD2(-5.0, 0.0); - - const Geom2dProp::CurvatureResult aRes = - Geom2dProp::ComputeCurvature(aD1, aD2, Precision::Confusion()); - ASSERT_TRUE(aRes.IsDefined); - EXPECT_NEAR(aRes.Value, 1.0 / 5.0, 1.0e-10); -} - -TEST(Geom2dPropTest, ComputeCurvature_ZeroD1_IsInfinite) -{ - const gp_Vec2d aD1(0.0, 0.0); - const gp_Vec2d aD2(1.0, 0.0); - - const Geom2dProp::CurvatureResult aRes = - Geom2dProp::ComputeCurvature(aD1, aD2, Precision::Confusion()); - ASSERT_TRUE(aRes.IsDefined); - EXPECT_TRUE(aRes.IsInfinite); -} - -TEST(Geom2dPropTest, ComputeCurvature_ZeroD2_IsZero) -{ - const gp_Vec2d aD1(1.0, 0.0); - const gp_Vec2d aD2(0.0, 0.0); - - const Geom2dProp::CurvatureResult aRes = - Geom2dProp::ComputeCurvature(aD1, aD2, Precision::Confusion()); - ASSERT_TRUE(aRes.IsDefined); - EXPECT_FALSE(aRes.IsInfinite); - EXPECT_NEAR(aRes.Value, 0.0, Precision::Confusion()); -} - -TEST(Geom2dPropTest, ComputeCurvature_ParallelD1D2_IsZero) -{ - // D1 and D2 are parallel => cross product is 0 => curvature is 0 - const gp_Vec2d aD1(1.0, 0.0); - const gp_Vec2d aD2(3.0, 0.0); - - const Geom2dProp::CurvatureResult aRes = - Geom2dProp::ComputeCurvature(aD1, aD2, Precision::Confusion()); - ASSERT_TRUE(aRes.IsDefined); - EXPECT_NEAR(aRes.Value, 0.0, Precision::Confusion()); -} - -TEST(Geom2dPropTest, ComputeNormal_Circle) -{ - const gp_Vec2d aD1(0.0, 1.0); - const gp_Vec2d aD2(-1.0, 0.0); - - const Geom2dProp::NormalResult aRes = Geom2dProp::ComputeNormal(aD1, aD2, Precision::Confusion()); - ASSERT_TRUE(aRes.IsDefined); - // Normal perpendicular to tangent - EXPECT_NEAR(std::abs(aRes.Direction.X() * aD1.X() + aRes.Direction.Y() * aD1.Y()), - 0.0, - Precision::Confusion()); -} - -TEST(Geom2dPropTest, ComputeNormal_Line_Undefined) -{ - const gp_Vec2d aD1(1.0, 0.0); - const gp_Vec2d aD2(0.0, 0.0); - - const Geom2dProp::NormalResult aRes = Geom2dProp::ComputeNormal(aD1, aD2, Precision::Confusion()); - EXPECT_FALSE(aRes.IsDefined); -} - -TEST(Geom2dPropTest, ComputeNormal_Perpendicularity) -{ - // At an arbitrary point: D1=(1,1), D2=(0,2) - const gp_Vec2d aD1(1.0, 1.0); - const gp_Vec2d aD2(0.0, 2.0); - - const Geom2dProp::NormalResult aNorm = - Geom2dProp::ComputeNormal(aD1, aD2, Precision::Confusion()); - ASSERT_TRUE(aNorm.IsDefined); - - const Geom2dProp::TangentResult aTan = - Geom2dProp::ComputeTangent(aD1, aD2, gp_Vec2d(0, 0), Precision::Confusion()); - ASSERT_TRUE(aTan.IsDefined); - - const double aDot = - aTan.Direction.X() * aNorm.Direction.X() + aTan.Direction.Y() * aNorm.Direction.Y(); - EXPECT_NEAR(aDot, 0.0, Precision::Confusion()); -} - -TEST(Geom2dPropTest, ComputeCentreOfCurvature_Circle) -{ - const gp_Pnt2d aPnt(1.0, 0.0); - const gp_Vec2d aD1(0.0, 1.0); - const gp_Vec2d aD2(-1.0, 0.0); - - const Geom2dProp::CentreResult aRes = - Geom2dProp::ComputeCentreOfCurvature(aPnt, aD1, aD2, Precision::Confusion()); - ASSERT_TRUE(aRes.IsDefined); - EXPECT_NEAR(aRes.Centre.X(), 0.0, Precision::Confusion()); - EXPECT_NEAR(aRes.Centre.Y(), 0.0, Precision::Confusion()); -} - -TEST(Geom2dPropTest, ComputeCentreOfCurvature_Line_Undefined) -{ - const gp_Pnt2d aPnt(0.0, 0.0); - const gp_Vec2d aD1(1.0, 0.0); - const gp_Vec2d aD2(0.0, 0.0); - - const Geom2dProp::CentreResult aRes = - Geom2dProp::ComputeCentreOfCurvature(aPnt, aD1, aD2, Precision::Confusion()); - EXPECT_FALSE(aRes.IsDefined); -} - -TEST(Geom2dPropTest, ComputeCentreOfCurvature_DistanceEqualsRadius) -{ - // Circle R=3 centered at (0,0), point at (3,0) - const gp_Pnt2d aPnt(3.0, 0.0); - const gp_Vec2d aD1(0.0, 3.0); - const gp_Vec2d aD2(-3.0, 0.0); - - const Geom2dProp::CentreResult aRes = - Geom2dProp::ComputeCentreOfCurvature(aPnt, aD1, aD2, Precision::Confusion()); - ASSERT_TRUE(aRes.IsDefined); - const double aDist = aPnt.Distance(aRes.Centre); - EXPECT_NEAR(aDist, 3.0, Precision::Confusion()); -} - -// ============================================================================ -// Line tests via Geom2dProp_Curve dispatcher -// ============================================================================ - -class Geom2dProp_CurveLineTest : public ::testing::Test -{ -protected: - void SetUp() override - { - gp_Lin2d aLin(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)); - myLine = new Geom2d_Line(aLin); - myProp.emplace(myLine); - } - - occ::handle myLine; - std::optional myProp; -}; - -TEST_F(Geom2dProp_CurveLineTest, IsInitialized) -{ - EXPECT_EQ(myProp->GetType(), GeomAbs_Line); -} - -TEST_F(Geom2dProp_CurveLineTest, Tangent) -{ - const Geom2dProp::TangentResult aRes = myProp->Tangent(5.0, Precision::Confusion()); - ASSERT_TRUE(aRes.IsDefined); - EXPECT_NEAR(aRes.Direction.X(), 1.0, Precision::Confusion()); - EXPECT_NEAR(aRes.Direction.Y(), 0.0, Precision::Confusion()); -} - -TEST_F(Geom2dProp_CurveLineTest, TangentIsConstant) -{ - // Tangent should be the same at any parameter - for (double u = -100.0; u <= 100.0; u += 50.0) - { - const Geom2dProp::TangentResult aRes = myProp->Tangent(u, Precision::Confusion()); - ASSERT_TRUE(aRes.IsDefined); - EXPECT_NEAR(aRes.Direction.X(), 1.0, Precision::Confusion()); - EXPECT_NEAR(aRes.Direction.Y(), 0.0, Precision::Confusion()); - } -} - -TEST_F(Geom2dProp_CurveLineTest, CurvatureIsZero) -{ - const Geom2dProp::CurvatureResult aRes = myProp->Curvature(5.0, Precision::Confusion()); - ASSERT_TRUE(aRes.IsDefined); - EXPECT_FALSE(aRes.IsInfinite); - EXPECT_NEAR(aRes.Value, 0.0, Precision::Confusion()); -} - -TEST_F(Geom2dProp_CurveLineTest, NormalUndefined) -{ - const Geom2dProp::NormalResult aRes = myProp->Normal(5.0, Precision::Confusion()); - EXPECT_FALSE(aRes.IsDefined); -} - -TEST_F(Geom2dProp_CurveLineTest, CentreUndefined) -{ - const Geom2dProp::CentreResult aRes = myProp->CentreOfCurvature(5.0, Precision::Confusion()); - EXPECT_FALSE(aRes.IsDefined); -} - -TEST_F(Geom2dProp_CurveLineTest, NoExtrema) -{ - const Geom2dProp::CurveAnalysis aRes = myProp->FindCurvatureExtrema(); - EXPECT_TRUE(aRes.IsDone); - EXPECT_TRUE(aRes.Points.IsEmpty()); -} - -TEST_F(Geom2dProp_CurveLineTest, NoInflections) -{ - const Geom2dProp::CurveAnalysis aRes = myProp->FindInflections(); - EXPECT_TRUE(aRes.IsDone); - EXPECT_TRUE(aRes.Points.IsEmpty()); -} - -// Diagonal line -TEST(Geom2dProp_LineTest, DiagonalLine_TangentDirection) -{ - gp_Lin2d aLin(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 1.0)); - occ::handle aLine = new Geom2d_Line(aLin); - - Geom2dProp_Curve aProp(aLine); - - const Geom2dProp::TangentResult aTan = aProp.Tangent(0.0, Precision::Confusion()); - ASSERT_TRUE(aTan.IsDefined); - const double aSqrt2Inv = 1.0 / std::sqrt(2.0); - EXPECT_NEAR(aTan.Direction.X(), aSqrt2Inv, Precision::Confusion()); - EXPECT_NEAR(aTan.Direction.Y(), aSqrt2Inv, Precision::Confusion()); -} - -// ============================================================================ -// Circle tests via Geom2dProp_Curve dispatcher -// ============================================================================ - -class Geom2dProp_CurveCircleTest : public ::testing::Test -{ -protected: - void SetUp() override - { - gp_Circ2d aCirc(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 5.0); - myCircle = new Geom2d_Circle(aCirc); - myProp.emplace(myCircle); - } - - occ::handle myCircle; - std::optional myProp; -}; - -TEST_F(Geom2dProp_CurveCircleTest, IsInitialized) -{ - EXPECT_EQ(myProp->GetType(), GeomAbs_Circle); -} - -TEST_F(Geom2dProp_CurveCircleTest, Tangent) -{ - const Geom2dProp::TangentResult aRes = myProp->Tangent(0.0, Precision::Confusion()); - ASSERT_TRUE(aRes.IsDefined); - EXPECT_NEAR(aRes.Direction.X(), 0.0, Precision::Confusion()); - EXPECT_NEAR(aRes.Direction.Y(), 1.0, Precision::Confusion()); -} - -TEST_F(Geom2dProp_CurveCircleTest, TangentAtPiHalf) -{ - const Geom2dProp::TangentResult aRes = myProp->Tangent(M_PI / 2.0, Precision::Confusion()); - ASSERT_TRUE(aRes.IsDefined); - EXPECT_NEAR(aRes.Direction.X(), -1.0, Precision::Confusion()); - EXPECT_NEAR(aRes.Direction.Y(), 0.0, Precision::Confusion()); -} - -TEST_F(Geom2dProp_CurveCircleTest, TangentPerpendicularToRadius) -{ - // At any parameter, tangent should be perpendicular to the radius vector - for (double u = 0.0; u < 2.0 * M_PI; u += M_PI / 7.0) - { - const Geom2dProp::TangentResult aTan = myProp->Tangent(u, Precision::Confusion()); - ASSERT_TRUE(aTan.IsDefined); - // Radius direction at param u on circle centered at origin - const double aRadX = std::cos(u); - const double aRadY = std::sin(u); - const double aDot = aTan.Direction.X() * aRadX + aTan.Direction.Y() * aRadY; - EXPECT_NEAR(aDot, 0.0, 1.0e-10); - } -} - -TEST_F(Geom2dProp_CurveCircleTest, ConstantCurvature) -{ - for (double u = 0.0; u < 2.0 * M_PI; u += M_PI / 4.0) - { - const Geom2dProp::CurvatureResult aRes = myProp->Curvature(u, Precision::Confusion()); - ASSERT_TRUE(aRes.IsDefined); - EXPECT_NEAR(aRes.Value, 1.0 / 5.0, Precision::Confusion()); - } -} - -TEST_F(Geom2dProp_CurveCircleTest, Normal) -{ - const Geom2dProp::NormalResult aRes = myProp->Normal(0.0, Precision::Confusion()); - ASSERT_TRUE(aRes.IsDefined); - const Geom2dProp::TangentResult aTan = myProp->Tangent(0.0, Precision::Confusion()); - EXPECT_NEAR( - std::abs(aTan.Direction.X() * aRes.Direction.X() + aTan.Direction.Y() * aRes.Direction.Y()), - 0.0, - Precision::Confusion()); -} - -TEST_F(Geom2dProp_CurveCircleTest, NormalPointsTowardCenter) -{ - // At param=0, point=(5,0), normal should point toward center (0,0) => direction (-1,0) - const Geom2dProp::NormalResult aRes = myProp->Normal(0.0, Precision::Confusion()); - ASSERT_TRUE(aRes.IsDefined); - EXPECT_NEAR(aRes.Direction.X(), -1.0, Precision::Confusion()); - EXPECT_NEAR(aRes.Direction.Y(), 0.0, Precision::Confusion()); -} - -TEST_F(Geom2dProp_CurveCircleTest, CentreOfCurvature) -{ - const Geom2dProp::CentreResult aRes = myProp->CentreOfCurvature(0.0, Precision::Confusion()); - ASSERT_TRUE(aRes.IsDefined); - EXPECT_NEAR(aRes.Centre.X(), 0.0, Precision::Confusion()); - EXPECT_NEAR(aRes.Centre.Y(), 0.0, Precision::Confusion()); -} - -TEST_F(Geom2dProp_CurveCircleTest, CentreOfCurvature_ConstantAtAllParams) -{ - for (double u = 0.0; u < 2.0 * M_PI; u += M_PI / 5.0) - { - const Geom2dProp::CentreResult aRes = myProp->CentreOfCurvature(u, Precision::Confusion()); - ASSERT_TRUE(aRes.IsDefined); - EXPECT_NEAR(aRes.Centre.X(), 0.0, Precision::Confusion()); - EXPECT_NEAR(aRes.Centre.Y(), 0.0, Precision::Confusion()); - } -} - -TEST_F(Geom2dProp_CurveCircleTest, NoExtrema) -{ - const Geom2dProp::CurveAnalysis aRes = myProp->FindCurvatureExtrema(); - EXPECT_TRUE(aRes.IsDone); - EXPECT_TRUE(aRes.Points.IsEmpty()); -} - -TEST_F(Geom2dProp_CurveCircleTest, NoInflections) -{ - const Geom2dProp::CurveAnalysis aRes = myProp->FindInflections(); - EXPECT_TRUE(aRes.IsDone); - EXPECT_TRUE(aRes.Points.IsEmpty()); -} - -// Different radius circle -TEST(Geom2dProp_CircleTest, SmallRadius_HighCurvature) -{ - gp_Circ2d aCirc(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 0.1); - occ::handle aCircle = new Geom2d_Circle(aCirc); - - Geom2dProp_Curve aProp(aCircle); - - const Geom2dProp::CurvatureResult aCurv = aProp.Curvature(0.0, Precision::Confusion()); - ASSERT_TRUE(aCurv.IsDefined); - EXPECT_NEAR(aCurv.Value, 10.0, Precision::Confusion()); -} - -// Off-center circle -TEST(Geom2dProp_CircleTest, OffCenter_CentreOfCurvature) -{ - gp_Circ2d aCirc(gp_Ax2d(gp_Pnt2d(3.0, 7.0), gp_Dir2d(1.0, 0.0)), 4.0); - occ::handle aCircle = new Geom2d_Circle(aCirc); - - Geom2dProp_Curve aProp(aCircle); - - const Geom2dProp::CentreResult aCentre = aProp.CentreOfCurvature(1.0, Precision::Confusion()); - ASSERT_TRUE(aCentre.IsDefined); - EXPECT_NEAR(aCentre.Centre.X(), 3.0, Precision::Confusion()); - EXPECT_NEAR(aCentre.Centre.Y(), 7.0, Precision::Confusion()); -} - -// ============================================================================ -// Ellipse tests via Geom2dProp_Curve dispatcher -// ============================================================================ - -class Geom2dProp_CurveEllipseTest : public ::testing::Test -{ -protected: - void SetUp() override - { - gp_Elips2d anElips(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 10.0, 5.0); - myEllipse = new Geom2d_Ellipse(anElips); - myProp.emplace(myEllipse); - } - - occ::handle myEllipse; - std::optional myProp; -}; - -TEST_F(Geom2dProp_CurveEllipseTest, IsInitialized) -{ - EXPECT_EQ(myProp->GetType(), GeomAbs_Ellipse); -} - -TEST_F(Geom2dProp_CurveEllipseTest, TangentAtMajorVertex) -{ - // At U=0, point is on major axis endpoint, tangent should be vertical - const Geom2dProp::TangentResult aTan = myProp->Tangent(0.0, Precision::Confusion()); - ASSERT_TRUE(aTan.IsDefined); - EXPECT_NEAR(aTan.Direction.X(), 0.0, Precision::Confusion()); - EXPECT_NEAR(std::abs(aTan.Direction.Y()), 1.0, Precision::Confusion()); -} - -TEST_F(Geom2dProp_CurveEllipseTest, TangentAtMinorVertex) -{ - // At U=PI/2, point is on minor axis endpoint, tangent should be horizontal - const Geom2dProp::TangentResult aTan = myProp->Tangent(M_PI / 2.0, Precision::Confusion()); - ASSERT_TRUE(aTan.IsDefined); - EXPECT_NEAR(std::abs(aTan.Direction.X()), 1.0, Precision::Confusion()); - EXPECT_NEAR(aTan.Direction.Y(), 0.0, Precision::Confusion()); -} - -TEST_F(Geom2dProp_CurveEllipseTest, TangentPerpToNormal) -{ - for (double u = 0.0; u < 2.0 * M_PI; u += M_PI / 6.0) - { - const Geom2dProp::TangentResult aTan = myProp->Tangent(u, Precision::Confusion()); - const Geom2dProp::NormalResult aNorm = myProp->Normal(u, Precision::Confusion()); - ASSERT_TRUE(aTan.IsDefined); - ASSERT_TRUE(aNorm.IsDefined); - const double aDot = - aTan.Direction.X() * aNorm.Direction.X() + aTan.Direction.Y() * aNorm.Direction.Y(); - EXPECT_NEAR(aDot, 0.0, 1.0e-10); - } -} - -TEST_F(Geom2dProp_CurveEllipseTest, CurvatureAtMajorVertex) -{ - // At U=0 (major vertex): curvature = a/b^2 = 10/25 = 0.4 - const Geom2dProp::CurvatureResult aRes = myProp->Curvature(0.0, Precision::Confusion()); - ASSERT_TRUE(aRes.IsDefined); - EXPECT_NEAR(aRes.Value, 10.0 / 25.0, 1.0e-6); -} - -TEST_F(Geom2dProp_CurveEllipseTest, CurvatureAtMinorVertex) -{ - // At U=PI/2 (minor vertex): curvature = b/a^2 = 5/100 = 0.05 - const Geom2dProp::CurvatureResult aRes = myProp->Curvature(M_PI / 2.0, Precision::Confusion()); - ASSERT_TRUE(aRes.IsDefined); - EXPECT_NEAR(aRes.Value, 5.0 / 100.0, 1.0e-6); -} - -TEST_F(Geom2dProp_CurveEllipseTest, CurvatureAtPi) -{ - // At U=PI (opposite major vertex), curvature same as U=0 - const Geom2dProp::CurvatureResult aRes = myProp->Curvature(M_PI, Precision::Confusion()); - ASSERT_TRUE(aRes.IsDefined); - EXPECT_NEAR(aRes.Value, 10.0 / 25.0, 1.0e-6); -} - -TEST_F(Geom2dProp_CurveEllipseTest, CurvatureSymmetry) -{ - // Curvature at U and -U should be equal (ellipse is symmetric) - for (double u = 0.1; u < M_PI; u += 0.3) - { - const Geom2dProp::CurvatureResult aRes1 = myProp->Curvature(u, Precision::Confusion()); - const Geom2dProp::CurvatureResult aRes2 = myProp->Curvature(-u, Precision::Confusion()); - ASSERT_TRUE(aRes1.IsDefined); - ASSERT_TRUE(aRes2.IsDefined); - EXPECT_NEAR(aRes1.Value, aRes2.Value, 1.0e-10); - } -} - -TEST_F(Geom2dProp_CurveEllipseTest, CurvatureMaxAtMajorVertex) -{ - // |curvature| should be maximum at major vertex (U=0, PI) - const double aCurvMax = myProp->Curvature(0.0, Precision::Confusion()).Value; - for (double u = 0.1; u < 2.0 * M_PI; u += 0.2) - { - const Geom2dProp::CurvatureResult aCurv = myProp->Curvature(u, Precision::Confusion()); - ASSERT_TRUE(aCurv.IsDefined); - EXPECT_LE(std::abs(aCurv.Value), std::abs(aCurvMax) + 1.0e-10); - } -} - -TEST_F(Geom2dProp_CurveEllipseTest, NormalAtMajorVertex) -{ - const Geom2dProp::NormalResult aRes = myProp->Normal(0.0, Precision::Confusion()); - ASSERT_TRUE(aRes.IsDefined); - // At (10,0) on x-axis aligned ellipse, normal should point toward center: (-1,0) - EXPECT_NEAR(aRes.Direction.X(), -1.0, Precision::Confusion()); - EXPECT_NEAR(aRes.Direction.Y(), 0.0, Precision::Confusion()); -} - -TEST_F(Geom2dProp_CurveEllipseTest, CentreOfCurvatureAtMajorVertex) -{ - const Geom2dProp::CentreResult aRes = myProp->CentreOfCurvature(0.0, Precision::Confusion()); - ASSERT_TRUE(aRes.IsDefined); - // Radius of curvature at major vertex = b^2/a = 25/10 = 2.5 - // Centre should be at (10 - 2.5, 0) = (7.5, 0) - EXPECT_NEAR(aRes.Centre.X(), 7.5, 1.0e-6); - EXPECT_NEAR(aRes.Centre.Y(), 0.0, 1.0e-6); -} - -TEST_F(Geom2dProp_CurveEllipseTest, CentreOfCurvatureAtMinorVertex) -{ - const Geom2dProp::CentreResult aRes = - myProp->CentreOfCurvature(M_PI / 2.0, Precision::Confusion()); - ASSERT_TRUE(aRes.IsDefined); - // Radius of curvature at minor vertex = a^2/b = 100/5 = 20 - // Centre should be at (0, 5 - 20) = (0, -15) - EXPECT_NEAR(aRes.Centre.X(), 0.0, 1.0e-6); - EXPECT_NEAR(aRes.Centre.Y(), -15.0, 1.0e-6); -} - -TEST_F(Geom2dProp_CurveEllipseTest, FindCurvatureExtrema) -{ - const Geom2dProp::CurveAnalysis aRes = myProp->FindCurvatureExtrema(); - ASSERT_TRUE(aRes.IsDone); - EXPECT_EQ(aRes.Points.Length(), 4); - - if (aRes.Points.Length() >= 4) - { - EXPECT_NEAR(aRes.Points.Value(0).Parameter, 0.0, 1.0e-10); - EXPECT_EQ(aRes.Points.Value(0).Type, Geom2dProp::CIType::MinCurvature); - - EXPECT_NEAR(aRes.Points.Value(1).Parameter, M_PI / 2.0, 1.0e-10); - EXPECT_EQ(aRes.Points.Value(1).Type, Geom2dProp::CIType::MaxCurvature); - - EXPECT_NEAR(aRes.Points.Value(2).Parameter, M_PI, 1.0e-10); - EXPECT_EQ(aRes.Points.Value(2).Type, Geom2dProp::CIType::MinCurvature); - - EXPECT_NEAR(aRes.Points.Value(3).Parameter, 3.0 * M_PI / 2.0, 1.0e-10); - EXPECT_EQ(aRes.Points.Value(3).Type, Geom2dProp::CIType::MaxCurvature); - } -} - -TEST_F(Geom2dProp_CurveEllipseTest, NoInflections) -{ - const Geom2dProp::CurveAnalysis aRes = myProp->FindInflections(); - EXPECT_TRUE(aRes.IsDone); - EXPECT_TRUE(aRes.Points.IsEmpty()); -} - -// Ellipse with equal semi-axes is a circle -TEST(Geom2dProp_EllipseTest, EqualSemiAxes_BehavesLikeCircle) -{ - gp_Elips2d anElips(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 5.0, 5.0); - occ::handle anEllipse = new Geom2d_Ellipse(anElips); - - Geom2dProp_Curve aProp(anEllipse); - - // Curvature should be constant = 1/R = 1/5 - for (double u = 0.0; u < 2.0 * M_PI; u += M_PI / 4.0) - { - const Geom2dProp::CurvatureResult aCurv = aProp.Curvature(u, Precision::Confusion()); - ASSERT_TRUE(aCurv.IsDefined); - EXPECT_NEAR(aCurv.Value, 1.0 / 5.0, 1.0e-10); - } -} - -// ============================================================================ -// Hyperbola tests -// ============================================================================ - -class Geom2dProp_CurveHyperbolaTest : public ::testing::Test -{ -protected: - void SetUp() override - { - gp_Hypr2d aHypr(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 5.0, 3.0); - myHyperbola = new Geom2d_Hyperbola(aHypr); - myProp.emplace(myHyperbola); - } - - occ::handle myHyperbola; - std::optional myProp; -}; - -TEST_F(Geom2dProp_CurveHyperbolaTest, IsInitialized) -{ - EXPECT_EQ(myProp->GetType(), GeomAbs_Hyperbola); -} - -TEST_F(Geom2dProp_CurveHyperbolaTest, TangentAtVertex) -{ - const Geom2dProp::TangentResult aTan = myProp->Tangent(0.0, Precision::Confusion()); - ASSERT_TRUE(aTan.IsDefined); - // At vertex of hyperbola (t=0), tangent is vertical - EXPECT_NEAR(aTan.Direction.X(), 0.0, Precision::Confusion()); - EXPECT_NEAR(std::abs(aTan.Direction.Y()), 1.0, Precision::Confusion()); -} - -TEST_F(Geom2dProp_CurveHyperbolaTest, CurvatureAtVertex) -{ - // At vertex (t=0): curvature = b^2/a^2 * 1/a * a = b^2/(a * a) ... actually K = b^2/a - // For hyperbola x=a*cosh(t), y=b*sinh(t): - // K(0) = b^2/(a^2 * (b^2/a^2)^(3/2)) ... Just verify it's defined and positive. - const Geom2dProp::CurvatureResult aCurv = myProp->Curvature(0.0, Precision::Confusion()); - ASSERT_TRUE(aCurv.IsDefined); - EXPECT_GT(aCurv.Value, 0.0); -} - -TEST_F(Geom2dProp_CurveHyperbolaTest, CurvatureDecreasesFromVertex) -{ - // Curvature should be maximum at vertex and decrease away from it - const double aCurvAtVertex = std::abs(myProp->Curvature(0.0, Precision::Confusion()).Value); - for (double u = 0.5; u < 3.0; u += 0.5) - { - const Geom2dProp::CurvatureResult aCurv = myProp->Curvature(u, Precision::Confusion()); - ASSERT_TRUE(aCurv.IsDefined); - EXPECT_LT(std::abs(aCurv.Value), aCurvAtVertex + 1.0e-10); - } -} - -TEST_F(Geom2dProp_CurveHyperbolaTest, NormalAtVertex) -{ - const Geom2dProp::NormalResult aNorm = myProp->Normal(0.0, Precision::Confusion()); - ASSERT_TRUE(aNorm.IsDefined); - // Normal should be perpendicular to tangent - const Geom2dProp::TangentResult aTan = myProp->Tangent(0.0, Precision::Confusion()); - const double aDot = - aTan.Direction.X() * aNorm.Direction.X() + aTan.Direction.Y() * aNorm.Direction.Y(); - EXPECT_NEAR(aDot, 0.0, 1.0e-10); -} - -TEST_F(Geom2dProp_CurveHyperbolaTest, CentreOfCurvatureAtVertex) -{ - const Geom2dProp::CentreResult aCentre = myProp->CentreOfCurvature(0.0, Precision::Confusion()); - ASSERT_TRUE(aCentre.IsDefined); -} - -TEST_F(Geom2dProp_CurveHyperbolaTest, CurvatureExtremaAtVertex) -{ - const Geom2dProp::CurveAnalysis aExtrema = myProp->FindCurvatureExtrema(); - ASSERT_TRUE(aExtrema.IsDone); - EXPECT_EQ(aExtrema.Points.Length(), 1); - if (!aExtrema.Points.IsEmpty()) - { - EXPECT_NEAR(aExtrema.Points.Value(0).Parameter, 0.0, 1.0e-10); - EXPECT_EQ(aExtrema.Points.Value(0).Type, Geom2dProp::CIType::MinCurvature); - } -} - -TEST_F(Geom2dProp_CurveHyperbolaTest, NoInflections) -{ - const Geom2dProp::CurveAnalysis aInfl = myProp->FindInflections(); - EXPECT_TRUE(aInfl.IsDone); - EXPECT_TRUE(aInfl.Points.IsEmpty()); -} - -// ============================================================================ -// Parabola tests -// ============================================================================ - -class Geom2dProp_CurveParabolaTest : public ::testing::Test -{ -protected: - void SetUp() override - { - // Focal parameter p=2 => parabola y^2 = 4px = 8x - gp_Parab2d aParab(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 2.0); - myParabola = new Geom2d_Parabola(aParab); - myProp.emplace(myParabola); - } - - occ::handle myParabola; - std::optional myProp; -}; - -TEST_F(Geom2dProp_CurveParabolaTest, IsInitialized) -{ - EXPECT_EQ(myProp->GetType(), GeomAbs_Parabola); -} - -TEST_F(Geom2dProp_CurveParabolaTest, TangentAtVertex) -{ - const Geom2dProp::TangentResult aTan = myProp->Tangent(0.0, Precision::Confusion()); - ASSERT_TRUE(aTan.IsDefined); - // At vertex, tangent is vertical - EXPECT_NEAR(aTan.Direction.X(), 0.0, Precision::Confusion()); - EXPECT_NEAR(std::abs(aTan.Direction.Y()), 1.0, Precision::Confusion()); -} - -TEST_F(Geom2dProp_CurveParabolaTest, CurvatureAtVertex) -{ - // At vertex: curvature = 1/(2*focal_parameter) = 1/4 = 0.25 - const Geom2dProp::CurvatureResult aCurv = myProp->Curvature(0.0, Precision::Confusion()); - ASSERT_TRUE(aCurv.IsDefined); - EXPECT_GT(aCurv.Value, 0.0); -} - -TEST_F(Geom2dProp_CurveParabolaTest, CurvatureDecreasesFromVertex) -{ - const double aCurvAtVertex = std::abs(myProp->Curvature(0.0, Precision::Confusion()).Value); - for (double u = 1.0; u <= 5.0; u += 1.0) - { - const Geom2dProp::CurvatureResult aCurv = myProp->Curvature(u, Precision::Confusion()); - ASSERT_TRUE(aCurv.IsDefined); - EXPECT_LT(std::abs(aCurv.Value), aCurvAtVertex); - } -} - -TEST_F(Geom2dProp_CurveParabolaTest, CurvatureSymmetric) -{ - // Curvature at U and -U should be equal - for (double u = 0.5; u <= 5.0; u += 0.5) - { - const double aCurv1 = myProp->Curvature(u, Precision::Confusion()).Value; - const double aCurv2 = myProp->Curvature(-u, Precision::Confusion()).Value; - EXPECT_NEAR(aCurv1, aCurv2, 1.0e-10); - } -} - -TEST_F(Geom2dProp_CurveParabolaTest, NormalAtVertex) -{ - const Geom2dProp::NormalResult aNorm = myProp->Normal(0.0, Precision::Confusion()); - ASSERT_TRUE(aNorm.IsDefined); - const Geom2dProp::TangentResult aTan = myProp->Tangent(0.0, Precision::Confusion()); - const double aDot = - aTan.Direction.X() * aNorm.Direction.X() + aTan.Direction.Y() * aNorm.Direction.Y(); - EXPECT_NEAR(aDot, 0.0, 1.0e-10); -} - -TEST_F(Geom2dProp_CurveParabolaTest, CentreOfCurvatureAtVertex) -{ - const Geom2dProp::CentreResult aCentre = myProp->CentreOfCurvature(0.0, Precision::Confusion()); - ASSERT_TRUE(aCentre.IsDefined); -} - -TEST_F(Geom2dProp_CurveParabolaTest, CurvatureExtremaAtVertex) -{ - const Geom2dProp::CurveAnalysis aExtrema = myProp->FindCurvatureExtrema(); - ASSERT_TRUE(aExtrema.IsDone); - EXPECT_EQ(aExtrema.Points.Length(), 1); - if (!aExtrema.Points.IsEmpty()) - { - EXPECT_NEAR(aExtrema.Points.Value(0).Parameter, 0.0, 1.0e-10); - EXPECT_EQ(aExtrema.Points.Value(0).Type, Geom2dProp::CIType::MinCurvature); - } -} - -TEST_F(Geom2dProp_CurveParabolaTest, NoInflections) -{ - const Geom2dProp::CurveAnalysis aInfl = myProp->FindInflections(); - EXPECT_TRUE(aInfl.IsDone); - EXPECT_TRUE(aInfl.Points.IsEmpty()); -} - -// ============================================================================ -// Bezier curve tests -// ============================================================================ - -class Geom2dProp_CurveBezierTest : public ::testing::Test -{ -protected: - void SetUp() override - { - // S-shaped cubic Bezier: (0,0), (1,2), (3,-2), (4,0) - NCollection_Array1 aPoles(1, 4); - aPoles(1) = gp_Pnt2d(0.0, 0.0); - aPoles(2) = gp_Pnt2d(1.0, 2.0); - aPoles(3) = gp_Pnt2d(3.0, -2.0); - aPoles(4) = gp_Pnt2d(4.0, 0.0); - myBezier = new Geom2d_BezierCurve(aPoles); - myProp.emplace(myBezier); - } - - occ::handle myBezier; - std::optional myProp; -}; - -TEST_F(Geom2dProp_CurveBezierTest, IsInitialized) -{ - EXPECT_EQ(myProp->GetType(), GeomAbs_BezierCurve); -} - -TEST_F(Geom2dProp_CurveBezierTest, TangentAtStart) -{ - const Geom2dProp::TangentResult aTan = myProp->Tangent(0.0, Precision::Confusion()); - ASSERT_TRUE(aTan.IsDefined); - // Tangent at start should point toward second control point: (1,2) - // Direction should be proportional to (1,2), normalized - const double aLen = std::sqrt(1.0 + 4.0); - EXPECT_NEAR(aTan.Direction.X(), 1.0 / aLen, 1.0e-6); - EXPECT_NEAR(aTan.Direction.Y(), 2.0 / aLen, 1.0e-6); -} - -TEST_F(Geom2dProp_CurveBezierTest, TangentAtEnd) -{ - const Geom2dProp::TangentResult aTan = myProp->Tangent(1.0, Precision::Confusion()); - ASSERT_TRUE(aTan.IsDefined); - // Tangent at end should point from third control point to fourth: (4,0)-(3,-2) = (1,2) - const double aLen = std::sqrt(1.0 + 4.0); - EXPECT_NEAR(aTan.Direction.X(), 1.0 / aLen, 1.0e-6); - EXPECT_NEAR(aTan.Direction.Y(), 2.0 / aLen, 1.0e-6); -} - -TEST_F(Geom2dProp_CurveBezierTest, CurvatureAtMultiplePoints) -{ - for (double u = 0.0; u <= 1.0; u += 0.1) - { - const Geom2dProp::CurvatureResult aCurv = myProp->Curvature(u, Precision::Confusion()); - EXPECT_TRUE(aCurv.IsDefined); - EXPECT_FALSE(aCurv.IsInfinite); - } -} - -TEST_F(Geom2dProp_CurveBezierTest, NormalPerpendicularToTangent) -{ - for (double u = 0.1; u < 1.0; u += 0.2) - { - const Geom2dProp::TangentResult aTan = myProp->Tangent(u, Precision::Confusion()); - const Geom2dProp::NormalResult aNorm = myProp->Normal(u, Precision::Confusion()); - if (aTan.IsDefined && aNorm.IsDefined) - { - const double aDot = - aTan.Direction.X() * aNorm.Direction.X() + aTan.Direction.Y() * aNorm.Direction.Y(); - EXPECT_NEAR(aDot, 0.0, 1.0e-10); - } - } -} - -TEST_F(Geom2dProp_CurveBezierTest, CentreOfCurvature_DistanceIsRadiusOfCurvature) -{ - const double u = 0.3; - const Geom2dProp::CurvatureResult aCurv = myProp->Curvature(u, Precision::Confusion()); - const Geom2dProp::CentreResult aCentre = myProp->CentreOfCurvature(u, Precision::Confusion()); - if (aCurv.IsDefined && aCentre.IsDefined && !aCurv.IsInfinite && std::abs(aCurv.Value) > 1.0e-10) - { - gp_Pnt2d aPnt; - gp_Vec2d aD1; - myBezier->D1(u, aPnt, aD1); - const double aDist = aPnt.Distance(aCentre.Centre); - EXPECT_NEAR(aDist, 1.0 / std::abs(aCurv.Value), 1.0e-6); - } -} - -TEST_F(Geom2dProp_CurveBezierTest, InflectionPoints) -{ - // S-shaped curve should have inflection point(s) near the middle - const Geom2dProp::CurveAnalysis aInflections = myProp->FindInflections(); - EXPECT_TRUE(aInflections.IsDone); - EXPECT_GE(aInflections.Points.Length(), 1); - if (!aInflections.Points.IsEmpty()) - { - for (int i = 0; i < aInflections.Points.Length(); ++i) - { - EXPECT_EQ(aInflections.Points.Value(i).Type, Geom2dProp::CIType::Inflection); - // Should be within the parameter range [0, 1] - EXPECT_GE(aInflections.Points.Value(i).Parameter, 0.0 - 1.0e-6); - EXPECT_LE(aInflections.Points.Value(i).Parameter, 1.0 + 1.0e-6); - } - } -} - -TEST_F(Geom2dProp_CurveBezierTest, CurvatureExtrema) -{ - const Geom2dProp::CurveAnalysis aExtrema = myProp->FindCurvatureExtrema(); - EXPECT_TRUE(aExtrema.IsDone); - // S-shaped cubic should have curvature extrema - for (int i = 0; i < aExtrema.Points.Length(); ++i) - { - EXPECT_TRUE(aExtrema.Points.Value(i).Type == Geom2dProp::CIType::MinCurvature - || aExtrema.Points.Value(i).Type == Geom2dProp::CIType::MaxCurvature); - EXPECT_GE(aExtrema.Points.Value(i).Parameter, 0.0 - 1.0e-6); - EXPECT_LE(aExtrema.Points.Value(i).Parameter, 1.0 + 1.0e-6); - } -} - -// Straight-line Bezier -TEST(Geom2dProp_BezierTest, StraightLine_ZeroCurvature) -{ - NCollection_Array1 aPoles(1, 3); - aPoles(1) = gp_Pnt2d(0.0, 0.0); - aPoles(2) = gp_Pnt2d(2.0, 0.0); - aPoles(3) = gp_Pnt2d(4.0, 0.0); - occ::handle aBezier = new Geom2d_BezierCurve(aPoles); - - Geom2dProp_Curve aProp(aBezier); - - const Geom2dProp::CurvatureResult aCurv = aProp.Curvature(0.5, Precision::Confusion()); - ASSERT_TRUE(aCurv.IsDefined); - EXPECT_NEAR(aCurv.Value, 0.0, Precision::Confusion()); -} - -// Quadratic Bezier (arc-like) -TEST(Geom2dProp_BezierTest, QuadraticBezier_Properties) -{ - NCollection_Array1 aPoles(1, 3); - aPoles(1) = gp_Pnt2d(0.0, 0.0); - aPoles(2) = gp_Pnt2d(1.0, 2.0); - aPoles(3) = gp_Pnt2d(2.0, 0.0); - occ::handle aBezier = new Geom2d_BezierCurve(aPoles); - - Geom2dProp_Curve aProp(aBezier); - - // Symmetric parabolic arc: curvature should be max at midpoint - const double aCurvMid = std::abs(aProp.Curvature(0.5, Precision::Confusion()).Value); - EXPECT_GT(aCurvMid, 0.0); - - // No inflections for a parabolic arc - const Geom2dProp::CurveAnalysis aInfl = aProp.FindInflections(); - EXPECT_TRUE(aInfl.IsDone); - EXPECT_TRUE(aInfl.Points.IsEmpty()); -} - -// ============================================================================ -// BSpline curve tests -// ============================================================================ - -class Geom2dProp_CurveBSplineTest : public ::testing::Test -{ -protected: - void SetUp() override - { - NCollection_Array1 aPoles(1, 4); - aPoles(1) = gp_Pnt2d(0.0, 0.0); - aPoles(2) = gp_Pnt2d(1.0, 2.0); - aPoles(3) = gp_Pnt2d(3.0, 2.0); - aPoles(4) = gp_Pnt2d(4.0, 0.0); - - NCollection_Array1 aKnots(1, 3); - aKnots(1) = 0.0; - aKnots(2) = 0.5; - aKnots(3) = 1.0; - - NCollection_Array1 aMults(1, 3); - aMults(1) = 3; - aMults(2) = 1; - aMults(3) = 3; - - myBSpline = new Geom2d_BSplineCurve(aPoles, aKnots, aMults, 2); - myProp.emplace(myBSpline); - } - - occ::handle myBSpline; - std::optional myProp; -}; - -TEST_F(Geom2dProp_CurveBSplineTest, IsInitialized) -{ - EXPECT_EQ(myProp->GetType(), GeomAbs_BSplineCurve); -} - -TEST_F(Geom2dProp_CurveBSplineTest, TangentDefined) -{ - for (double u = 0.0; u <= 1.0; u += 0.2) - { - const Geom2dProp::TangentResult aTan = myProp->Tangent(u, Precision::Confusion()); - EXPECT_TRUE(aTan.IsDefined); - } -} - -TEST_F(Geom2dProp_CurveBSplineTest, CurvatureDefined) -{ - for (double u = 0.0; u <= 1.0; u += 0.2) - { - const Geom2dProp::CurvatureResult aCurv = myProp->Curvature(u, Precision::Confusion()); - EXPECT_TRUE(aCurv.IsDefined); - EXPECT_FALSE(aCurv.IsInfinite); - } -} - -TEST_F(Geom2dProp_CurveBSplineTest, NormalDefined) -{ - // B-spline has non-zero curvature, so normal should be defined in the middle - const Geom2dProp::NormalResult aNorm = myProp->Normal(0.3, Precision::Confusion()); - EXPECT_TRUE(aNorm.IsDefined); -} - -TEST_F(Geom2dProp_CurveBSplineTest, CentreOfCurvatureDefined) -{ - const Geom2dProp::CentreResult aCentre = myProp->CentreOfCurvature(0.3, Precision::Confusion()); - EXPECT_TRUE(aCentre.IsDefined); -} - -TEST_F(Geom2dProp_CurveBSplineTest, CurvatureExtrema) -{ - const Geom2dProp::CurveAnalysis aExtrema = myProp->FindCurvatureExtrema(); - EXPECT_TRUE(aExtrema.IsDone); - // Verify all extrema parameters are within [0, 1] - for (int i = 0; i < aExtrema.Points.Length(); ++i) - { - EXPECT_GE(aExtrema.Points.Value(i).Parameter, 0.0 - 1.0e-6); - EXPECT_LE(aExtrema.Points.Value(i).Parameter, 1.0 + 1.0e-6); - } -} - -TEST_F(Geom2dProp_CurveBSplineTest, InflectionPoints) -{ - const Geom2dProp::CurveAnalysis aInfl = myProp->FindInflections(); - EXPECT_TRUE(aInfl.IsDone); - for (int i = 0; i < aInfl.Points.Length(); ++i) - { - EXPECT_EQ(aInfl.Points.Value(i).Type, Geom2dProp::CIType::Inflection); - EXPECT_GE(aInfl.Points.Value(i).Parameter, 0.0 - 1.0e-6); - EXPECT_LE(aInfl.Points.Value(i).Parameter, 1.0 + 1.0e-6); - } -} - -// B-spline with lower continuity (C1) -TEST(Geom2dProp_BSplineTest, LowContinuity_C1) -{ - NCollection_Array1 aPoles(1, 5); - aPoles(1) = gp_Pnt2d(0.0, 0.0); - aPoles(2) = gp_Pnt2d(1.0, 3.0); - aPoles(3) = gp_Pnt2d(2.0, 1.0); - aPoles(4) = gp_Pnt2d(3.0, 3.0); - aPoles(5) = gp_Pnt2d(4.0, 0.0); - - NCollection_Array1 aKnots(1, 4); - aKnots(1) = 0.0; - aKnots(2) = 0.33; - aKnots(3) = 0.66; - aKnots(4) = 1.0; - - NCollection_Array1 aMults(1, 4); - aMults(1) = 3; - aMults(2) = 1; - aMults(3) = 1; - aMults(4) = 3; - - occ::handle aBSpline = new Geom2d_BSplineCurve(aPoles, aKnots, aMults, 2); - - Geom2dProp_Curve aProp(aBSpline); - - // Should work with C3 interval subdivision - const Geom2dProp::CurveAnalysis aExtrema = aProp.FindCurvatureExtrema(); - EXPECT_TRUE(aExtrema.IsDone); - - const Geom2dProp::CurveAnalysis aInfl = aProp.FindInflections(); - EXPECT_TRUE(aInfl.IsDone); -} - -// ============================================================================ -// Offset curve tests -// ============================================================================ - -TEST(Geom2dProp_OffsetCurveTest, IsInitialized) -{ - gp_Circ2d aCirc(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 5.0); - occ::handle aCircle = new Geom2d_Circle(aCirc); - occ::handle anOffset = new Geom2d_OffsetCurve(aCircle, 2.0); - - Geom2dProp_Curve aProp(anOffset); - EXPECT_EQ(aProp.GetType(), GeomAbs_OffsetCurve); -} - -TEST(Geom2dProp_OffsetCurveTest, OffsetCircle_ConstantCurvature) -{ - // Offset of circle R=5 by +2 gives circle R=7, curvature=1/7 - gp_Circ2d aCirc(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 5.0); - occ::handle aCircle = new Geom2d_Circle(aCirc); - occ::handle anOffset = new Geom2d_OffsetCurve(aCircle, 2.0); - - Geom2dProp_Curve aProp(anOffset); - - for (double u = 0.0; u < 2.0 * M_PI; u += M_PI / 4.0) - { - const Geom2dProp::CurvatureResult aCurv = aProp.Curvature(u, Precision::Confusion()); - ASSERT_TRUE(aCurv.IsDefined); - EXPECT_NEAR(std::abs(aCurv.Value), 1.0 / 7.0, 1.0e-6); - } -} - -TEST(Geom2dProp_OffsetCurveTest, TangentAndNormalDefined) -{ - gp_Circ2d aCirc(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 5.0); - occ::handle aCircle = new Geom2d_Circle(aCirc); - occ::handle anOffset = new Geom2d_OffsetCurve(aCircle, 2.0); - - Geom2dProp_Curve aProp(anOffset); - - const Geom2dProp::TangentResult aTan = aProp.Tangent(0.5, Precision::Confusion()); - EXPECT_TRUE(aTan.IsDefined); - - const Geom2dProp::NormalResult aNorm = aProp.Normal(0.5, Precision::Confusion()); - EXPECT_TRUE(aNorm.IsDefined); - - // Perpendicularity - if (aTan.IsDefined && aNorm.IsDefined) - { - const double aDot = - aTan.Direction.X() * aNorm.Direction.X() + aTan.Direction.Y() * aNorm.Direction.Y(); - EXPECT_NEAR(aDot, 0.0, 1.0e-10); - } -} - -TEST(Geom2dProp_OffsetCurveTest, OffsetEllipse_ExtremaAndInflections) -{ - gp_Elips2d anElips(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 10.0, 5.0); - occ::handle anEllipse = new Geom2d_Ellipse(anElips); - occ::handle anOffset = new Geom2d_OffsetCurve(anEllipse, 1.0); - - Geom2dProp_Curve aProp(anOffset); - - const Geom2dProp::CurveAnalysis aExtrema = aProp.FindCurvatureExtrema(); - EXPECT_TRUE(aExtrema.IsDone); - - const Geom2dProp::CurveAnalysis aInfl = aProp.FindInflections(); - EXPECT_TRUE(aInfl.IsDone); -} - -// ============================================================================ -// TrimmedCurve tests -// ============================================================================ - -TEST(Geom2dProp_TrimmedCurveTest, UnwrapsToCircle) -{ - gp_Circ2d aCirc(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 5.0); - occ::handle aCircle = new Geom2d_Circle(aCirc); - occ::handle aTrimmed = new Geom2d_TrimmedCurve(aCircle, 0.0, M_PI); - - Geom2dProp_Curve aProp(aTrimmed); - EXPECT_EQ(aProp.GetType(), GeomAbs_Circle); - - const Geom2dProp::CurvatureResult aCurv = aProp.Curvature(0.5, Precision::Confusion()); - ASSERT_TRUE(aCurv.IsDefined); - EXPECT_NEAR(aCurv.Value, 1.0 / 5.0, Precision::Confusion()); -} - -TEST(Geom2dProp_TrimmedCurveTest, UnwrapsToEllipse) -{ - gp_Elips2d anElips(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 10.0, 5.0); - occ::handle anEllipse = new Geom2d_Ellipse(anElips); - occ::handle aTrimmed = new Geom2d_TrimmedCurve(anEllipse, 0.0, M_PI); - - Geom2dProp_Curve aProp(aTrimmed); - EXPECT_EQ(aProp.GetType(), GeomAbs_Ellipse); -} - -TEST(Geom2dProp_TrimmedCurveTest, NestedTrimmedCurve) -{ - gp_Circ2d aCirc(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 3.0); - occ::handle aCircle = new Geom2d_Circle(aCirc); - occ::handle aTrimmed1 = new Geom2d_TrimmedCurve(aCircle, 0.0, M_PI); - occ::handle aTrimmed2 = new Geom2d_TrimmedCurve(aTrimmed1, 0.1, 1.0); - - Geom2dProp_Curve aProp(aTrimmed2); - EXPECT_EQ(aProp.GetType(), GeomAbs_Circle); - - const Geom2dProp::CurvatureResult aCurv = aProp.Curvature(0.5, Precision::Confusion()); - ASSERT_TRUE(aCurv.IsDefined); - EXPECT_NEAR(aCurv.Value, 1.0 / 3.0, Precision::Confusion()); -} - -// ============================================================================ -// Null / uninitialized tests -// ============================================================================ - -TEST(Geom2dProp_CurveTest, NullHandle_NotInitialized) -{ - occ::handle aNullCurve; - Geom2dProp_Curve aProp(aNullCurve); - - const Geom2dProp::TangentResult aTan = aProp.Tangent(0.0, 1.0e-7); - EXPECT_FALSE(aTan.IsDefined); - - const Geom2dProp::CurvatureResult aCurv = aProp.Curvature(0.0, 1.0e-7); - EXPECT_FALSE(aCurv.IsDefined); - - const Geom2dProp::NormalResult aNorm = aProp.Normal(0.0, 1.0e-7); - EXPECT_FALSE(aNorm.IsDefined); - - const Geom2dProp::CentreResult aCentre = aProp.CentreOfCurvature(0.0, 1.0e-7); - EXPECT_FALSE(aCentre.IsDefined); - - const Geom2dProp::CurveAnalysis aExtrema = aProp.FindCurvatureExtrema(); - EXPECT_FALSE(aExtrema.IsDone); - - const Geom2dProp::CurveAnalysis aInfl = aProp.FindInflections(); - EXPECT_FALSE(aInfl.IsDone); -} - -TEST(Geom2dProp_CurveTest, DifferentTypes) -{ - // Circle - gp_Circ2d aCirc(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 5.0); - occ::handle aCircle = new Geom2d_Circle(aCirc); - Geom2dProp_Curve aPropCircle(aCircle); - EXPECT_EQ(aPropCircle.GetType(), GeomAbs_Circle); - - // Line - gp_Lin2d aLin(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)); - occ::handle aLine = new Geom2d_Line(aLin); - Geom2dProp_Curve aPropLine(aLine); - EXPECT_EQ(aPropLine.GetType(), GeomAbs_Line); - EXPECT_NEAR(aPropLine.Curvature(0.0, Precision::Confusion()).Value, 0.0, Precision::Confusion()); -} - -// ============================================================================ -// Initialize from adaptor tests -// ============================================================================ - -TEST(Geom2dProp_AdaptorTest, InitFromGeom2dAdaptor) -{ - gp_Circ2d aCirc(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 5.0); - occ::handle aCircle = new Geom2d_Circle(aCirc); - Geom2dAdaptor_Curve anAdaptor(aCircle); - - Geom2dProp_Curve aProp(anAdaptor); - EXPECT_EQ(aProp.GetType(), GeomAbs_Circle); - - const Geom2dProp::CurvatureResult aCurv = aProp.Curvature(0.0, Precision::Confusion()); - ASSERT_TRUE(aCurv.IsDefined); - EXPECT_NEAR(aCurv.Value, 1.0 / 5.0, Precision::Confusion()); -} - -TEST(Geom2dProp_AdaptorTest, InitFromGeom2dAdaptor_Ellipse) -{ - gp_Elips2d anElips(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 8.0, 3.0); - occ::handle anEllipse = new Geom2d_Ellipse(anElips); - Geom2dAdaptor_Curve anAdaptor(anEllipse); - - Geom2dProp_Curve aProp(anAdaptor); - EXPECT_EQ(aProp.GetType(), GeomAbs_Ellipse); - - // Curvature at major vertex: a/b^2 = 8/9 - const Geom2dProp::CurvatureResult aCurv = aProp.Curvature(0.0, Precision::Confusion()); - ASSERT_TRUE(aCurv.IsDefined); - EXPECT_NEAR(aCurv.Value, 8.0 / 9.0, 1.0e-6); -} - -TEST(Geom2dProp_AdaptorTest, InitFromGeom2dAdaptor_BSpline) -{ - NCollection_Array1 aPoles(1, 4); - aPoles(1) = gp_Pnt2d(0.0, 0.0); - aPoles(2) = gp_Pnt2d(1.0, 2.0); - aPoles(3) = gp_Pnt2d(3.0, 2.0); - aPoles(4) = gp_Pnt2d(4.0, 0.0); - - NCollection_Array1 aKnots(1, 3); - aKnots(1) = 0.0; - aKnots(2) = 0.5; - aKnots(3) = 1.0; - - NCollection_Array1 aMults(1, 3); - aMults(1) = 3; - aMults(2) = 1; - aMults(3) = 3; - - occ::handle aBSpline = new Geom2d_BSplineCurve(aPoles, aKnots, aMults, 2); - Geom2dAdaptor_Curve anAdaptor(aBSpline); - - Geom2dProp_Curve aProp(anAdaptor); - EXPECT_EQ(aProp.GetType(), GeomAbs_BSplineCurve); -} - -// ============================================================================ -// Cross-validation tests -// ============================================================================ - -TEST(Geom2dProp_CrossValidationTest, Circle_MatchesLProp) -{ - gp_Circ2d aCirc(gp_Ax2d(gp_Pnt2d(1.0, 2.0), gp_Dir2d(1.0, 0.0)), 7.0); - occ::handle aCircle = new Geom2d_Circle(aCirc); - - Geom2dProp_Curve aProp(aCircle); - - for (double u = 0.0; u < 2.0 * M_PI; u += M_PI / 6.0) - { - const Geom2dProp::CurvatureResult aCurv = aProp.Curvature(u, Precision::Confusion()); - ASSERT_TRUE(aCurv.IsDefined); - EXPECT_NEAR(aCurv.Value, 1.0 / 7.0, 1.0e-10); - - const Geom2dProp::CentreResult aCentre = aProp.CentreOfCurvature(u, Precision::Confusion()); - ASSERT_TRUE(aCentre.IsDefined); - EXPECT_NEAR(aCentre.Centre.X(), 1.0, Precision::Confusion()); - EXPECT_NEAR(aCentre.Centre.Y(), 2.0, Precision::Confusion()); - } -} - -TEST(Geom2dProp_CrossValidationTest, Ellipse_MatchesLProp) -{ - gp_Elips2d anElips(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 10.0, 5.0); - occ::handle anEllipse = new Geom2d_Ellipse(anElips); - - Geom2dProp_Curve aProp(anEllipse); - - // At major vertex (U=0): curvature = a/b^2 = 10/25 = 0.4 - const Geom2dProp::CurvatureResult aCurv0 = aProp.Curvature(0.0, Precision::Confusion()); - ASSERT_TRUE(aCurv0.IsDefined); - EXPECT_NEAR(aCurv0.Value, 10.0 / 25.0, 1.0e-6); - - // At minor vertex (U=PI/2): curvature = b/a^2 = 5/100 = 0.05 - const Geom2dProp::CurvatureResult aCurvPi2 = aProp.Curvature(M_PI / 2.0, Precision::Confusion()); - ASSERT_TRUE(aCurvPi2.IsDefined); - EXPECT_NEAR(aCurvPi2.Value, 5.0 / 100.0, 1.0e-6); -} - -// Cross-validate: free function vs. dispatcher give same result -TEST(Geom2dProp_CrossValidationTest, FreeFunctionVsDispatcher) -{ - gp_Circ2d aCirc(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 3.0); - occ::handle aCircle = new Geom2d_Circle(aCirc); - - Geom2dProp_Curve aProp(aCircle); - - const double u = 1.0; - gp_Pnt2d aPnt; - gp_Vec2d aD1, aD2; - aCircle->D2(u, aPnt, aD1, aD2); - - // Free function - const Geom2dProp::CurvatureResult aCurvFree = - Geom2dProp::ComputeCurvature(aD1, aD2, Precision::Confusion()); - // Dispatcher - const Geom2dProp::CurvatureResult aCurvDisp = aProp.Curvature(u, Precision::Confusion()); - - ASSERT_TRUE(aCurvFree.IsDefined); - ASSERT_TRUE(aCurvDisp.IsDefined); - EXPECT_NEAR(aCurvFree.Value, aCurvDisp.Value, 1.0e-10); -} - -// Cross-validate centre of curvature consistency: distance from point = 1/|curvature| -TEST(Geom2dProp_CrossValidationTest, CentreDistanceConsistency) -{ - gp_Elips2d anElips(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 8.0, 4.0); - occ::handle anEllipse = new Geom2d_Ellipse(anElips); - - Geom2dProp_Curve aProp(anEllipse); - - for (double u = 0.0; u < 2.0 * M_PI; u += M_PI / 8.0) - { - const Geom2dProp::CurvatureResult aCurv = aProp.Curvature(u, Precision::Confusion()); - const Geom2dProp::CentreResult aCentre = aProp.CentreOfCurvature(u, Precision::Confusion()); - if (aCurv.IsDefined && aCentre.IsDefined && !aCurv.IsInfinite - && std::abs(aCurv.Value) > 1.0e-10) - { - gp_Pnt2d aPnt; - gp_Vec2d aD1; - anEllipse->D1(u, aPnt, aD1); - const double aDist = aPnt.Distance(aCentre.Centre); - const double aExpected = 1.0 / std::abs(aCurv.Value); - EXPECT_NEAR(aDist, aExpected, 1.0e-6); - } - } -} - -// Cross-validate: adaptor init and geometry init give same results -TEST(Geom2dProp_CrossValidationTest, AdaptorVsGeometryInit) -{ - gp_Elips2d anElips(gp_Ax2d(gp_Pnt2d(1.0, 2.0), gp_Dir2d(1.0, 0.0)), 6.0, 3.0); - occ::handle anEllipse = new Geom2d_Ellipse(anElips); - - Geom2dProp_Curve aPropGeom(anEllipse); - - Geom2dAdaptor_Curve anAdaptor(anEllipse); - Geom2dProp_Curve aPropAdap(anAdaptor); - - for (double u = 0.0; u < 2.0 * M_PI; u += M_PI / 5.0) - { - const Geom2dProp::CurvatureResult aCurvG = aPropGeom.Curvature(u, Precision::Confusion()); - const Geom2dProp::CurvatureResult aCurvA = aPropAdap.Curvature(u, Precision::Confusion()); - ASSERT_TRUE(aCurvG.IsDefined); - ASSERT_TRUE(aCurvA.IsDefined); - EXPECT_NEAR(aCurvG.Value, aCurvA.Value, 1.0e-10); - } -} - -// ============================================================================ -// Geometry() / Adaptor() accessor tests -// ============================================================================ - -TEST(Geom2dPropCurveTest, Geometry_HandlePath_ReturnsNonNull) -{ - occ::handle aLine = new Geom2d_Line(gp_Pnt2d(), gp_Dir2d(1, 0)); - Geom2dProp_Curve aProp(aLine); - EXPECT_NE(aProp.Geometry(), nullptr); - EXPECT_EQ(aProp.Adaptor(), nullptr); -} - -TEST(Geom2dPropCurveTest, Geometry_AdaptorPath_Line_ReturnsNonNull) -{ - occ::handle aLine = new Geom2d_Line(gp_Pnt2d(), gp_Dir2d(1, 0)); - Geom2dAdaptor_Curve anAdaptor(aLine); - Geom2dProp_Curve aProp(anAdaptor); - // Line evaluator extracts geometry from adaptor - EXPECT_NE(aProp.Geometry(), nullptr); -} - -TEST(Geom2dPropCurveTest, Geometry_TrimmedCurve_ReturnsBasisCurve) -{ - occ::handle aCircle = new Geom2d_Circle(gp_Ax2d(gp_Pnt2d(), gp_Dir2d(1, 0)), 5.0); - occ::handle aTrimmed = new Geom2d_TrimmedCurve(aCircle, 0.0, M_PI); - Geom2dProp_Curve aProp(aTrimmed); - - const Geom2d_Curve* aGeom = aProp.Geometry(); - ASSERT_NE(aGeom, nullptr); - EXPECT_TRUE(aGeom->IsKind(STANDARD_TYPE(Geom2d_Circle))); -} - -TEST(Geom2dPropCurveTest, Geometry_AllCurveTypes_NonNull) -{ - // Line - { - occ::handle aCurve = new Geom2d_Line(gp_Pnt2d(), gp_Dir2d(0, 1)); - Geom2dProp_Curve aProp(aCurve); - EXPECT_NE(aProp.Geometry(), nullptr); - } - // Ellipse - { - gp_Elips2d anElips(gp_Ax2d(gp_Pnt2d(), gp_Dir2d(1, 0)), 5.0, 3.0); - occ::handle aCurve = new Geom2d_Ellipse(anElips); - Geom2dProp_Curve aProp(aCurve); - EXPECT_NE(aProp.Geometry(), nullptr); - } - // Hyperbola - { - gp_Hypr2d aHypr(gp_Ax2d(gp_Pnt2d(), gp_Dir2d(1, 0)), 5.0, 3.0); - occ::handle aCurve = new Geom2d_Hyperbola(aHypr); - Geom2dProp_Curve aProp(aCurve); - EXPECT_NE(aProp.Geometry(), nullptr); - } - // Parabola - { - gp_Parab2d aParab(gp_Ax2d(gp_Pnt2d(), gp_Dir2d(1, 0)), 2.0); - occ::handle aCurve = new Geom2d_Parabola(aParab); - Geom2dProp_Curve aProp(aCurve); - EXPECT_NE(aProp.Geometry(), nullptr); - } -} - -// ============================================================================ -// Continuity() tests -// ============================================================================ - -TEST(Geom2dPropCurveTest, Continuity_TwoLines_C1) -{ - occ::handle aL1 = new Geom2d_Line(gp_Pnt2d(0, 0), gp_Dir2d(1, 0)); - occ::handle aL2 = new Geom2d_Line(gp_Pnt2d(1, 0), gp_Dir2d(1, 0)); - GeomAbs_Shape aCont = Geom2dProp_Curve::Continuity(aL1, aL2, 1.0, 0.0, false, false); - EXPECT_GE(aCont, GeomAbs_C1); -} - -TEST(Geom2dPropCurveTest, Continuity_ReversedJunction_C1) -{ - occ::handle aL1 = new Geom2d_Line(gp_Pnt2d(0, 0), gp_Dir2d(1, 0)); - occ::handle aL2 = new Geom2d_Line(gp_Pnt2d(1, 0), gp_Dir2d(-1, 0)); - // Reversed second curve: directions match after reversal - GeomAbs_Shape aCont = Geom2dProp_Curve::Continuity(aL1, aL2, 1.0, 0.0, false, true); - EXPECT_GE(aCont, GeomAbs_C1); -} - -TEST(Geom2dPropCurveTest, Continuity_PerpendicularLines_C0) -{ - occ::handle aL1 = new Geom2d_Line(gp_Pnt2d(0, 0), gp_Dir2d(1, 0)); - occ::handle aL2 = new Geom2d_Line(gp_Pnt2d(1, 0), gp_Dir2d(0, 1)); - GeomAbs_Shape aCont = Geom2dProp_Curve::Continuity(aL1, aL2, 1.0, 0.0, false, false); - EXPECT_EQ(aCont, GeomAbs_C0); -} - -TEST(Geom2dPropCurveTest, Continuity_TrimmedBSpline_AtKnot) -{ - // Build a simple cubic B-spline with an interior knot - NCollection_Array1 aPoles(1, 5); - aPoles.SetValue(1, gp_Pnt2d(0, 0)); - aPoles.SetValue(2, gp_Pnt2d(1, 2)); - aPoles.SetValue(3, gp_Pnt2d(3, 2)); - aPoles.SetValue(4, gp_Pnt2d(4, 0)); - aPoles.SetValue(5, gp_Pnt2d(5, 1)); - - NCollection_Array1 aKnots(1, 3); - aKnots.SetValue(1, 0.0); - aKnots.SetValue(2, 0.5); - aKnots.SetValue(3, 1.0); - - NCollection_Array1 aMults(1, 3); - aMults.SetValue(1, 4); - aMults.SetValue(2, 1); - aMults.SetValue(3, 4); - - occ::handle aBSpl = new Geom2d_BSplineCurve(aPoles, aKnots, aMults, 3); - - // Split at the interior knot: two trimmed pieces meet at u=0.5 - occ::handle aT1 = new Geom2d_TrimmedCurve(aBSpl, 0.0, 0.5); - occ::handle aT2 = new Geom2d_TrimmedCurve(aBSpl, 0.5, 1.0); - - GeomAbs_Shape aCont = Geom2dProp_Curve::Continuity(aT1, aT2, 0.5, 0.5, false, false); - // Same underlying BSpline at same knot, first derivatives match -> at least C1 - EXPECT_GE(aCont, GeomAbs_C1); -} - -TEST(Geom2dPropCurveTest, Continuity_DisconnectedCurves_Throws) -{ - occ::handle aL1 = new Geom2d_Line(gp_Pnt2d(0, 0), gp_Dir2d(1, 0)); - occ::handle aL2 = new Geom2d_Line(gp_Pnt2d(0, 10), gp_Dir2d(1, 0)); - EXPECT_THROW(Geom2dProp_Curve::Continuity(aL1, aL2, 0.0, 0.0, false, false), Standard_Failure); -} diff --git a/src/ModelingData/TKG2d/GTests/Geom2dProp_VsCLProps2d_Test.cxx b/src/ModelingData/TKG2d/GTests/Geom2dProp_VsCLProps2d_Test.cxx deleted file mode 100644 index f962bb055f..0000000000 --- a/src/ModelingData/TKG2d/GTests/Geom2dProp_VsCLProps2d_Test.cxx +++ /dev/null @@ -1,580 +0,0 @@ -// 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. - -// Cross-validation tests comparing Geom2dProp_Curve against Geom2dLProp_CLProps2d -// for local differential properties (tangent, curvature, normal, centre of curvature). - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -namespace -{ -constexpr double THE_PARAM_TOL = Precision::Confusion(); -constexpr double THE_VALUE_TOL = 1.0e-10; -constexpr double THE_DIR_TOL = 1.0e-10; -constexpr double THE_POINT_TOL = 1.0e-8; - -//! Compare tangent from new Geom2dProp vs old CLProps2d at given parameter. -void compareTangent(Geom2dProp_Curve& theProp, - Geom2dLProp_CLProps2d& theOld, - const double theParam, - const ::testing::TestInfo* = nullptr) -{ - theOld.SetParameter(theParam); - - const Geom2dProp::TangentResult aNewTan = theProp.Tangent(theParam, THE_PARAM_TOL); - const bool aOldDefined = theOld.IsTangentDefined(); - - EXPECT_EQ(aNewTan.IsDefined, aOldDefined) << "Tangent defined mismatch at U=" << theParam; - - if (aNewTan.IsDefined && aOldDefined) - { - gp_Dir2d aOldDir; - theOld.Tangent(aOldDir); - // Tangent directions may differ by sign; compare absolute dot product - const double aDot = aNewTan.Direction.X() * aOldDir.X() + aNewTan.Direction.Y() * aOldDir.Y(); - EXPECT_NEAR(std::abs(aDot), 1.0, THE_DIR_TOL) << "Tangent direction mismatch at U=" << theParam; - } -} - -//! Compare curvature from new Geom2dProp vs old CLProps2d at given parameter. -void compareCurvature(Geom2dProp_Curve& theProp, - Geom2dLProp_CLProps2d& theOld, - const double theParam) -{ - theOld.SetParameter(theParam); - - const Geom2dProp::CurvatureResult aNewCurv = theProp.Curvature(theParam, THE_PARAM_TOL); - const double aOldCurv = theOld.Curvature(); - - if (aNewCurv.IsDefined && !aNewCurv.IsInfinite) - { - EXPECT_NEAR(aNewCurv.Value, aOldCurv, THE_VALUE_TOL) << "Curvature mismatch at U=" << theParam; - } -} - -//! Compare normal from new Geom2dProp vs old CLProps2d at given parameter. -void compareNormal(Geom2dProp_Curve& theProp, Geom2dLProp_CLProps2d& theOld, const double theParam) -{ - theOld.SetParameter(theParam); - - const Geom2dProp::NormalResult aNewNorm = theProp.Normal(theParam, THE_PARAM_TOL); - - // Old API: Normal() throws if curvature is nearly zero; curvature check needed - const double aOldCurv = theOld.Curvature(); - if (std::abs(aOldCurv) < THE_PARAM_TOL) - { - // Old API would throw - new API returns IsDefined=false - EXPECT_FALSE(aNewNorm.IsDefined) << "Normal should be undefined at U=" << theParam; - return; - } - - if (aNewNorm.IsDefined) - { - gp_Dir2d aOldDir; - theOld.Normal(aOldDir); - const double aDot = aNewNorm.Direction.X() * aOldDir.X() + aNewNorm.Direction.Y() * aOldDir.Y(); - EXPECT_NEAR(std::abs(aDot), 1.0, THE_DIR_TOL) << "Normal direction mismatch at U=" << theParam; - } -} - -//! Compare centre of curvature from new Geom2dProp vs old CLProps2d at given parameter. -void compareCentre(Geom2dProp_Curve& theProp, Geom2dLProp_CLProps2d& theOld, const double theParam) -{ - theOld.SetParameter(theParam); - - const Geom2dProp::CentreResult aNewCentre = theProp.CentreOfCurvature(theParam, THE_PARAM_TOL); - - // Old API: CentreOfCurvature() throws if curvature is nearly zero - const double aOldCurv = theOld.Curvature(); - if (std::abs(aOldCurv) < THE_PARAM_TOL) - { - EXPECT_FALSE(aNewCentre.IsDefined) << "Centre should be undefined at U=" << theParam; - return; - } - - if (aNewCentre.IsDefined) - { - gp_Pnt2d aOldCentre; - theOld.CentreOfCurvature(aOldCentre); - EXPECT_NEAR(aNewCentre.Centre.X(), aOldCentre.X(), THE_POINT_TOL) - << "Centre X mismatch at U=" << theParam; - EXPECT_NEAR(aNewCentre.Centre.Y(), aOldCentre.Y(), THE_POINT_TOL) - << "Centre Y mismatch at U=" << theParam; - } -} - -//! Run all four property comparisons at given parameter. -void compareAllProperties(Geom2dProp_Curve& theProp, - Geom2dLProp_CLProps2d& theOld, - const double theParam) -{ - compareTangent(theProp, theOld, theParam); - compareCurvature(theProp, theOld, theParam); - compareNormal(theProp, theOld, theParam); - compareCentre(theProp, theOld, theParam); -} - -} // namespace - -// ============================================================================ -// Line -// ============================================================================ - -TEST(Geom2dProp_VsCLProps2dTest, Line_Tangent) -{ - gp_Lin2d aLin(gp_Pnt2d(1.0, 2.0), gp_Dir2d(3.0, 4.0)); - occ::handle aLine = new Geom2d_Line(aLin); - - Geom2dProp_Curve aProp(aLine); - Geom2dLProp_CLProps2d aOld(aLine, 2, THE_PARAM_TOL); - - for (double u = -10.0; u <= 10.0; u += 2.5) - { - compareTangent(aProp, aOld, u); - } -} - -TEST(Geom2dProp_VsCLProps2dTest, Line_Curvature) -{ - gp_Lin2d aLin(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 1.0)); - occ::handle aLine = new Geom2d_Line(aLin); - - Geom2dProp_Curve aProp(aLine); - Geom2dLProp_CLProps2d aOld(aLine, 2, THE_PARAM_TOL); - - for (double u = -5.0; u <= 5.0; u += 1.0) - { - compareCurvature(aProp, aOld, u); - } -} - -// ============================================================================ -// Circle -// ============================================================================ - -TEST(Geom2dProp_VsCLProps2dTest, Circle_AllProperties) -{ - gp_Circ2d aCirc(gp_Ax2d(gp_Pnt2d(3.0, 4.0), gp_Dir2d(1.0, 0.0)), 7.0); - occ::handle aCircle = new Geom2d_Circle(aCirc); - - Geom2dProp_Curve aProp(aCircle); - Geom2dLProp_CLProps2d aOld(aCircle, 2, THE_PARAM_TOL); - - for (double u = 0.0; u < 2.0 * M_PI; u += M_PI / 6.0) - { - compareAllProperties(aProp, aOld, u); - } -} - -TEST(Geom2dProp_VsCLProps2dTest, Circle_SmallRadius) -{ - gp_Circ2d aCirc(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 0.01); - occ::handle aCircle = new Geom2d_Circle(aCirc); - - Geom2dProp_Curve aProp(aCircle); - Geom2dLProp_CLProps2d aOld(aCircle, 2, THE_PARAM_TOL); - - for (double u = 0.0; u < 2.0 * M_PI; u += M_PI / 4.0) - { - compareAllProperties(aProp, aOld, u); - } -} - -TEST(Geom2dProp_VsCLProps2dTest, Circle_LargeRadius) -{ - gp_Circ2d aCirc(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 1000.0); - occ::handle aCircle = new Geom2d_Circle(aCirc); - - Geom2dProp_Curve aProp(aCircle); - Geom2dLProp_CLProps2d aOld(aCircle, 2, THE_PARAM_TOL); - - for (double u = 0.0; u < 2.0 * M_PI; u += M_PI / 4.0) - { - compareAllProperties(aProp, aOld, u); - } -} - -// ============================================================================ -// Ellipse -// ============================================================================ - -TEST(Geom2dProp_VsCLProps2dTest, Ellipse_AllProperties) -{ - gp_Elips2d anElips(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 10.0, 5.0); - occ::handle anEllipse = new Geom2d_Ellipse(anElips); - - Geom2dProp_Curve aProp(anEllipse); - Geom2dLProp_CLProps2d aOld(anEllipse, 2, THE_PARAM_TOL); - - for (double u = 0.0; u < 2.0 * M_PI; u += M_PI / 12.0) - { - compareAllProperties(aProp, aOld, u); - } -} - -TEST(Geom2dProp_VsCLProps2dTest, Ellipse_HighEccentricity) -{ - gp_Elips2d anElips(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 100.0, 1.0); - occ::handle anEllipse = new Geom2d_Ellipse(anElips); - - Geom2dProp_Curve aProp(anEllipse); - Geom2dLProp_CLProps2d aOld(anEllipse, 2, THE_PARAM_TOL); - - for (double u = 0.0; u < 2.0 * M_PI; u += M_PI / 8.0) - { - compareAllProperties(aProp, aOld, u); - } -} - -TEST(Geom2dProp_VsCLProps2dTest, Ellipse_OffCenter) -{ - gp_Elips2d anElips(gp_Ax2d(gp_Pnt2d(100.0, -50.0), gp_Dir2d(1.0, 0.0)), 8.0, 3.0); - occ::handle anEllipse = new Geom2d_Ellipse(anElips); - - Geom2dProp_Curve aProp(anEllipse); - Geom2dLProp_CLProps2d aOld(anEllipse, 2, THE_PARAM_TOL); - - for (double u = 0.0; u < 2.0 * M_PI; u += M_PI / 8.0) - { - compareAllProperties(aProp, aOld, u); - } -} - -// ============================================================================ -// Hyperbola -// ============================================================================ - -TEST(Geom2dProp_VsCLProps2dTest, Hyperbola_AllProperties) -{ - gp_Hypr2d anHypr(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 6.0, 3.0); - occ::handle aHyperbola = new Geom2d_Hyperbola(anHypr); - - Geom2dProp_Curve aProp(aHyperbola); - Geom2dLProp_CLProps2d aOld(aHyperbola, 2, THE_PARAM_TOL); - - for (double u = -2.0; u <= 2.0; u += 0.5) - { - compareAllProperties(aProp, aOld, u); - } -} - -TEST(Geom2dProp_VsCLProps2dTest, Hyperbola_NearVertex) -{ - gp_Hypr2d anHypr(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 4.0, 2.0); - occ::handle aHyperbola = new Geom2d_Hyperbola(anHypr); - - Geom2dProp_Curve aProp(aHyperbola); - Geom2dLProp_CLProps2d aOld(aHyperbola, 2, THE_PARAM_TOL); - - // Fine-grained near vertex - for (double u = -0.5; u <= 0.5; u += 0.1) - { - compareAllProperties(aProp, aOld, u); - } -} - -// ============================================================================ -// Parabola -// ============================================================================ - -TEST(Geom2dProp_VsCLProps2dTest, Parabola_AllProperties) -{ - gp_Parab2d aParab(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 2.0); - occ::handle aParabola = new Geom2d_Parabola(aParab); - - Geom2dProp_Curve aProp(aParabola); - Geom2dLProp_CLProps2d aOld(aParabola, 2, THE_PARAM_TOL); - - for (double u = -5.0; u <= 5.0; u += 1.0) - { - compareAllProperties(aProp, aOld, u); - } -} - -TEST(Geom2dProp_VsCLProps2dTest, Parabola_SmallFocal) -{ - gp_Parab2d aParab(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 0.1); - occ::handle aParabola = new Geom2d_Parabola(aParab); - - Geom2dProp_Curve aProp(aParabola); - Geom2dLProp_CLProps2d aOld(aParabola, 2, THE_PARAM_TOL); - - for (double u = -3.0; u <= 3.0; u += 0.5) - { - compareAllProperties(aProp, aOld, u); - } -} - -TEST(Geom2dProp_VsCLProps2dTest, Parabola_LargeFocal) -{ - gp_Parab2d aParab(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 50.0); - occ::handle aParabola = new Geom2d_Parabola(aParab); - - Geom2dProp_Curve aProp(aParabola); - Geom2dLProp_CLProps2d aOld(aParabola, 2, THE_PARAM_TOL); - - for (double u = -10.0; u <= 10.0; u += 2.0) - { - compareAllProperties(aProp, aOld, u); - } -} - -// ============================================================================ -// Bezier curve -// ============================================================================ - -TEST(Geom2dProp_VsCLProps2dTest, Bezier_CubicSShape) -{ - NCollection_Array1 aPoles(1, 4); - aPoles(1) = gp_Pnt2d(0.0, 0.0); - aPoles(2) = gp_Pnt2d(1.0, 2.0); - aPoles(3) = gp_Pnt2d(3.0, -2.0); - aPoles(4) = gp_Pnt2d(4.0, 0.0); - occ::handle aBezier = new Geom2d_BezierCurve(aPoles); - - Geom2dProp_Curve aProp(aBezier); - Geom2dLProp_CLProps2d aOld(aBezier, 2, THE_PARAM_TOL); - - for (double u = 0.0; u <= 1.0; u += 0.1) - { - compareAllProperties(aProp, aOld, u); - } -} - -TEST(Geom2dProp_VsCLProps2dTest, Bezier_Quadratic) -{ - NCollection_Array1 aPoles(1, 3); - aPoles(1) = gp_Pnt2d(0.0, 0.0); - aPoles(2) = gp_Pnt2d(2.0, 4.0); - aPoles(3) = gp_Pnt2d(4.0, 0.0); - occ::handle aBezier = new Geom2d_BezierCurve(aPoles); - - Geom2dProp_Curve aProp(aBezier); - Geom2dLProp_CLProps2d aOld(aBezier, 2, THE_PARAM_TOL); - - for (double u = 0.0; u <= 1.0; u += 0.1) - { - compareAllProperties(aProp, aOld, u); - } -} - -TEST(Geom2dProp_VsCLProps2dTest, Bezier_HighDegree) -{ - NCollection_Array1 aPoles(1, 6); - aPoles(1) = gp_Pnt2d(0.0, 0.0); - aPoles(2) = gp_Pnt2d(1.0, 3.0); - aPoles(3) = gp_Pnt2d(2.0, -1.0); - aPoles(4) = gp_Pnt2d(3.0, 2.0); - aPoles(5) = gp_Pnt2d(4.0, -2.0); - aPoles(6) = gp_Pnt2d(5.0, 1.0); - occ::handle aBezier = new Geom2d_BezierCurve(aPoles); - - Geom2dProp_Curve aProp(aBezier); - Geom2dLProp_CLProps2d aOld(aBezier, 2, THE_PARAM_TOL); - - for (double u = 0.0; u <= 1.0; u += 0.05) - { - compareAllProperties(aProp, aOld, u); - } -} - -// ============================================================================ -// BSpline curve -// ============================================================================ - -TEST(Geom2dProp_VsCLProps2dTest, BSpline_Quadratic) -{ - NCollection_Array1 aPoles(1, 4); - aPoles(1) = gp_Pnt2d(0.0, 0.0); - aPoles(2) = gp_Pnt2d(1.0, 2.0); - aPoles(3) = gp_Pnt2d(3.0, 2.0); - aPoles(4) = gp_Pnt2d(4.0, 0.0); - - NCollection_Array1 aKnots(1, 3); - aKnots(1) = 0.0; - aKnots(2) = 0.5; - aKnots(3) = 1.0; - - NCollection_Array1 aMults(1, 3); - aMults(1) = 3; - aMults(2) = 1; - aMults(3) = 3; - - occ::handle aBSpline = new Geom2d_BSplineCurve(aPoles, aKnots, aMults, 2); - - Geom2dProp_Curve aProp(aBSpline); - Geom2dLProp_CLProps2d aOld(aBSpline, 2, THE_PARAM_TOL); - - for (double u = 0.0; u <= 1.0; u += 0.1) - { - compareAllProperties(aProp, aOld, u); - } -} - -TEST(Geom2dProp_VsCLProps2dTest, BSpline_Cubic) -{ - NCollection_Array1 aPoles(1, 6); - aPoles(1) = gp_Pnt2d(0.0, 0.0); - aPoles(2) = gp_Pnt2d(1.0, 3.0); - aPoles(3) = gp_Pnt2d(2.0, 1.0); - aPoles(4) = gp_Pnt2d(3.0, 4.0); - aPoles(5) = gp_Pnt2d(4.0, 2.0); - aPoles(6) = gp_Pnt2d(5.0, 0.0); - - NCollection_Array1 aKnots(1, 4); - aKnots(1) = 0.0; - aKnots(2) = 0.33; - aKnots(3) = 0.66; - aKnots(4) = 1.0; - - NCollection_Array1 aMults(1, 4); - aMults(1) = 4; - aMults(2) = 1; - aMults(3) = 1; - aMults(4) = 4; - - occ::handle aBSpline = new Geom2d_BSplineCurve(aPoles, aKnots, aMults, 3); - - Geom2dProp_Curve aProp(aBSpline); - Geom2dLProp_CLProps2d aOld(aBSpline, 2, THE_PARAM_TOL); - - for (double u = 0.0; u <= 1.0; u += 0.05) - { - compareAllProperties(aProp, aOld, u); - } -} - -TEST(Geom2dProp_VsCLProps2dTest, BSpline_Degree4) -{ - NCollection_Array1 aPoles(1, 5); - aPoles(1) = gp_Pnt2d(0.0, 0.0); - aPoles(2) = gp_Pnt2d(1.0, 3.0); - aPoles(3) = gp_Pnt2d(2.0, -1.0); - aPoles(4) = gp_Pnt2d(3.0, 2.0); - aPoles(5) = gp_Pnt2d(4.0, 0.0); - - NCollection_Array1 aKnots(1, 2); - aKnots(1) = 0.0; - aKnots(2) = 1.0; - - NCollection_Array1 aMults(1, 2); - aMults(1) = 5; - aMults(2) = 5; - - occ::handle aBSpline = new Geom2d_BSplineCurve(aPoles, aKnots, aMults, 4); - - Geom2dProp_Curve aProp(aBSpline); - Geom2dLProp_CLProps2d aOld(aBSpline, 2, THE_PARAM_TOL); - - for (double u = 0.0; u <= 1.0; u += 0.05) - { - compareAllProperties(aProp, aOld, u); - } -} - -// ============================================================================ -// Offset curve -// ============================================================================ - -TEST(Geom2dProp_VsCLProps2dTest, OffsetCircle_AllProperties) -{ - gp_Circ2d aCirc(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 5.0); - occ::handle aCircle = new Geom2d_Circle(aCirc); - occ::handle anOffset = new Geom2d_OffsetCurve(aCircle, 2.0); - - Geom2dProp_Curve aProp(anOffset); - Geom2dLProp_CLProps2d aOld(anOffset, 2, THE_PARAM_TOL); - - for (double u = 0.0; u < 2.0 * M_PI; u += M_PI / 6.0) - { - compareAllProperties(aProp, aOld, u); - } -} - -TEST(Geom2dProp_VsCLProps2dTest, OffsetEllipse_AllProperties) -{ - gp_Elips2d anElips(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 10.0, 5.0); - occ::handle anEllipse = new Geom2d_Ellipse(anElips); - occ::handle anOffset = new Geom2d_OffsetCurve(anEllipse, 1.0); - - Geom2dProp_Curve aProp(anOffset); - Geom2dLProp_CLProps2d aOld(anOffset, 2, THE_PARAM_TOL); - - for (double u = 0.0; u < 2.0 * M_PI; u += M_PI / 8.0) - { - compareAllProperties(aProp, aOld, u); - } -} - -// ============================================================================ -// Trimmed curve -// ============================================================================ - -TEST(Geom2dProp_VsCLProps2dTest, TrimmedEllipse_AllProperties) -{ - gp_Elips2d anElips(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 8.0, 4.0); - occ::handle anEllipse = new Geom2d_Ellipse(anElips); - occ::handle aTrimmed = new Geom2d_TrimmedCurve(anEllipse, 0.5, 2.5); - - Geom2dProp_Curve aProp(aTrimmed); - Geom2dLProp_CLProps2d aOld(aTrimmed, 2, THE_PARAM_TOL); - - for (double u = 0.5; u <= 2.5; u += 0.2) - { - compareAllProperties(aProp, aOld, u); - } -} - -TEST(Geom2dProp_VsCLProps2dTest, TrimmedBezier_AllProperties) -{ - NCollection_Array1 aPoles(1, 4); - aPoles(1) = gp_Pnt2d(0.0, 0.0); - aPoles(2) = gp_Pnt2d(1.0, 3.0); - aPoles(3) = gp_Pnt2d(3.0, -1.0); - aPoles(4) = gp_Pnt2d(4.0, 1.0); - occ::handle aBezier = new Geom2d_BezierCurve(aPoles); - occ::handle aTrimmed = new Geom2d_TrimmedCurve(aBezier, 0.2, 0.8); - - Geom2dProp_Curve aProp(aTrimmed); - Geom2dLProp_CLProps2d aOld(aTrimmed, 2, THE_PARAM_TOL); - - for (double u = 0.2; u <= 0.8; u += 0.1) - { - compareAllProperties(aProp, aOld, u); - } -} diff --git a/src/ModelingData/TKG2d/GTests/Geom2dProp_VsLProp_Test.cxx b/src/ModelingData/TKG2d/GTests/Geom2dProp_VsLProp_Test.cxx deleted file mode 100644 index cd869b0033..0000000000 --- a/src/ModelingData/TKG2d/GTests/Geom2dProp_VsLProp_Test.cxx +++ /dev/null @@ -1,660 +0,0 @@ -// 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. - -// Cross-validation tests comparing Geom2dProp_Curve against Geom2dLProp_CurAndInf2d -// for global curve analysis (curvature extrema and inflection point finding). - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -namespace -{ -constexpr double THE_PARAM_TOL = 1.0e-4; - -//! Map LProp_CIType to Geom2dProp::CIType for comparison. -Geom2dProp::CIType mapLPropType(const LProp_CIType theType) -{ - switch (theType) - { - case LProp_Inflection: - return Geom2dProp::CIType::Inflection; - case LProp_MinCur: - return Geom2dProp::CIType::MinCurvature; - case LProp_MaxCur: - return Geom2dProp::CIType::MaxCurvature; - } - return Geom2dProp::CIType::Inflection; -} - -//! Compare extrema results from old and new APIs. -void compareExtrema(const Geom2dProp::CurveAnalysis& theNew, - const Geom2dLProp_CurAndInf2d& theOld, - const double theTol = THE_PARAM_TOL) -{ - EXPECT_EQ(theNew.Points.Length(), theOld.NbPoints()); - - const int aNb = std::min(theNew.Points.Length(), theOld.NbPoints()); - for (int i = 0; i < aNb; ++i) - { - EXPECT_NEAR(theNew.Points.Value(i).Parameter, theOld.Parameter(i + 1), theTol) - << "Parameter mismatch at index " << i; - EXPECT_EQ(theNew.Points.Value(i).Type, mapLPropType(theOld.Type(i + 1))) - << "Type mismatch at index " << i; - } -} - -} // namespace - -// ============================================================================ -// Circle - no extrema, no inflections -// ============================================================================ - -TEST(Geom2dProp_VsCurAndInf2dTest, Circle_NoExtrema) -{ - gp_Circ2d aCirc(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 5.0); - occ::handle aCircle = new Geom2d_Circle(aCirc); - - Geom2dLProp_CurAndInf2d anOld; - anOld.PerformCurExt(aCircle); - ASSERT_TRUE(anOld.IsDone()); - EXPECT_EQ(anOld.NbPoints(), 0); - - Geom2dProp_Curve aProp(aCircle); - const Geom2dProp::CurveAnalysis aNew = aProp.FindCurvatureExtrema(); - ASSERT_TRUE(aNew.IsDone); - EXPECT_EQ(aNew.Points.Length(), 0); -} - -TEST(Geom2dProp_VsCurAndInf2dTest, Circle_NoInflections) -{ - gp_Circ2d aCirc(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 5.0); - occ::handle aCircle = new Geom2d_Circle(aCirc); - - Geom2dLProp_CurAndInf2d anOld; - anOld.PerformInf(aCircle); - ASSERT_TRUE(anOld.IsDone()); - EXPECT_EQ(anOld.NbPoints(), 0); - - Geom2dProp_Curve aProp(aCircle); - const Geom2dProp::CurveAnalysis aNew = aProp.FindInflections(); - ASSERT_TRUE(aNew.IsDone); - EXPECT_EQ(aNew.Points.Length(), 0); -} - -// ============================================================================ -// Ellipse - 4 extrema, no inflections -// ============================================================================ - -TEST(Geom2dProp_VsCurAndInf2dTest, Ellipse_Extrema) -{ - gp_Elips2d anElips(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 10.0, 5.0); - occ::handle anEllipse = new Geom2d_Ellipse(anElips); - - Geom2dLProp_CurAndInf2d anOld; - anOld.PerformCurExt(anEllipse); - ASSERT_TRUE(anOld.IsDone()); - - Geom2dProp_Curve aProp(anEllipse); - const Geom2dProp::CurveAnalysis aNew = aProp.FindCurvatureExtrema(); - ASSERT_TRUE(aNew.IsDone); - - compareExtrema(aNew, anOld, 1.0e-6); -} - -TEST(Geom2dProp_VsCurAndInf2dTest, Ellipse_NoInflections) -{ - gp_Elips2d anElips(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 10.0, 5.0); - occ::handle anEllipse = new Geom2d_Ellipse(anElips); - - Geom2dLProp_CurAndInf2d anOld; - anOld.PerformInf(anEllipse); - ASSERT_TRUE(anOld.IsDone()); - EXPECT_EQ(anOld.NbPoints(), 0); - - Geom2dProp_Curve aProp(anEllipse); - const Geom2dProp::CurveAnalysis aNew = aProp.FindInflections(); - ASSERT_TRUE(aNew.IsDone); - EXPECT_EQ(aNew.Points.Length(), 0); -} - -TEST(Geom2dProp_VsCurAndInf2dTest, Ellipse_HighEccentricity_Extrema) -{ - gp_Elips2d anElips(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 50.0, 2.0); - occ::handle anEllipse = new Geom2d_Ellipse(anElips); - - Geom2dLProp_CurAndInf2d anOld; - anOld.PerformCurExt(anEllipse); - ASSERT_TRUE(anOld.IsDone()); - - Geom2dProp_Curve aProp(anEllipse); - const Geom2dProp::CurveAnalysis aNew = aProp.FindCurvatureExtrema(); - ASSERT_TRUE(aNew.IsDone); - - compareExtrema(aNew, anOld, 1.0e-6); -} - -TEST(Geom2dProp_VsCurAndInf2dTest, Ellipse_FullPerform) -{ - gp_Elips2d anElips(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 8.0, 3.0); - occ::handle anEllipse = new Geom2d_Ellipse(anElips); - - Geom2dLProp_CurAndInf2d anOld; - anOld.Perform(anEllipse); - ASSERT_TRUE(anOld.IsDone()); - - Geom2dProp_Curve aProp(anEllipse); - const Geom2dProp::CurveAnalysis aNewExt = aProp.FindCurvatureExtrema(); - const Geom2dProp::CurveAnalysis aNewInfl = aProp.FindInflections(); - ASSERT_TRUE(aNewExt.IsDone); - ASSERT_TRUE(aNewInfl.IsDone); - - const int aNewTotal = aNewExt.Points.Length() + aNewInfl.Points.Length(); - EXPECT_EQ(aNewTotal, anOld.NbPoints()); -} - -// ============================================================================ -// Hyperbola - 1 extremum at vertex, no inflections -// ============================================================================ - -TEST(Geom2dProp_VsCurAndInf2dTest, Hyperbola_Extrema) -{ - gp_Hypr2d anHypr(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 6.0, 3.0); - occ::handle aHyperbola = new Geom2d_Hyperbola(anHypr); - - Geom2dLProp_CurAndInf2d anOld; - anOld.PerformCurExt(aHyperbola); - ASSERT_TRUE(anOld.IsDone()); - - Geom2dProp_Curve aProp(aHyperbola); - const Geom2dProp::CurveAnalysis aNew = aProp.FindCurvatureExtrema(); - ASSERT_TRUE(aNew.IsDone); - - compareExtrema(aNew, anOld, 1.0e-6); -} - -TEST(Geom2dProp_VsCurAndInf2dTest, Hyperbola_NoInflections) -{ - gp_Hypr2d anHypr(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 6.0, 3.0); - occ::handle aHyperbola = new Geom2d_Hyperbola(anHypr); - - Geom2dLProp_CurAndInf2d anOld; - anOld.PerformInf(aHyperbola); - ASSERT_TRUE(anOld.IsDone()); - EXPECT_EQ(anOld.NbPoints(), 0); - - Geom2dProp_Curve aProp(aHyperbola); - const Geom2dProp::CurveAnalysis aNew = aProp.FindInflections(); - ASSERT_TRUE(aNew.IsDone); - EXPECT_EQ(aNew.Points.Length(), 0); -} - -// ============================================================================ -// Parabola - 1 extremum at vertex, no inflections -// ============================================================================ - -TEST(Geom2dProp_VsCurAndInf2dTest, Parabola_Extrema) -{ - gp_Parab2d aParab(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 2.0); - occ::handle aParabola = new Geom2d_Parabola(aParab); - - Geom2dLProp_CurAndInf2d anOld; - anOld.PerformCurExt(aParabola); - ASSERT_TRUE(anOld.IsDone()); - - Geom2dProp_Curve aProp(aParabola); - const Geom2dProp::CurveAnalysis aNew = aProp.FindCurvatureExtrema(); - ASSERT_TRUE(aNew.IsDone); - - compareExtrema(aNew, anOld, 1.0e-6); -} - -TEST(Geom2dProp_VsCurAndInf2dTest, Parabola_NoInflections) -{ - gp_Parab2d aParab(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 2.0); - occ::handle aParabola = new Geom2d_Parabola(aParab); - - Geom2dLProp_CurAndInf2d anOld; - anOld.PerformInf(aParabola); - ASSERT_TRUE(anOld.IsDone()); - EXPECT_EQ(anOld.NbPoints(), 0); - - Geom2dProp_Curve aProp(aParabola); - const Geom2dProp::CurveAnalysis aNew = aProp.FindInflections(); - ASSERT_TRUE(aNew.IsDone); - EXPECT_EQ(aNew.Points.Length(), 0); -} - -TEST(Geom2dProp_VsCurAndInf2dTest, Parabola_FullPerform) -{ - gp_Parab2d aParab(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 5.0); - occ::handle aParabola = new Geom2d_Parabola(aParab); - - Geom2dLProp_CurAndInf2d anOld; - anOld.Perform(aParabola); - ASSERT_TRUE(anOld.IsDone()); - - Geom2dProp_Curve aProp(aParabola); - const Geom2dProp::CurveAnalysis aNewExt = aProp.FindCurvatureExtrema(); - const Geom2dProp::CurveAnalysis aNewInfl = aProp.FindInflections(); - ASSERT_TRUE(aNewExt.IsDone); - ASSERT_TRUE(aNewInfl.IsDone); - - const int aNewTotal = aNewExt.Points.Length() + aNewInfl.Points.Length(); - EXPECT_EQ(aNewTotal, anOld.NbPoints()); -} - -// ============================================================================ -// Bezier - numeric extrema and inflections -// ============================================================================ - -TEST(Geom2dProp_VsCurAndInf2dTest, Bezier_CubicS_Inflections) -{ - NCollection_Array1 aPoles(1, 4); - aPoles(1) = gp_Pnt2d(0.0, 0.0); - aPoles(2) = gp_Pnt2d(1.0, 2.0); - aPoles(3) = gp_Pnt2d(3.0, -1.0); - aPoles(4) = gp_Pnt2d(4.0, 1.0); - occ::handle aBezier = new Geom2d_BezierCurve(aPoles); - - Geom2dLProp_CurAndInf2d anOld; - anOld.PerformInf(aBezier); - ASSERT_TRUE(anOld.IsDone()); - - Geom2dProp_Curve aProp(aBezier); - const Geom2dProp::CurveAnalysis aNew = aProp.FindInflections(); - ASSERT_TRUE(aNew.IsDone); - - compareExtrema(aNew, anOld); -} - -TEST(Geom2dProp_VsCurAndInf2dTest, Bezier_CubicS_Extrema) -{ - NCollection_Array1 aPoles(1, 4); - aPoles(1) = gp_Pnt2d(0.0, 0.0); - aPoles(2) = gp_Pnt2d(1.0, 2.0); - aPoles(3) = gp_Pnt2d(3.0, -1.0); - aPoles(4) = gp_Pnt2d(4.0, 1.0); - occ::handle aBezier = new Geom2d_BezierCurve(aPoles); - - Geom2dLProp_CurAndInf2d anOld; - anOld.PerformCurExt(aBezier); - ASSERT_TRUE(anOld.IsDone()); - - Geom2dProp_Curve aProp(aBezier); - const Geom2dProp::CurveAnalysis aNew = aProp.FindCurvatureExtrema(); - ASSERT_TRUE(aNew.IsDone); - - compareExtrema(aNew, anOld); -} - -TEST(Geom2dProp_VsCurAndInf2dTest, Bezier_CubicS_FullPerform) -{ - NCollection_Array1 aPoles(1, 4); - aPoles(1) = gp_Pnt2d(0.0, 0.0); - aPoles(2) = gp_Pnt2d(1.0, 2.0); - aPoles(3) = gp_Pnt2d(3.0, -2.0); - aPoles(4) = gp_Pnt2d(4.0, 0.0); - occ::handle aBezier = new Geom2d_BezierCurve(aPoles); - - Geom2dLProp_CurAndInf2d anOld; - anOld.Perform(aBezier); - ASSERT_TRUE(anOld.IsDone()); - - Geom2dProp_Curve aProp(aBezier); - const Geom2dProp::CurveAnalysis aNewExt = aProp.FindCurvatureExtrema(); - const Geom2dProp::CurveAnalysis aNewInfl = aProp.FindInflections(); - ASSERT_TRUE(aNewExt.IsDone); - ASSERT_TRUE(aNewInfl.IsDone); - - const int aNewTotal = aNewExt.Points.Length() + aNewInfl.Points.Length(); - EXPECT_EQ(aNewTotal, anOld.NbPoints()); -} - -TEST(Geom2dProp_VsCurAndInf2dTest, Bezier_Quadratic_NoInflections) -{ - NCollection_Array1 aPoles(1, 3); - aPoles(1) = gp_Pnt2d(0.0, 0.0); - aPoles(2) = gp_Pnt2d(2.0, 4.0); - aPoles(3) = gp_Pnt2d(4.0, 0.0); - occ::handle aBezier = new Geom2d_BezierCurve(aPoles); - - Geom2dLProp_CurAndInf2d anOld; - anOld.PerformInf(aBezier); - ASSERT_TRUE(anOld.IsDone()); - - Geom2dProp_Curve aProp(aBezier); - const Geom2dProp::CurveAnalysis aNew = aProp.FindInflections(); - ASSERT_TRUE(aNew.IsDone); - - EXPECT_EQ(aNew.Points.Length(), anOld.NbPoints()); -} - -TEST(Geom2dProp_VsCurAndInf2dTest, Bezier_HighDegree_FullPerform) -{ - NCollection_Array1 aPoles(1, 6); - aPoles(1) = gp_Pnt2d(0.0, 0.0); - aPoles(2) = gp_Pnt2d(1.0, 3.0); - aPoles(3) = gp_Pnt2d(2.0, -1.0); - aPoles(4) = gp_Pnt2d(3.0, 2.0); - aPoles(5) = gp_Pnt2d(4.0, -2.0); - aPoles(6) = gp_Pnt2d(5.0, 1.0); - occ::handle aBezier = new Geom2d_BezierCurve(aPoles); - - Geom2dLProp_CurAndInf2d anOld; - anOld.Perform(aBezier); - ASSERT_TRUE(anOld.IsDone()); - - Geom2dProp_Curve aProp(aBezier); - const Geom2dProp::CurveAnalysis aNewExt = aProp.FindCurvatureExtrema(); - const Geom2dProp::CurveAnalysis aNewInfl = aProp.FindInflections(); - ASSERT_TRUE(aNewExt.IsDone); - ASSERT_TRUE(aNewInfl.IsDone); - - const int aNewTotal = aNewExt.Points.Length() + aNewInfl.Points.Length(); - EXPECT_EQ(aNewTotal, anOld.NbPoints()); -} - -// ============================================================================ -// BSpline - numeric with C3 interval subdivision -// ============================================================================ - -TEST(Geom2dProp_VsCurAndInf2dTest, BSpline_Degree4_FullPerform) -{ - NCollection_Array1 aPoles(1, 5); - aPoles(1) = gp_Pnt2d(0.0, 0.0); - aPoles(2) = gp_Pnt2d(1.0, 3.0); - aPoles(3) = gp_Pnt2d(2.0, -1.0); - aPoles(4) = gp_Pnt2d(3.0, 2.0); - aPoles(5) = gp_Pnt2d(4.0, 0.0); - - NCollection_Array1 aKnots(1, 2); - aKnots(1) = 0.0; - aKnots(2) = 1.0; - - NCollection_Array1 aMults(1, 2); - aMults(1) = 5; - aMults(2) = 5; - - occ::handle aBSpline = new Geom2d_BSplineCurve(aPoles, aKnots, aMults, 4); - - Geom2dLProp_CurAndInf2d anOld; - anOld.Perform(aBSpline); - ASSERT_TRUE(anOld.IsDone()); - - Geom2dProp_Curve aProp(aBSpline); - const Geom2dProp::CurveAnalysis aNewExt = aProp.FindCurvatureExtrema(); - const Geom2dProp::CurveAnalysis aNewInfl = aProp.FindInflections(); - ASSERT_TRUE(aNewExt.IsDone); - ASSERT_TRUE(aNewInfl.IsDone); - - const int aNewTotal = aNewExt.Points.Length() + aNewInfl.Points.Length(); - EXPECT_EQ(aNewTotal, anOld.NbPoints()); -} - -TEST(Geom2dProp_VsCurAndInf2dTest, BSpline_Cubic_Extrema) -{ - NCollection_Array1 aPoles(1, 6); - aPoles(1) = gp_Pnt2d(0.0, 0.0); - aPoles(2) = gp_Pnt2d(1.0, 3.0); - aPoles(3) = gp_Pnt2d(2.0, 1.0); - aPoles(4) = gp_Pnt2d(3.0, 4.0); - aPoles(5) = gp_Pnt2d(4.0, 2.0); - aPoles(6) = gp_Pnt2d(5.0, 0.0); - - NCollection_Array1 aKnots(1, 4); - aKnots(1) = 0.0; - aKnots(2) = 0.33; - aKnots(3) = 0.66; - aKnots(4) = 1.0; - - NCollection_Array1 aMults(1, 4); - aMults(1) = 4; - aMults(2) = 1; - aMults(3) = 1; - aMults(4) = 4; - - occ::handle aBSpline = new Geom2d_BSplineCurve(aPoles, aKnots, aMults, 3); - - Geom2dLProp_CurAndInf2d anOld; - anOld.PerformCurExt(aBSpline); - ASSERT_TRUE(anOld.IsDone()); - - Geom2dProp_Curve aProp(aBSpline); - const Geom2dProp::CurveAnalysis aNew = aProp.FindCurvatureExtrema(); - ASSERT_TRUE(aNew.IsDone); - - compareExtrema(aNew, anOld); -} - -TEST(Geom2dProp_VsCurAndInf2dTest, BSpline_Cubic_Inflections) -{ - NCollection_Array1 aPoles(1, 6); - aPoles(1) = gp_Pnt2d(0.0, 0.0); - aPoles(2) = gp_Pnt2d(1.0, 3.0); - aPoles(3) = gp_Pnt2d(2.0, 1.0); - aPoles(4) = gp_Pnt2d(3.0, 4.0); - aPoles(5) = gp_Pnt2d(4.0, 2.0); - aPoles(6) = gp_Pnt2d(5.0, 0.0); - - NCollection_Array1 aKnots(1, 4); - aKnots(1) = 0.0; - aKnots(2) = 0.33; - aKnots(3) = 0.66; - aKnots(4) = 1.0; - - NCollection_Array1 aMults(1, 4); - aMults(1) = 4; - aMults(2) = 1; - aMults(3) = 1; - aMults(4) = 4; - - occ::handle aBSpline = new Geom2d_BSplineCurve(aPoles, aKnots, aMults, 3); - - Geom2dLProp_CurAndInf2d anOld; - anOld.PerformInf(aBSpline); - ASSERT_TRUE(anOld.IsDone()); - - Geom2dProp_Curve aProp(aBSpline); - const Geom2dProp::CurveAnalysis aNew = aProp.FindInflections(); - ASSERT_TRUE(aNew.IsDone); - - compareExtrema(aNew, anOld); -} - -TEST(Geom2dProp_VsCurAndInf2dTest, BSpline_LowContinuity_FullPerform) -{ - NCollection_Array1 aPoles(1, 5); - aPoles(1) = gp_Pnt2d(0.0, 0.0); - aPoles(2) = gp_Pnt2d(1.0, 3.0); - aPoles(3) = gp_Pnt2d(2.0, 1.0); - aPoles(4) = gp_Pnt2d(3.0, 3.0); - aPoles(5) = gp_Pnt2d(4.0, 0.0); - - NCollection_Array1 aKnots(1, 4); - aKnots(1) = 0.0; - aKnots(2) = 0.33; - aKnots(3) = 0.66; - aKnots(4) = 1.0; - - NCollection_Array1 aMults(1, 4); - aMults(1) = 3; - aMults(2) = 1; - aMults(3) = 1; - aMults(4) = 3; - - occ::handle aBSpline = new Geom2d_BSplineCurve(aPoles, aKnots, aMults, 2); - - Geom2dLProp_CurAndInf2d anOld; - anOld.Perform(aBSpline); - ASSERT_TRUE(anOld.IsDone()); - - Geom2dProp_Curve aProp(aBSpline); - const Geom2dProp::CurveAnalysis aNewExt = aProp.FindCurvatureExtrema(); - const Geom2dProp::CurveAnalysis aNewInfl = aProp.FindInflections(); - ASSERT_TRUE(aNewExt.IsDone); - ASSERT_TRUE(aNewInfl.IsDone); - - const int aNewTotal = aNewExt.Points.Length() + aNewInfl.Points.Length(); - - // The new C3-subdivision solver analyzes each smooth interval independently, - // finding inflection points near knots that the old global solver misses. - // Verify the new API finds at least as many points as the old. - EXPECT_GE(aNewTotal, anOld.NbPoints()); - - // Verify all old points are found by the new API. - for (int i = 1; i <= anOld.NbPoints(); ++i) - { - const double anOldParam = anOld.Parameter(i); - bool aFound = false; - for (int j = 0; j < aNewExt.Points.Length(); ++j) - { - if (std::abs(aNewExt.Points[j].Parameter - anOldParam) < 1.0e-3) - { - aFound = true; - break; - } - } - if (!aFound) - { - for (int j = 0; j < aNewInfl.Points.Length(); ++j) - { - if (std::abs(aNewInfl.Points[j].Parameter - anOldParam) < 1.0e-3) - { - aFound = true; - break; - } - } - } - EXPECT_TRUE(aFound) << "Old point at param=" << anOldParam << " not found in new results"; - } -} - -// ============================================================================ -// Trimmed curve - should work through unwrapping -// ============================================================================ - -TEST(Geom2dProp_VsCurAndInf2dTest, TrimmedEllipse_Extrema) -{ - gp_Elips2d anElips(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 10.0, 5.0); - occ::handle anEllipse = new Geom2d_Ellipse(anElips); - occ::handle aTrimmed = new Geom2d_TrimmedCurve(anEllipse, 0.0, M_PI); - - Geom2dLProp_CurAndInf2d anOld; - anOld.PerformCurExt(aTrimmed); - ASSERT_TRUE(anOld.IsDone()); - - Geom2dProp_Curve aProp(aTrimmed); - const Geom2dProp::CurveAnalysis aNew = aProp.FindCurvatureExtrema(); - ASSERT_TRUE(aNew.IsDone); - - compareExtrema(aNew, anOld, 1.0e-6); -} - -TEST(Geom2dProp_VsCurAndInf2dTest, TrimmedBezier_FullPerform) -{ - NCollection_Array1 aPoles(1, 4); - aPoles(1) = gp_Pnt2d(0.0, 0.0); - aPoles(2) = gp_Pnt2d(1.0, 3.0); - aPoles(3) = gp_Pnt2d(3.0, -1.0); - aPoles(4) = gp_Pnt2d(4.0, 1.0); - occ::handle aBezier = new Geom2d_BezierCurve(aPoles); - occ::handle aTrimmed = new Geom2d_TrimmedCurve(aBezier, 0.1, 0.9); - - Geom2dLProp_CurAndInf2d anOld; - anOld.Perform(aTrimmed); - ASSERT_TRUE(anOld.IsDone()); - - Geom2dProp_Curve aProp(aTrimmed); - const Geom2dProp::CurveAnalysis aNewExt = aProp.FindCurvatureExtrema(); - const Geom2dProp::CurveAnalysis aNewInfl = aProp.FindInflections(); - ASSERT_TRUE(aNewExt.IsDone); - ASSERT_TRUE(aNewInfl.IsDone); - - const int aNewTotal = aNewExt.Points.Length() + aNewInfl.Points.Length(); - EXPECT_EQ(aNewTotal, anOld.NbPoints()); -} - -// ============================================================================ -// Offset curve - numeric -// ============================================================================ - -TEST(Geom2dProp_VsCurAndInf2dTest, OffsetEllipse_Extrema) -{ - gp_Elips2d anElips(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 10.0, 5.0); - occ::handle anEllipse = new Geom2d_Ellipse(anElips); - occ::handle anOffset = new Geom2d_OffsetCurve(anEllipse, 1.0); - - Geom2dLProp_CurAndInf2d anOld; - anOld.PerformCurExt(anOffset); - ASSERT_TRUE(anOld.IsDone()); - - Geom2dProp_Curve aProp(anOffset); - const Geom2dProp::CurveAnalysis aNew = aProp.FindCurvatureExtrema(); - ASSERT_TRUE(aNew.IsDone); - - compareExtrema(aNew, anOld); -} - -TEST(Geom2dProp_VsCurAndInf2dTest, OffsetEllipse_Inflections) -{ - gp_Elips2d anElips(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 10.0, 5.0); - occ::handle anEllipse = new Geom2d_Ellipse(anElips); - occ::handle anOffset = new Geom2d_OffsetCurve(anEllipse, 1.0); - - Geom2dLProp_CurAndInf2d anOld; - anOld.PerformInf(anOffset); - ASSERT_TRUE(anOld.IsDone()); - - Geom2dProp_Curve aProp(anOffset); - const Geom2dProp::CurveAnalysis aNew = aProp.FindInflections(); - ASSERT_TRUE(aNew.IsDone); - - EXPECT_EQ(aNew.Points.Length(), anOld.NbPoints()); -} - -TEST(Geom2dProp_VsCurAndInf2dTest, OffsetCircle_NoExtrema) -{ - gp_Circ2d aCirc(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 5.0); - occ::handle aCircle = new Geom2d_Circle(aCirc); - occ::handle anOffset = new Geom2d_OffsetCurve(aCircle, 2.0); - - Geom2dLProp_CurAndInf2d anOld; - anOld.PerformCurExt(anOffset); - ASSERT_TRUE(anOld.IsDone()); - - Geom2dProp_Curve aProp(anOffset); - const Geom2dProp::CurveAnalysis aNew = aProp.FindCurvatureExtrema(); - ASSERT_TRUE(aNew.IsDone); - - EXPECT_EQ(aNew.Points.Length(), anOld.NbPoints()); -} diff --git a/src/ModelingData/TKG2d/Geom2dProp/FILES.cmake b/src/ModelingData/TKG2d/Geom2dProp/FILES.cmake deleted file mode 100644 index 6663bb0219..0000000000 --- a/src/ModelingData/TKG2d/Geom2dProp/FILES.cmake +++ /dev/null @@ -1,26 +0,0 @@ -# Source files for Geom2dProp package -set(OCCT_Geom2dProp_FILES_LOCATION "${CMAKE_CURRENT_LIST_DIR}") - -set(OCCT_Geom2dProp_FILES - Geom2dProp.hxx - Geom2dProp.cxx - Geom2dProp_BezierCurve.hxx - Geom2dProp_BezierCurve.cxx - Geom2dProp_CurveAnalysisTools.pxx - Geom2dProp_BSplineCurve.hxx - Geom2dProp_BSplineCurve.cxx - Geom2dProp_Circle.hxx - Geom2dProp_Curve.hxx - Geom2dProp_Curve.cxx - Geom2dProp_Ellipse.hxx - Geom2dProp_Ellipse.cxx - Geom2dProp_Hyperbola.hxx - Geom2dProp_Hyperbola.cxx - Geom2dProp_Line.hxx - Geom2dProp_OffsetCurve.hxx - Geom2dProp_OffsetCurve.cxx - Geom2dProp_OtherCurve.hxx - Geom2dProp_OtherCurve.cxx - Geom2dProp_Parabola.hxx - Geom2dProp_Parabola.cxx -) diff --git a/src/ModelingData/TKG2d/Geom2dProp/Geom2dProp.cxx b/src/ModelingData/TKG2d/Geom2dProp/Geom2dProp.cxx deleted file mode 100644 index 577f84c797..0000000000 --- a/src/ModelingData/TKG2d/Geom2dProp/Geom2dProp.cxx +++ /dev/null @@ -1,164 +0,0 @@ -// 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 - -#include - -//================================================================================================= - -Geom2dProp::TangentResult Geom2dProp::ComputeTangent(const gp_Vec2d& theD1, - const gp_Vec2d& theD2, - const gp_Vec2d& theD3, - const double theTol) -{ - const double aTol2 = theTol * theTol; - - // Try first derivative - if (theD1.SquareMagnitude() > aTol2) - { - return {gp_Dir2d(theD1), true}; - } - - // Try second derivative - if (theD2.SquareMagnitude() > aTol2) - { - return {gp_Dir2d(theD2), true}; - } - - // Try third derivative - if (theD3.SquareMagnitude() > aTol2) - { - return {gp_Dir2d(theD3), true}; - } - - return {{}, false}; -} - -//================================================================================================= - -Geom2dProp::TangentResult Geom2dProp::ComputeTangent(const gp_Vec2d& theD1, - const gp_Vec2d& theD2, - const gp_Vec2d& theD3, - const double theTol, - const gp_Pnt2d& thePntBefore, - const gp_Pnt2d& thePntAfter) -{ - const double aTol2 = theTol * theTol; - - // If D1 is non-null, use it directly (no sign ambiguity). - if (theD1.SquareMagnitude() > aTol2) - { - return {gp_Dir2d(theD1), true}; - } - - // D1 is null: find first non-null higher derivative. - gp_Vec2d aVec; - if (theD2.SquareMagnitude() > aTol2) - aVec = theD2; - else if (theD3.SquareMagnitude() > aTol2) - aVec = theD3; - else - return {{}, false}; - - // Correct sign of higher-order derivative using finite-difference direction. - const gp_Vec2d aFiniteDiff(thePntBefore, thePntAfter); - if (aVec.Dot(aFiniteDiff) < 0.0) - aVec.Reverse(); - - return {gp_Dir2d(aVec), true}; -} - -//================================================================================================= - -Geom2dProp::CurvatureResult Geom2dProp::ComputeCurvature(const gp_Vec2d& theD1, - const gp_Vec2d& theD2, - const double theTol) -{ - const double aTol2 = theTol * theTol; - const double aDD1 = theD1.SquareMagnitude(); - - // If first derivative is null, curvature is infinite (singular point). - if (aDD1 <= aTol2) - { - return {0.0, true, true}; - } - - const double aDD2 = theD2.SquareMagnitude(); - - // If second derivative is null, curvature is zero. - if (aDD2 <= aTol2) - { - return {0.0, true, false}; - } - - const double aN = theD1.CrossSquareMagnitude(theD2); - - // If D1 and D2 are collinear, curvature is zero. - const double aT = aN / aDD1 / aDD2; - if (aT <= aTol2) - { - return {0.0, true, false}; - } - - // Legacy Geom2dLProp compatibility: curvature is unsigned. - const double aCurvature = std::sqrt(aN) / aDD1 / std::sqrt(aDD1); - return {aCurvature, true, false}; -} - -//================================================================================================= - -Geom2dProp::NormalResult Geom2dProp::ComputeNormal(const gp_Vec2d& theD1, - const gp_Vec2d& theD2, - const double theTol) -{ - const CurvatureResult aCurvRes = ComputeCurvature(theD1, theD2, theTol); - if (!aCurvRes.IsDefined || aCurvRes.IsInfinite || std::abs(aCurvRes.Value) <= theTol) - { - return {{}, false}; - } - - gp_Vec2d aNorm = theD2.Multiplied(theD1.Dot(theD1)); - aNorm.Subtract(theD1.Multiplied(theD1.Dot(theD2))); - if (aNorm.SquareMagnitude() <= theTol * theTol) - { - return {{}, false}; - } - return {gp_Dir2d(aNorm), true}; -} - -//================================================================================================= - -Geom2dProp::CentreResult Geom2dProp::ComputeCentreOfCurvature(const gp_Pnt2d& thePnt, - const gp_Vec2d& theD1, - const gp_Vec2d& theD2, - const double theTol) -{ - const CurvatureResult aCurvRes = ComputeCurvature(theD1, theD2, theTol); - if (!aCurvRes.IsDefined || aCurvRes.IsInfinite || std::abs(aCurvRes.Value) <= theTol) - { - return {{}, false}; - } - - gp_Vec2d aNorm = theD2.Multiplied(theD1.Dot(theD1)); - aNorm.Subtract(theD1.Multiplied(theD1.Dot(theD2))); - if (aNorm.SquareMagnitude() <= theTol * theTol) - { - return {{}, false}; - } - - aNorm.Normalize(); - aNorm.Divide(aCurvRes.Value); - - return {thePnt.Translated(aNorm), true}; -} diff --git a/src/ModelingData/TKG2d/Geom2dProp/Geom2dProp.hxx b/src/ModelingData/TKG2d/Geom2dProp/Geom2dProp.hxx deleted file mode 100644 index 7958273271..0000000000 --- a/src/ModelingData/TKG2d/Geom2dProp/Geom2dProp.hxx +++ /dev/null @@ -1,201 +0,0 @@ -// 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. - -#ifndef _Geom2dProp_HeaderFile -#define _Geom2dProp_HeaderFile - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -//! @brief Namespace containing result structures and free functions for 2D curve -//! differential property computation. -//! -//! Provides lightweight result structures with explicit validity flags instead of -//! exception-based APIs, and geometry-agnostic free functions that compute local -//! differential properties from derivative vectors. -namespace Geom2dProp -{ - -//! Parameter domain for a 2D curve (used for trimmed curves). -struct CurveDomain -{ - double First; //!< First parameter - double Last; //!< Last parameter -}; - -//! Result of tangent direction computation. -struct TangentResult -{ - gp_Dir2d Direction; //!< Tangent direction (valid only when IsDefined is true) - bool IsDefined = false; //!< True if the tangent is well-defined -}; - -//! Result of curvature computation. -struct CurvatureResult -{ - double Value = 0.0; //!< Curvature value (valid only when IsDefined is true) - bool IsDefined = false; //!< True if curvature could be computed - bool IsInfinite = false; //!< True if first derivative is null (singular point) -}; - -//! Result of normal direction computation. -struct NormalResult -{ - gp_Dir2d Direction; //!< Normal direction (valid only when IsDefined is true) - bool IsDefined = false; //!< True if the normal is well-defined -}; - -//! Result of centre of curvature computation. -struct CentreResult -{ - gp_Pnt2d Centre; //!< Centre of curvature (valid only when IsDefined is true) - bool IsDefined = false; //!< True if the centre is well-defined -}; - -//! Type of a special curve point (curvature extremum or inflection). -enum class CIType -{ - Inflection, //!< Inflection point (curvature changes sign) - MinCurvature, //!< Local minimum of the radius of curvature (maximum of |curvature|) - MaxCurvature //!< Local maximum of the radius of curvature (minimum of |curvature|) -}; - -//! A special point on a curve with its parameter and type. -struct CurveSpecialPoint -{ - double Parameter = 0.0; //!< Curve parameter - CIType Type = CIType::Inflection; //!< Point type -}; - -//! Result of global curve analysis (curvature extrema and inflection points). -struct CurveAnalysis -{ - NCollection_DynamicArray Points; //!< Special points sorted by parameter - bool IsDone = false; //!< True if analysis completed -}; - -// ============================================================================ -// Derivative caching -// ============================================================================ - -//! Derivative order for 2D curve property caching. -//! Values must match std::variant alternative indices in CurveCache::Data. -enum class CurveDerivOrder -{ - Undefined = 0, //!< No caching specified (monostate) - Value = 1, //!< Cache point only (gp_Pnt2d) - Tangent = 2, //!< Cache up to D1 (Geom2d_Curve::ResD1) - Curvature = 3, //!< Cache up to D2 (Geom2d_Curve::ResD2) - CurvatureDeriv = 4 //!< Cache up to D3 (Geom2d_Curve::ResD3) -}; - -//! Cached 2D curve derivatives at a parameter value. -//! @note The variant alternative indices must match CurveDerivOrder enum values. -struct CurveCache -{ - double Param = std::numeric_limits::quiet_NaN(); - std:: - variant - Data; - - bool IsValid(double theParam) const { return Param == theParam; } - - CurveDerivOrder Order() const { return static_cast(Data.index()); } - - bool HasOrder(CurveDerivOrder theNeeded) const - { - return static_cast(Order()) >= static_cast(theNeeded); - } - - void Invalidate() - { - Param = std::numeric_limits::quiet_NaN(); - Data.emplace(); - } -}; - -//! Compute tangent direction from derivative vectors. -//! Tries D1 first; if D1 magnitude^2 <= theTol^2, tries D2, then D3. -//! @note When D1 is null and a higher-order derivative is used, the sign of -//! the direction may be wrong. Use the overload with finite-difference points -//! for sign correction when the curve parameterization is available. -//! @param[in] theD1 first derivative vector -//! @param[in] theD2 second derivative vector -//! @param[in] theD3 third derivative vector -//! @param[in] theTol linear tolerance for zero-vector detection -//! @return tangent result with validity flag -Standard_EXPORT TangentResult ComputeTangent(const gp_Vec2d& theD1, - const gp_Vec2d& theD2, - const gp_Vec2d& theD3, - double theTol); - -//! Compute tangent direction with sign correction for higher-order derivatives. -//! Same as ComputeTangent, but when D1 is null and a higher-order derivative is -//! used, corrects the sign by comparing with a finite-difference direction vector. -//! @param[in] theD1 first derivative vector -//! @param[in] theD2 second derivative vector -//! @param[in] theD3 third derivative vector -//! @param[in] theTol linear tolerance for zero-vector detection -//! @param[in] thePntBefore point on the curve before the evaluation point -//! @param[in] thePntAfter point on the curve after the evaluation point -//! @return tangent result with validity flag and corrected sign -Standard_EXPORT TangentResult ComputeTangent(const gp_Vec2d& theD1, - const gp_Vec2d& theD2, - const gp_Vec2d& theD3, - double theTol, - const gp_Pnt2d& thePntBefore, - const gp_Pnt2d& thePntAfter); - -//! Compute curvature from first and second derivative vectors. -//! Curvature = |D1 x D2| / |D1|^3 -//! @param[in] theD1 first derivative vector -//! @param[in] theD2 second derivative vector -//! @param[in] theTol linear tolerance for zero-vector detection -//! @return curvature result with validity and infinity flags -Standard_EXPORT CurvatureResult ComputeCurvature(const gp_Vec2d& theD1, - const gp_Vec2d& theD2, - double theTol); - -//! Compute normal direction from first and second derivative vectors. -//! Normal = D1 x (D2 x D1) (normalized), perpendicular to tangent pointing toward center. -//! @param[in] theD1 first derivative vector -//! @param[in] theD2 second derivative vector -//! @param[in] theTol linear tolerance for zero-vector detection -//! @return normal result with validity flag -Standard_EXPORT NormalResult ComputeNormal(const gp_Vec2d& theD1, - const gp_Vec2d& theD2, - double theTol); - -//! Compute centre of curvature from point and derivative vectors. -//! Centre = Point + Normal / Curvature -//! @param[in] thePnt point on the curve -//! @param[in] theD1 first derivative vector -//! @param[in] theD2 second derivative vector -//! @param[in] theTol linear tolerance for zero-vector detection -//! @return centre result with validity flag -Standard_EXPORT CentreResult ComputeCentreOfCurvature(const gp_Pnt2d& thePnt, - const gp_Vec2d& theD1, - const gp_Vec2d& theD2, - double theTol); - -} // namespace Geom2dProp - -#endif // _Geom2dProp_HeaderFile diff --git a/src/ModelingData/TKG2d/Geom2dProp/Geom2dProp_BSplineCurve.cxx b/src/ModelingData/TKG2d/Geom2dProp/Geom2dProp_BSplineCurve.cxx deleted file mode 100644 index 4c7d2e1fb2..0000000000 --- a/src/ModelingData/TKG2d/Geom2dProp/Geom2dProp_BSplineCurve.cxx +++ /dev/null @@ -1,125 +0,0 @@ -// 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 -#include - -#include - -//================================================================================================= - -Geom2dProp::TangentResult Geom2dProp_BSplineCurve::Tangent(const double theParam, - const double theTol) const -{ - if (!myCurve.IsNull()) - { - return Geom2dProp_CurveAnalysisTools::EvaluateTangentCached(myCurve.get(), - theParam, - theTol, - myRequestedOrder, - myCache); - } - return Geom2dProp_CurveAnalysisTools::EvaluateTangentCached(myAdaptor, - theParam, - theTol, - myRequestedOrder, - myCache); -} - -//================================================================================================= - -Geom2dProp::CurvatureResult Geom2dProp_BSplineCurve::Curvature(const double theParam, - const double theTol) const -{ - if (!myCurve.IsNull()) - { - return Geom2dProp_CurveAnalysisTools::EvaluateCurvatureCached(myCurve.get(), - theParam, - theTol, - myRequestedOrder, - myCache); - } - return Geom2dProp_CurveAnalysisTools::EvaluateCurvatureCached(myAdaptor, - theParam, - theTol, - myRequestedOrder, - myCache); -} - -//================================================================================================= - -Geom2dProp::NormalResult Geom2dProp_BSplineCurve::Normal(const double theParam, - const double theTol) const -{ - if (!myCurve.IsNull()) - { - return Geom2dProp_CurveAnalysisTools::EvaluateNormalCached(myCurve.get(), - theParam, - theTol, - myRequestedOrder, - myCache); - } - return Geom2dProp_CurveAnalysisTools::EvaluateNormalCached(myAdaptor, - theParam, - theTol, - myRequestedOrder, - myCache); -} - -//================================================================================================= - -Geom2dProp::CentreResult Geom2dProp_BSplineCurve::CentreOfCurvature(const double theParam, - const double theTol) const -{ - if (!myCurve.IsNull()) - { - return Geom2dProp_CurveAnalysisTools::EvaluateCentreOfCurvatureCached(myCurve.get(), - theParam, - theTol, - myRequestedOrder, - myCache); - } - return Geom2dProp_CurveAnalysisTools::EvaluateCentreOfCurvatureCached(myAdaptor, - theParam, - theTol, - myRequestedOrder, - myCache); -} - -//================================================================================================= - -Geom2dProp::CurveAnalysis Geom2dProp_BSplineCurve::FindCurvatureExtrema() const -{ - if (!myCurve.IsNull()) - { - const double aFirst = myDomain.has_value() ? myDomain->First : myCurve->FirstParameter(); - const double aLast = myDomain.has_value() ? myDomain->Last : myCurve->LastParameter(); - Geom2dAdaptor_Curve anAdaptor(myCurve, aFirst, aLast); - return Geom2dProp_CurveAnalysisTools::FindCurvatureExtremaBySpans(&anAdaptor, GeomAbs_C3); - } - return Geom2dProp_CurveAnalysisTools::FindCurvatureExtremaBySpans(myAdaptor, GeomAbs_C3); -} - -//================================================================================================= - -Geom2dProp::CurveAnalysis Geom2dProp_BSplineCurve::FindInflections() const -{ - if (!myCurve.IsNull()) - { - const double aFirst = myDomain.has_value() ? myDomain->First : myCurve->FirstParameter(); - const double aLast = myDomain.has_value() ? myDomain->Last : myCurve->LastParameter(); - Geom2dAdaptor_Curve anAdaptor(myCurve, aFirst, aLast); - return Geom2dProp_CurveAnalysisTools::FindInflectionsBySpans(&anAdaptor, GeomAbs_C3); - } - return Geom2dProp_CurveAnalysisTools::FindInflectionsBySpans(myAdaptor, GeomAbs_C3); -} diff --git a/src/ModelingData/TKG2d/Geom2dProp/Geom2dProp_BSplineCurve.hxx b/src/ModelingData/TKG2d/Geom2dProp/Geom2dProp_BSplineCurve.hxx deleted file mode 100644 index d90e37d197..0000000000 --- a/src/ModelingData/TKG2d/Geom2dProp/Geom2dProp_BSplineCurve.hxx +++ /dev/null @@ -1,109 +0,0 @@ -// 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. - -#ifndef _Geom2dProp_BSplineCurve_HeaderFile -#define _Geom2dProp_BSplineCurve_HeaderFile - -#include -#include -#include -#include -#include - -#include - -//! @brief Local differential properties for a 2D B-spline curve. -//! -//! Uses numeric root-finding for curvature extrema and inflection points. -//! For B-splines with continuity less than C3, the parameter range is subdivided -//! into C3 intervals for more robust root-finding. -//! -//! Can be constructed from either a Geom2dAdaptor_Curve pointer or a occ::handle. -//! When constructed from a handle, no adaptor is created; for complex methods -//! (FindCurvatureExtrema, FindInflections) a stack-local adaptor is created on demand. -class Geom2dProp_BSplineCurve -{ -public: - DEFINE_STANDARD_ALLOC - - //! Constructor with adaptor pointer (non-owning). - //! @param theAdaptor the 2D curve adaptor (must wrap a B-spline curve, must not be null) - Geom2dProp_BSplineCurve( - const Geom2dAdaptor_Curve* theAdaptor, - Geom2dProp::CurveDerivOrder theOrder = Geom2dProp::CurveDerivOrder::Curvature) - : myAdaptor(theAdaptor), - myRequestedOrder(theOrder) - { - } - - //! Constructor from geometry handle. - //! @param theCurve the 2D B-spline curve geometry - //! @param theDomain optional parameter domain (for trimmed curves) - Geom2dProp_BSplineCurve( - const occ::handle& theCurve, - const std::optional& theDomain = std::nullopt, - Geom2dProp::CurveDerivOrder theOrder = Geom2dProp::CurveDerivOrder::Curvature) - : myAdaptor(nullptr), - myRequestedOrder(theOrder), - myCurve(theCurve), - myDomain(theDomain) - { - } - - //! Non-copyable and non-movable. - Geom2dProp_BSplineCurve(const Geom2dProp_BSplineCurve&) = delete; - Geom2dProp_BSplineCurve& operator=(const Geom2dProp_BSplineCurve&) = delete; - Geom2dProp_BSplineCurve(Geom2dProp_BSplineCurve&&) = delete; - Geom2dProp_BSplineCurve& operator=(Geom2dProp_BSplineCurve&&) = delete; - - //! Sets the derivative caching order. - void SetDerivOrder(Geom2dProp::CurveDerivOrder theOrder) { myRequestedOrder = theOrder; } - - //! Returns the derivative caching order. - Geom2dProp::CurveDerivOrder DerivOrder() const { return myRequestedOrder; } - - //! Returns the adaptor pointer (nullptr when constructed from handle). - const Geom2dAdaptor_Curve* Adaptor() const { return myAdaptor; } - - //! Returns pointer to underlying geometry, or nullptr if constructed from adaptor. - const Geom2d_Curve* Geometry() const { return myCurve.get(); } - - //! Compute tangent at given parameter. - Standard_EXPORT Geom2dProp::TangentResult Tangent(double theParam, double theTol) const; - - //! Compute curvature at given parameter. - Standard_EXPORT Geom2dProp::CurvatureResult Curvature(double theParam, double theTol) const; - - //! Compute normal at given parameter. - Standard_EXPORT Geom2dProp::NormalResult Normal(double theParam, double theTol) const; - - //! Compute centre of curvature at given parameter. - Standard_EXPORT Geom2dProp::CentreResult CentreOfCurvature(double theParam, double theTol) const; - - //! Find curvature extrema using numeric root-finding. - //! For non-C3 B-splines, subdivides into C3 intervals. - Standard_EXPORT Geom2dProp::CurveAnalysis FindCurvatureExtrema() const; - - //! Find inflection points using numeric root-finding. - //! For non-C3 B-splines, subdivides into C3 intervals. - Standard_EXPORT Geom2dProp::CurveAnalysis FindInflections() const; - -private: - const Geom2dAdaptor_Curve* myAdaptor; - Geom2dProp::CurveDerivOrder myRequestedOrder; - mutable Geom2dProp::CurveCache myCache; - occ::handle myCurve; //!< Geometry handle (handle path) - std::optional myDomain; //!< Optional parameter domain -}; - -#endif // _Geom2dProp_BSplineCurve_HeaderFile diff --git a/src/ModelingData/TKG2d/Geom2dProp/Geom2dProp_BezierCurve.cxx b/src/ModelingData/TKG2d/Geom2dProp/Geom2dProp_BezierCurve.cxx deleted file mode 100644 index 817ba5c0b3..0000000000 --- a/src/ModelingData/TKG2d/Geom2dProp/Geom2dProp_BezierCurve.cxx +++ /dev/null @@ -1,124 +0,0 @@ -// 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 -#include - -//================================================================================================= - -Geom2dProp::TangentResult Geom2dProp_BezierCurve::Tangent(const double theParam, - const double theTol) const -{ - if (!myCurve.IsNull()) - { - return Geom2dProp_CurveAnalysisTools::EvaluateTangentCached(myCurve.get(), - theParam, - theTol, - myRequestedOrder, - myCache); - } - return Geom2dProp_CurveAnalysisTools::EvaluateTangentCached(myAdaptor, - theParam, - theTol, - myRequestedOrder, - myCache); -} - -//================================================================================================= - -Geom2dProp::CurvatureResult Geom2dProp_BezierCurve::Curvature(const double theParam, - const double theTol) const -{ - if (!myCurve.IsNull()) - { - return Geom2dProp_CurveAnalysisTools::EvaluateCurvatureCached(myCurve.get(), - theParam, - theTol, - myRequestedOrder, - myCache); - } - return Geom2dProp_CurveAnalysisTools::EvaluateCurvatureCached(myAdaptor, - theParam, - theTol, - myRequestedOrder, - myCache); -} - -//================================================================================================= - -Geom2dProp::NormalResult Geom2dProp_BezierCurve::Normal(const double theParam, - const double theTol) const -{ - if (!myCurve.IsNull()) - { - return Geom2dProp_CurveAnalysisTools::EvaluateNormalCached(myCurve.get(), - theParam, - theTol, - myRequestedOrder, - myCache); - } - return Geom2dProp_CurveAnalysisTools::EvaluateNormalCached(myAdaptor, - theParam, - theTol, - myRequestedOrder, - myCache); -} - -//================================================================================================= - -Geom2dProp::CentreResult Geom2dProp_BezierCurve::CentreOfCurvature(const double theParam, - const double theTol) const -{ - if (!myCurve.IsNull()) - { - return Geom2dProp_CurveAnalysisTools::EvaluateCentreOfCurvatureCached(myCurve.get(), - theParam, - theTol, - myRequestedOrder, - myCache); - } - return Geom2dProp_CurveAnalysisTools::EvaluateCentreOfCurvatureCached(myAdaptor, - theParam, - theTol, - myRequestedOrder, - myCache); -} - -//================================================================================================= - -Geom2dProp::CurveAnalysis Geom2dProp_BezierCurve::FindCurvatureExtrema() const -{ - if (!myCurve.IsNull()) - { - // Create a stack-local adaptor for the span-based numeric search. - const double aFirst = myDomain.has_value() ? myDomain->First : myCurve->FirstParameter(); - const double aLast = myDomain.has_value() ? myDomain->Last : myCurve->LastParameter(); - Geom2dAdaptor_Curve anAdaptor(myCurve, aFirst, aLast); - return Geom2dProp_CurveAnalysisTools::FindCurvatureExtrema(&anAdaptor); - } - return Geom2dProp_CurveAnalysisTools::FindCurvatureExtrema(myAdaptor); -} - -//================================================================================================= - -Geom2dProp::CurveAnalysis Geom2dProp_BezierCurve::FindInflections() const -{ - if (!myCurve.IsNull()) - { - const double aFirst = myDomain.has_value() ? myDomain->First : myCurve->FirstParameter(); - const double aLast = myDomain.has_value() ? myDomain->Last : myCurve->LastParameter(); - Geom2dAdaptor_Curve anAdaptor(myCurve, aFirst, aLast); - return Geom2dProp_CurveAnalysisTools::FindInflections(&anAdaptor); - } - return Geom2dProp_CurveAnalysisTools::FindInflections(myAdaptor); -} diff --git a/src/ModelingData/TKG2d/Geom2dProp/Geom2dProp_BezierCurve.hxx b/src/ModelingData/TKG2d/Geom2dProp/Geom2dProp_BezierCurve.hxx deleted file mode 100644 index 2dd3be850c..0000000000 --- a/src/ModelingData/TKG2d/Geom2dProp/Geom2dProp_BezierCurve.hxx +++ /dev/null @@ -1,105 +0,0 @@ -// 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. - -#ifndef _Geom2dProp_BezierCurve_HeaderFile -#define _Geom2dProp_BezierCurve_HeaderFile - -#include -#include -#include -#include -#include - -#include - -//! @brief Local differential properties for a 2D Bezier curve. -//! -//! Uses numeric root-finding for curvature extrema and inflection points. -//! -//! Can be constructed from either a Geom2dAdaptor_Curve pointer or a occ::handle. -//! When constructed from a handle, no adaptor is created; for complex methods -//! (FindCurvatureExtrema, FindInflections) a stack-local adaptor is created on demand. -class Geom2dProp_BezierCurve -{ -public: - DEFINE_STANDARD_ALLOC - - //! Constructor with adaptor pointer (non-owning). - //! @param theAdaptor the 2D curve adaptor (must wrap a Bezier curve, must not be null) - Geom2dProp_BezierCurve( - const Geom2dAdaptor_Curve* theAdaptor, - Geom2dProp::CurveDerivOrder theOrder = Geom2dProp::CurveDerivOrder::Curvature) - : myAdaptor(theAdaptor), - myRequestedOrder(theOrder) - { - } - - //! Constructor from geometry handle. - //! @param theCurve the 2D Bezier curve geometry - //! @param theDomain optional parameter domain (for trimmed curves) - Geom2dProp_BezierCurve( - const occ::handle& theCurve, - const std::optional& theDomain = std::nullopt, - Geom2dProp::CurveDerivOrder theOrder = Geom2dProp::CurveDerivOrder::Curvature) - : myAdaptor(nullptr), - myRequestedOrder(theOrder), - myCurve(theCurve), - myDomain(theDomain) - { - } - - //! Non-copyable and non-movable. - Geom2dProp_BezierCurve(const Geom2dProp_BezierCurve&) = delete; - Geom2dProp_BezierCurve& operator=(const Geom2dProp_BezierCurve&) = delete; - Geom2dProp_BezierCurve(Geom2dProp_BezierCurve&&) = delete; - Geom2dProp_BezierCurve& operator=(Geom2dProp_BezierCurve&&) = delete; - - //! Sets the derivative caching order. - void SetDerivOrder(Geom2dProp::CurveDerivOrder theOrder) { myRequestedOrder = theOrder; } - - //! Returns the derivative caching order. - Geom2dProp::CurveDerivOrder DerivOrder() const { return myRequestedOrder; } - - //! Returns the adaptor pointer (nullptr when constructed from handle). - const Geom2dAdaptor_Curve* Adaptor() const { return myAdaptor; } - - //! Returns pointer to underlying geometry, or nullptr if constructed from adaptor. - const Geom2d_Curve* Geometry() const { return myCurve.get(); } - - //! Compute tangent at given parameter. - Standard_EXPORT Geom2dProp::TangentResult Tangent(double theParam, double theTol) const; - - //! Compute curvature at given parameter. - Standard_EXPORT Geom2dProp::CurvatureResult Curvature(double theParam, double theTol) const; - - //! Compute normal at given parameter. - Standard_EXPORT Geom2dProp::NormalResult Normal(double theParam, double theTol) const; - - //! Compute centre of curvature at given parameter. - Standard_EXPORT Geom2dProp::CentreResult CentreOfCurvature(double theParam, double theTol) const; - - //! Find curvature extrema using numeric root-finding. - Standard_EXPORT Geom2dProp::CurveAnalysis FindCurvatureExtrema() const; - - //! Find inflection points using numeric root-finding. - Standard_EXPORT Geom2dProp::CurveAnalysis FindInflections() const; - -private: - const Geom2dAdaptor_Curve* myAdaptor; - Geom2dProp::CurveDerivOrder myRequestedOrder; - mutable Geom2dProp::CurveCache myCache; - occ::handle myCurve; //!< Geometry handle (handle path) - std::optional myDomain; //!< Optional parameter domain -}; - -#endif // _Geom2dProp_BezierCurve_HeaderFile diff --git a/src/ModelingData/TKG2d/Geom2dProp/Geom2dProp_Circle.hxx b/src/ModelingData/TKG2d/Geom2dProp/Geom2dProp_Circle.hxx deleted file mode 100644 index e80e210f3e..0000000000 --- a/src/ModelingData/TKG2d/Geom2dProp/Geom2dProp_Circle.hxx +++ /dev/null @@ -1,164 +0,0 @@ -// 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. - -#ifndef _Geom2dProp_Circle_HeaderFile -#define _Geom2dProp_Circle_HeaderFile - -#include -#include -#include -#include - -#include - -//! @brief Local differential properties for a 2D circle. -//! -//! A circle has constant curvature = 1/R, well-defined tangent and normal -//! at every point, and no curvature extrema or inflection points. -//! -//! Can be constructed from either a Geom2dAdaptor_Curve pointer or a occ::handle. -//! When constructed from a handle, no adaptor is created. -class Geom2dProp_Circle -{ -public: - DEFINE_STANDARD_ALLOC - - //! Constructor with adaptor pointer (non-owning). - //! @param theAdaptor the 2D curve adaptor (must wrap a circle, must not be null) - Geom2dProp_Circle(const Geom2dAdaptor_Curve* theAdaptor, - Geom2dProp::CurveDerivOrder theOrder = Geom2dProp::CurveDerivOrder::Undefined) - : myAdaptor(theAdaptor), - myRadius(theAdaptor->Circle().Radius()), - myCenter(theAdaptor->Circle().Location()) - { - (void)theOrder; - } - - //! Constructor from geometry handle. - //! @param theCurve the 2D circle geometry (must be a Geom2d_Circle or downcastable to it) - //! @param theDomain optional parameter domain (unused for circle) - Geom2dProp_Circle(const occ::handle& theCurve, - const std::optional& theDomain = std::nullopt, - Geom2dProp::CurveDerivOrder theOrder = Geom2dProp::CurveDerivOrder::Undefined) - : myAdaptor(nullptr), - myCurve(theCurve) - { - (void)theDomain; - (void)theOrder; - const occ::handle aCircle = occ::down_cast(theCurve); - myRadius = aCircle->Radius(); - myCenter = aCircle->Circ2d().Location(); - } - - //! Non-copyable and non-movable. - Geom2dProp_Circle(const Geom2dProp_Circle&) = delete; - Geom2dProp_Circle& operator=(const Geom2dProp_Circle&) = delete; - Geom2dProp_Circle(Geom2dProp_Circle&&) = delete; - Geom2dProp_Circle& operator=(Geom2dProp_Circle&&) = delete; - - //! Sets the derivative caching order (no-op for analytical curves). - void SetDerivOrder(Geom2dProp::CurveDerivOrder) {} - - //! Returns the derivative caching order (always Undefined for analytical curves). - Geom2dProp::CurveDerivOrder DerivOrder() const { return Geom2dProp::CurveDerivOrder::Undefined; } - - //! Returns the adaptor pointer (nullptr when constructed from handle). - const Geom2dAdaptor_Curve* Adaptor() const { return myAdaptor; } - - //! Returns pointer to underlying geometry, or nullptr if constructed from adaptor. - const Geom2d_Curve* Geometry() const { return myCurve.get(); } - - //! Compute tangent at given parameter. - //! @param[in] theParam curve parameter - //! @param[in] theTol tolerance (unused for circle) - //! @return tangent result (always defined) - Geom2dProp::TangentResult Tangent(double theParam, double theTol) const - { - (void)theTol; - gp_Pnt2d aPnt; - gp_Vec2d aD1; - if (!myCurve.IsNull()) - { - myCurve->D1(theParam, aPnt, aD1); - } - else - { - myAdaptor->D1(theParam, aPnt, aD1); - } - return {gp_Dir2d(aD1), true}; - } - - //! Compute curvature at given parameter. - //! For a circle, curvature = 1/R (constant). - //! @param[in] theParam curve parameter (unused) - //! @param[in] theTol tolerance (unused) - //! @return curvature result (always defined, constant) - Geom2dProp::CurvatureResult Curvature(double theParam, double theTol) const - { - (void)theParam; - (void)theTol; - return {1.0 / myRadius, true, false}; - } - - //! Compute normal at given parameter. - //! @param[in] theParam curve parameter - //! @param[in] theTol tolerance (unused) - //! @return normal result (always defined) - Geom2dProp::NormalResult Normal(double theParam, double theTol) const - { - (void)theTol; - gp_Pnt2d aPnt; - gp_Vec2d aD1, aD2; - if (!myCurve.IsNull()) - { - myCurve->D2(theParam, aPnt, aD1, aD2); - } - else - { - myAdaptor->D2(theParam, aPnt, aD1, aD2); - } - // Normal = D2 * (D1.D1) - D1 * (D1.D2) - const gp_Vec2d aNorm = aD2 * aD1.Dot(aD1) - aD1 * aD1.Dot(aD2); - return {gp_Dir2d(aNorm), true}; - } - - //! Compute centre of curvature at given parameter. - //! For a circle, the centre of curvature is the geometric centre. - //! @param[in] theParam curve parameter (unused) - //! @param[in] theTol tolerance (unused) - //! @return centre result (always the circle centre) - Geom2dProp::CentreResult CentreOfCurvature(double theParam, double theTol) const - { - (void)theParam; - (void)theTol; - return {myCenter, true}; - } - - //! Find curvature extrema on the circle. - //! A circle has constant curvature, so no extrema. - //! @return empty analysis (always done) - Geom2dProp::CurveAnalysis FindCurvatureExtrema() const { return {{}, true}; } - - //! Find inflection points on the circle. - //! A circle has no inflection points. - //! @return empty analysis (always done) - Geom2dProp::CurveAnalysis FindInflections() const { return {{}, true}; } - -private: - const Geom2dAdaptor_Curve* myAdaptor = nullptr; //!< Non-owning adaptor pointer (adaptor path) - occ::handle myCurve; //!< Geometry handle (handle path) - double myRadius; //!< Cached circle radius - gp_Pnt2d myCenter; //!< Cached circle centre -}; - -#endif // _Geom2dProp_Circle_HeaderFile diff --git a/src/ModelingData/TKG2d/Geom2dProp/Geom2dProp_Curve.cxx b/src/ModelingData/TKG2d/Geom2dProp/Geom2dProp_Curve.cxx deleted file mode 100644 index 70bd662f65..0000000000 --- a/src/ModelingData/TKG2d/Geom2dProp/Geom2dProp_Curve.cxx +++ /dev/null @@ -1,551 +0,0 @@ -// 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 - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -//================================================================================================= - -Geom2dProp_Curve::Geom2dProp_Curve(const Adaptor2d_Curve2d& theCurve, - const Geom2dProp::CurveDerivOrder theOrder) - : myEvaluator(std::monostate{}), - myCurveType(GeomAbs_OtherCurve) -{ - initialization(theCurve, theOrder); -} - -//================================================================================================= - -Geom2dProp_Curve::Geom2dProp_Curve(const occ::handle& theCurve, - const Geom2dProp::CurveDerivOrder theOrder) - : myEvaluator(std::monostate{}), - myCurveType(GeomAbs_OtherCurve) -{ - initialization(theCurve, theOrder); -} - -//================================================================================================= - -void Geom2dProp_Curve::initialization(const Adaptor2d_Curve2d& theCurve, - const Geom2dProp::CurveDerivOrder theOrder) -{ - if (theCurve.IsKind(STANDARD_TYPE(Geom2dAdaptor_Curve))) - { - const Geom2dAdaptor_Curve& aGeomAdaptor = static_cast(theCurve); - if (!aGeomAdaptor.Curve().IsNull()) - { - // Dispatch specialized evaluators directly from the GeomAdaptor. - myOwnedAdaptor.Nullify(); - myCurveType = aGeomAdaptor.GetType(); - switch (myCurveType) - { - case GeomAbs_Line: - myEvaluator.emplace(&aGeomAdaptor, theOrder); - break; - case GeomAbs_Circle: - myEvaluator.emplace(&aGeomAdaptor, theOrder); - break; - case GeomAbs_Ellipse: - myEvaluator.emplace(&aGeomAdaptor, theOrder); - break; - case GeomAbs_Hyperbola: - myEvaluator.emplace(&aGeomAdaptor, theOrder); - break; - case GeomAbs_Parabola: - myEvaluator.emplace(&aGeomAdaptor, theOrder); - break; - case GeomAbs_BezierCurve: - myEvaluator.emplace(&aGeomAdaptor, theOrder); - break; - case GeomAbs_BSplineCurve: - myEvaluator.emplace(&aGeomAdaptor, theOrder); - break; - case GeomAbs_OffsetCurve: - myEvaluator.emplace(&aGeomAdaptor, theOrder); - break; - default: - myEvaluator.emplace(&theCurve, theOrder); - break; - } - return; - } - } - - // Non-Geom adaptor or empty curve handle: use OtherCurve with adaptor pointer. - myOwnedAdaptor.Nullify(); - myCurveType = theCurve.GetType(); - myEvaluator.emplace(&theCurve, theOrder); -} - -//================================================================================================= - -void Geom2dProp_Curve::initialization(const occ::handle& theCurve, - const Geom2dProp::CurveDerivOrder theOrder) -{ - if (theCurve.IsNull()) - { - myOwnedAdaptor.Nullify(); - myEvaluator.emplace(); - myCurveType = GeomAbs_OtherCurve; - return; - } - - // No adaptor creation for the handle path. - myOwnedAdaptor.Nullify(); - - // Unwrap TrimmedCurve to basis curve + optional CurveDomain. - occ::handle aBasis = theCurve; - std::optional aDomain; - if (aBasis->IsKind(STANDARD_TYPE(Geom2d_TrimmedCurve))) - { - aDomain = Geom2dProp::CurveDomain{theCurve->FirstParameter(), theCurve->LastParameter()}; - while (aBasis->IsKind(STANDARD_TYPE(Geom2d_TrimmedCurve))) - { - aBasis = occ::down_cast(aBasis)->BasisCurve(); - } - } - - // Type detection using DynamicType() - extracted once to avoid repeated virtual calls. - const occ::handle& aType = aBasis->DynamicType(); - if (aType == STANDARD_TYPE(Geom2d_Line)) - { - myCurveType = GeomAbs_Line; - myEvaluator.emplace(aBasis, aDomain, theOrder); - } - else if (aType == STANDARD_TYPE(Geom2d_Circle)) - { - myCurveType = GeomAbs_Circle; - myEvaluator.emplace(aBasis, aDomain, theOrder); - } - else if (aType == STANDARD_TYPE(Geom2d_Ellipse)) - { - myCurveType = GeomAbs_Ellipse; - myEvaluator.emplace(aBasis, aDomain, theOrder); - } - else if (aType == STANDARD_TYPE(Geom2d_Hyperbola)) - { - myCurveType = GeomAbs_Hyperbola; - myEvaluator.emplace(aBasis, aDomain, theOrder); - } - else if (aType == STANDARD_TYPE(Geom2d_Parabola)) - { - myCurveType = GeomAbs_Parabola; - myEvaluator.emplace(aBasis, aDomain, theOrder); - } - else if (aType == STANDARD_TYPE(Geom2d_BezierCurve)) - { - myCurveType = GeomAbs_BezierCurve; - myEvaluator.emplace(aBasis, aDomain, theOrder); - } - else if (aType == STANDARD_TYPE(Geom2d_BSplineCurve)) - { - myCurveType = GeomAbs_BSplineCurve; - myEvaluator.emplace(aBasis, aDomain, theOrder); - } - else if (aType == STANDARD_TYPE(Geom2d_OffsetCurve)) - { - myCurveType = GeomAbs_OffsetCurve; - myEvaluator.emplace(aBasis, aDomain, theOrder); - } - else - { - myCurveType = GeomAbs_OtherCurve; - myEvaluator.emplace(aBasis, aDomain, theOrder); - } -} - -//================================================================================================= - -void Geom2dProp_Curve::SetDerivOrder(const Geom2dProp::CurveDerivOrder theOrder) -{ - std::visit( - [theOrder](auto& theEval) { - using T = std::decay_t; - if constexpr (!std::is_same_v) - { - theEval.SetDerivOrder(theOrder); - } - }, - myEvaluator); -} - -//================================================================================================= - -Geom2dProp::CurveDerivOrder Geom2dProp_Curve::DerivOrder() const -{ - return std::visit( - [](const auto& theEval) -> Geom2dProp::CurveDerivOrder { - using T = std::decay_t; - if constexpr (std::is_same_v) - { - return Geom2dProp::CurveDerivOrder::Undefined; - } - else - { - return theEval.DerivOrder(); - } - }, - myEvaluator); -} - -//================================================================================================= - -const Adaptor2d_Curve2d* Geom2dProp_Curve::Adaptor() const -{ - if (!myOwnedAdaptor.IsNull()) - { - return myOwnedAdaptor.get(); - } - return nullptr; -} - -//================================================================================================= - -const Geom2d_Curve* Geom2dProp_Curve::Geometry() const -{ - return std::visit( - [](const auto& theEval) -> const Geom2d_Curve* { - using T = std::decay_t; - if constexpr (std::is_same_v) - { - return nullptr; - } - else - { - return theEval.Geometry(); - } - }, - myEvaluator); -} - -//================================================================================================= - -Geom2dProp::TangentResult Geom2dProp_Curve::Tangent(const double theParam, - const double theTol) const -{ - return std::visit( - [theParam, theTol](const auto& theEval) -> Geom2dProp::TangentResult { - using T = std::decay_t; - if constexpr (std::is_same_v) - { - return {{}, false}; - } - else - { - return theEval.Tangent(theParam, theTol); - } - }, - myEvaluator); -} - -//================================================================================================= - -Geom2dProp::CurvatureResult Geom2dProp_Curve::Curvature(const double theParam, - const double theTol) const -{ - return std::visit( - [theParam, theTol](const auto& theEval) -> Geom2dProp::CurvatureResult { - using T = std::decay_t; - if constexpr (std::is_same_v) - { - return {0.0, false, false}; - } - else - { - return theEval.Curvature(theParam, theTol); - } - }, - myEvaluator); -} - -//================================================================================================= - -Geom2dProp::NormalResult Geom2dProp_Curve::Normal(const double theParam, const double theTol) const -{ - return std::visit( - [theParam, theTol](const auto& theEval) -> Geom2dProp::NormalResult { - using T = std::decay_t; - if constexpr (std::is_same_v) - { - return {{}, false}; - } - else - { - return theEval.Normal(theParam, theTol); - } - }, - myEvaluator); -} - -//================================================================================================= - -Geom2dProp::CentreResult Geom2dProp_Curve::CentreOfCurvature(const double theParam, - const double theTol) const -{ - return std::visit( - [theParam, theTol](const auto& theEval) -> Geom2dProp::CentreResult { - using T = std::decay_t; - if constexpr (std::is_same_v) - { - return {{}, false}; - } - else - { - return theEval.CentreOfCurvature(theParam, theTol); - } - }, - myEvaluator); -} - -//================================================================================================= - -Geom2dProp::CurveAnalysis Geom2dProp_Curve::FindCurvatureExtrema() const -{ - return std::visit( - [](const auto& theEval) -> Geom2dProp::CurveAnalysis { - using T = std::decay_t; - if constexpr (std::is_same_v) - { - return {{}, false}; - } - else - { - return theEval.FindCurvatureExtrema(); - } - }, - myEvaluator); -} - -//================================================================================================= - -Geom2dProp::CurveAnalysis Geom2dProp_Curve::FindInflections() const -{ - return std::visit( - [](const auto& theEval) -> Geom2dProp::CurveAnalysis { - using T = std::decay_t; - if constexpr (std::is_same_v) - { - return {{}, false}; - } - else - { - return theEval.FindInflections(); - } - }, - myEvaluator); -} - -//================================================================================================= - -// Helper to convert GeomAbs_Shape to integer for comparison. -static int geomAbsToInteger(const GeomAbs_Shape theCont) -{ - switch (theCont) - { - case GeomAbs_C0: - return 0; - case GeomAbs_G1: - return 1; - case GeomAbs_C1: - return 2; - case GeomAbs_G2: - return 3; - case GeomAbs_C2: - return 4; - case GeomAbs_C3: - return 5; - case GeomAbs_CN: - return 6; - } - return 0; -} - -//================================================================================================= - -GeomAbs_Shape Geom2dProp_Curve::Continuity(const occ::handle& theC1, - const occ::handle& theC2, - const double theU1, - const double theU2, - const bool theR1, - const bool theR2, - const double theTolLinear, - const double theTolAngular) -{ - GeomAbs_Shape aCont = GeomAbs_C0; - bool isChecked = false; - - // Determine continuity order of each curve. - int aCont1 = geomAbsToInteger(theC1->Continuity()); - int aCont2 = geomAbsToInteger(theC2->Continuity()); - - // Unwrap TrimmedCurve to basis curve for BSpline knot analysis. - occ::handle aCurve1 = theC1; - occ::handle aCurve2 = theC2; - if (aCurve1->IsKind(STANDARD_TYPE(Geom2d_TrimmedCurve))) - { - aCurve1 = occ::down_cast(aCurve1)->BasisCurve(); - } - if (aCurve2->IsKind(STANDARD_TYPE(Geom2d_TrimmedCurve))) - { - aCurve2 = occ::down_cast(aCurve2)->BasisCurve(); - } - - // For BSpline curves, refine continuity from knot multiplicity. - if (aCurve1->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve))) - { - const occ::handle aBSpl = occ::down_cast(aCurve1); - double aTolerance = 0.0; - int anIdx1 = 0, anIdx2 = 0; - aBSpl->Resolution(theTolLinear, aTolerance); - aBSpl->LocateU(theU1, aTolerance, anIdx1, anIdx2); - if (anIdx1 > 1 && anIdx2 < aBSpl->NbKnots() && anIdx1 == anIdx2) - { - aCont1 = aBSpl->Degree() - aBSpl->Multiplicity(anIdx1); - } - else - { - aCont1 = 5; - } - } - if (aCurve2->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve))) - { - const occ::handle aBSpl = occ::down_cast(aCurve2); - double aTolerance = 0.0; - int anIdx1 = 0, anIdx2 = 0; - aBSpl->Resolution(theTolLinear, aTolerance); - aBSpl->LocateU(theU2, aTolerance, anIdx1, anIdx2); - if (anIdx1 > 1 && anIdx2 < aBSpl->NbKnots() && anIdx1 == anIdx2) - { - aCont2 = aBSpl->Degree() - aBSpl->Multiplicity(anIdx1); - } - else - { - aCont2 = 5; - } - } - - // Determine maximum derivative order to evaluate. - int aN1 = 0, aN2 = 0; - if (aCont1 >= 5) - aN1 = 3; - else if (aCont1 == 4) - aN1 = 2; - else if (aCont1 >= 2) - aN1 = 1; - if (aCont2 >= 5) - aN2 = 3; - else if (aCont2 == 4) - aN2 = 2; - else if (aCont2 >= 2) - aN2 = 1; - - // Evaluate derivatives at junction points. - Geom2dAdaptor_Curve anAdapt1(theC1); - Geom2dAdaptor_Curve anAdapt2(theC2); - - // Check point coincidence using D0 only. - gp_Pnt2d aPnt1 = anAdapt1.Value(theU1); - gp_Pnt2d aPnt2 = anAdapt2.Value(theU2); - if (!aPnt1.IsEqual(aPnt2, theTolLinear)) - { - throw Standard_Failure("Curves not connected"); - } - - const int aMinOrder = std::min(aN1, aN2); - if (aMinOrder >= 1) - { - gp_Pnt2d aDummyPnt; - gp_Vec2d aD1_1, aD1_2; - anAdapt1.D1(theU1, aDummyPnt, aD1_1); - anAdapt2.D1(theU2, aDummyPnt, aD1_2); - gp_Vec2d aVec1 = aD1_1; - gp_Vec2d aVec2 = aD1_2; - if (theR1) - aVec1.Reverse(); - if (theR2) - aVec2.Reverse(); - - if (aVec1.IsEqual(aVec2, theTolLinear, theTolAngular)) - { - aCont = GeomAbs_C1; - } - else - { - // Check G1 continuity via tangent directions. - Geom2dProp_Curve aProp1(theC1); - Geom2dProp_Curve aProp2(theC2); - const Geom2dProp::TangentResult aTan1 = aProp1.Tangent(theU1, theTolLinear); - const Geom2dProp::TangentResult aTan2 = aProp2.Tangent(theU2, theTolLinear); - if (aTan1.IsDefined && aTan2.IsDefined) - { - gp_Dir2d aDir1 = aTan1.Direction; - gp_Dir2d aDir2 = aTan2.Direction; - if (theR1) - aDir1.Reverse(); - if (theR2) - aDir2.Reverse(); - if (aDir1.IsEqual(aDir2, theTolAngular)) - { - aCont = GeomAbs_G1; - } - } - isChecked = true; - } - } - - if (aMinOrder >= 2 && !isChecked) - { - // Compare second derivatives. - gp_Pnt2d aDummy; - gp_Vec2d aDummy1, aDummy2; - gp_Vec2d aD2_1, aD2_2; - anAdapt1.D2(theU1, aDummy, aDummy1, aD2_1); - anAdapt2.D2(theU2, aDummy, aDummy2, aD2_2); - if (aD2_1.IsEqual(aD2_2, theTolLinear, theTolAngular)) - { - aCont = GeomAbs_C2; - } - } - - return aCont; -} - -//================================================================================================= - -GeomAbs_Shape Geom2dProp_Curve::Continuity(const occ::handle& theC1, - const occ::handle& theC2, - const double theU1, - const double theU2, - const bool theR1, - const bool theR2) -{ - return Continuity(theC1, - theC2, - theU1, - theU2, - theR1, - theR2, - Precision::Confusion(), - Precision::Angular()); -} diff --git a/src/ModelingData/TKG2d/Geom2dProp/Geom2dProp_Curve.hxx b/src/ModelingData/TKG2d/Geom2dProp/Geom2dProp_Curve.hxx deleted file mode 100644 index 0138632dff..0000000000 --- a/src/ModelingData/TKG2d/Geom2dProp/Geom2dProp_Curve.hxx +++ /dev/null @@ -1,199 +0,0 @@ -// 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. - -#ifndef _Geom2dProp_Curve_HeaderFile -#define _Geom2dProp_Curve_HeaderFile - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -//! @brief Unified local differential property evaluator for any 2D curve. -//! -//! Uses std::variant for compile-time type safety and zero heap allocation -//! for the evaluator itself. Automatically detects curve type from -//! Adaptor2d_Curve2d or Geom2d_Curve and dispatches to the appropriate -//! specialized evaluator. -//! -//! Supported curve types with optimized evaluation: -//! - Line: Trivial (zero curvature, constant tangent) -//! - Circle: Constant curvature 1/R -//! - Ellipse: Analytical curvature extrema at vertices -//! - Hyperbola: Analytical curvature extremum at vertex -//! - Parabola: Analytical curvature extremum at vertex -//! - BezierCurve: Numeric curvature extrema/inflection finding -//! - BSplineCurve: Numeric with C3 interval subdivision -//! - OffsetCurve: Numeric approach -//! - Other: Fallback using Geom2d_Curve virtual D1/D2/D3 -//! -//! Usage: -//! @code -//! Geom2dProp_Curve aProp(myGeom2dCurve); -//! Geom2dProp::CurvatureResult aCurv = aProp.Curvature(0.5, Precision::Confusion()); -//! if (aCurv.IsDefined) -//! { -//! double aValue = aCurv.Value; -//! } -//! @endcode -class Geom2dProp_Curve -{ -public: - DEFINE_STANDARD_ALLOC - - //! Variant type holding all possible 2D curve property evaluators. - using EvaluatorVariant = std::variant; - - //! Construct from 2D adaptor reference (auto-detects curve type). - //! For Geom2dAdaptor_Curve, extracts underlying Geom2d_Curve for optimized evaluation. - //! @param[in] theCurve 2D curve adaptor reference - //! @param[in] theOrder derivative caching order - Standard_EXPORT Geom2dProp_Curve( - const Adaptor2d_Curve2d& theCurve, - Geom2dProp::CurveDerivOrder theOrder = Geom2dProp::CurveDerivOrder::Curvature); - - //! Construct from geometry handle (auto-detects curve type). - //! @param[in] theCurve 2D geometry to evaluate - //! @param[in] theOrder derivative caching order - Standard_EXPORT Geom2dProp_Curve( - const occ::handle& theCurve, - Geom2dProp::CurveDerivOrder theOrder = Geom2dProp::CurveDerivOrder::Curvature); - - //! Non-copyable and non-movable. - Geom2dProp_Curve(const Geom2dProp_Curve&) = delete; - Geom2dProp_Curve& operator=(const Geom2dProp_Curve&) = delete; - Geom2dProp_Curve(Geom2dProp_Curve&&) = delete; - Geom2dProp_Curve& operator=(Geom2dProp_Curve&&) = delete; - - //! Returns the detected curve type. - GeomAbs_CurveType GetType() const { return myCurveType; } - - //! Sets the derivative caching order for the active evaluator. - //! Only effective for non-analytical curve types (BSpline, Bezier, Offset, Other). - Standard_EXPORT void SetDerivOrder(Geom2dProp::CurveDerivOrder theOrder); - - //! Returns the derivative caching order of the active evaluator. - Standard_EXPORT Geom2dProp::CurveDerivOrder DerivOrder() const; - - //! Returns the stored adaptor pointer, or null if not initialized. - Standard_EXPORT const Adaptor2d_Curve2d* Adaptor() const; - - //! Returns pointer to underlying geometry, or nullptr if not available. - //! When constructed from a handle, trimmed curves are unwrapped to their basis curve. - Standard_EXPORT const Geom2d_Curve* Geometry() const; - - //! Compute tangent at given parameter. - //! @param[in] theParam curve parameter - //! @param[in] theTol linear tolerance - //! @return tangent result with validity flag - Standard_EXPORT Geom2dProp::TangentResult Tangent(double theParam, double theTol) const; - - //! Compute curvature at given parameter. - //! @param[in] theParam curve parameter - //! @param[in] theTol linear tolerance - //! @return curvature result with validity and infinity flags - Standard_EXPORT Geom2dProp::CurvatureResult Curvature(double theParam, double theTol) const; - - //! Compute normal at given parameter. - //! @param[in] theParam curve parameter - //! @param[in] theTol linear tolerance - //! @return normal result with validity flag - Standard_EXPORT Geom2dProp::NormalResult Normal(double theParam, double theTol) const; - - //! Compute centre of curvature at given parameter. - //! @param[in] theParam curve parameter - //! @param[in] theTol linear tolerance - //! @return centre result with validity flag - Standard_EXPORT Geom2dProp::CentreResult CentreOfCurvature(double theParam, double theTol) const; - - //! Find curvature extrema on the curve. - //! @return analysis result with special points sorted by parameter - Standard_EXPORT Geom2dProp::CurveAnalysis FindCurvatureExtrema() const; - - //! Find inflection points on the curve. - //! @return analysis result with inflection points sorted by parameter - Standard_EXPORT Geom2dProp::CurveAnalysis FindInflections() const; - - //! Compute the degree of continuity at the junction between two curves. - //! The point theU1 on theC1 and the point theU2 on theC2 must be coincident. - //! For BSpline curves, knot multiplicity is used to determine available derivatives. - //! @param[in] theC1 first curve - //! @param[in] theC2 second curve - //! @param[in] theU1 parameter on first curve at junction - //! @param[in] theU2 parameter on second curve at junction - //! @param[in] theR1 true if first curve should be taken reversed - //! @param[in] theR2 true if second curve should be taken reversed - //! @param[in] theTolLinear linear tolerance for derivative comparison - //! @param[in] theTolAngular angular tolerance for direction comparison - //! @return degree of continuity at junction (C0, G1, C1, C2) - Standard_EXPORT static GeomAbs_Shape Continuity(const occ::handle& theC1, - const occ::handle& theC2, - double theU1, - double theU2, - bool theR1, - bool theR2, - double theTolLinear, - double theTolAngular); - - //! Same as above but using the standard tolerances from package Precision. - Standard_EXPORT static GeomAbs_Shape Continuity(const occ::handle& theC1, - const occ::handle& theC2, - double theU1, - double theU2, - bool theR1, - bool theR2); - -protected: - //! Initialize from 2D adaptor reference (auto-detects curve type). - //! @param[in] theCurve 2D curve adaptor reference - //! @param[in] theOrder derivative caching order - Standard_EXPORT void initialization(const Adaptor2d_Curve2d& theCurve, - Geom2dProp::CurveDerivOrder theOrder); - - //! Initialize from geometry handle (auto-detects curve type). - //! @param[in] theCurve 2D geometry to evaluate - //! @param[in] theOrder derivative caching order - Standard_EXPORT void initialization(const occ::handle& theCurve, - Geom2dProp::CurveDerivOrder theOrder); - -private: - occ::handle myOwnedAdaptor; //!< Owned adaptor when lifetime must be managed. - EvaluatorVariant myEvaluator; - GeomAbs_CurveType myCurveType; -}; - -#endif // _Geom2dProp_Curve_HeaderFile diff --git a/src/ModelingData/TKG2d/Geom2dProp/Geom2dProp_CurveAnalysisTools.pxx b/src/ModelingData/TKG2d/Geom2dProp/Geom2dProp_CurveAnalysisTools.pxx deleted file mode 100644 index 85938ad51a..0000000000 --- a/src/ModelingData/TKG2d/Geom2dProp/Geom2dProp_CurveAnalysisTools.pxx +++ /dev/null @@ -1,785 +0,0 @@ -// 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. - -#ifndef Geom2dProp_CurveAnalysisTools_PHeaderFile -#define Geom2dProp_CurveAnalysisTools_PHeaderFile - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -//! Internal helper utilities for numeric curve analysis shared across all -//! Geom2dProp curve evaluators (Bezier, BSpline, Offset, Other). -//! This header is not part of the public API. -namespace Geom2dProp_CurveAnalysisTools -{ - -constexpr double THE_CURVATURE_DERIV_COEFF = 3.0; //!< Coefficient in d(KC)/dU formula -constexpr double THE_DIFF_STEP_DIVISOR = 100.0; //!< Divisor for numerical differentiation step -constexpr double THE_D2_MAGNITUDE_THRESHOLD = 1.0e-4; //!< Threshold for second derivative magnitude -constexpr double THE_EPSILON_SCALE = 1.0e-4; //!< Scale factor for epsilon relative to domain -constexpr int THE_EXTREMA_NB_SAMPLES = 100; //!< Number of samples for curvature extrema search -constexpr int THE_INFLECTION_NB_SAMPLES = 30; //!< Number of samples for inflection search -constexpr double THE_INFLECTION_TOLERANCE = 1.0e-6; //!< Tolerance for inflection point finding - -//! Function for finding curvature extrema: F = d(curvature)/dU = 0 -//! In 2D: KC = (V1 ^ V2) / ||V1||^3 (scalar cross product) -//! F = d KC / dU -template -class FuncCurExt : public math_FunctionWithDerivative -{ -public: - FuncCurExt(const CurveAdaptor* theCurve, const double theTol) - : myCurve(theCurve), - myEpsX(theTol) - { - } - - bool Value(const double X, double& F) override - { - gp_Pnt2d aP; - gp_Vec2d aV1, aV2, aV3; - myCurve->D3(X, aP, aV1, aV2, aV3); - - const double aCPV1V2 = aV1.Crossed(aV2); - const double aCPV1V3 = aV1.Crossed(aV3); - const double aV1V2 = aV1.Dot(aV2); - const double aV1V1 = aV1.SquareMagnitude(); - const double aNV1 = std::sqrt(aV1V1); - const double aV13 = aV1V1 * aNV1; - const double aV15 = aV13 * aV1V1; - - if (aV15 < gp::Resolution()) - { - return false; - } - - F = aCPV1V3 / aV13 - THE_CURVATURE_DERIV_COEFF * aCPV1V2 * aV1V2 / aV15; - return true; - } - - bool Derivative(const double X, double& D) override - { - double aF; - return Values(X, aF, D); - } - - bool Values(const double X, double& F, double& D) override - { - double aDx = myEpsX / THE_DIFF_STEP_DIVISOR; - if (X + aDx > myCurve->LastParameter()) - { - aDx = -aDx; - } - - Value(X, F); - double aF2; - Value(X + aDx, aF2); - D = (aF2 - F) / aDx; - return true; - } - - //! Test if parameter corresponds to a minimum of the radius of curvature - //! (maximum of |curvature|) by comparison with a neighboring point. - bool IsMinKC(const double X) const - { - gp_Pnt2d aP; - gp_Vec2d aV1, aV2, aV3; - - myCurve->D3(X, aP, aV1, aV2, aV3); - const double aV1V1 = aV1.SquareMagnitude(); - const double aNV1 = std::sqrt(aV1V1); - const double aV13 = aV1V1 * aNV1; - - if (aV13 < gp::Resolution()) - { - return false; - } - const double aKC = aV1.Crossed(aV2) / aV13; - - double aDx = myEpsX; - if (X + aDx > myCurve->LastParameter()) - { - aDx = -aDx; - } - - myCurve->D3(X + aDx, aP, aV1, aV2, aV3); - const double aV1V1n = aV1.SquareMagnitude(); - const double aNV1n = std::sqrt(aV1V1n); - const double aV13n = aV1V1n * aNV1n; - - if (aV13n < gp::Resolution()) - { - return false; - } - const double aKP = aV1.Crossed(aV2) / aV13n; - - return std::abs(aKC) > std::abs(aKP); - } - -private: - const CurveAdaptor* myCurve; - double myEpsX; -}; - -//! Function for finding inflection points: F = (V1 ^ V2) / (||V1|| * ||V2||) = 0 -template -class FuncCurNul : public math_FunctionWithDerivative -{ -public: - FuncCurNul(const CurveAdaptor* theCurve) - : myCurve(theCurve) - { - } - - bool Value(const double X, double& F) override - { - double aD; - return Values(X, F, aD); - } - - bool Derivative(const double X, double& D) override - { - double aF; - return Values(X, aF, D); - } - - bool Values(const double X, double& F, double& D) override - { - gp_Pnt2d aP; - gp_Vec2d aV1, aV2, aV3; - myCurve->D3(X, aP, aV1, aV2, aV3); - - const double aCP1 = aV1.Crossed(aV2); - const double aCP2 = aV1.Crossed(aV3); - const double aV1V2 = aV1.Dot(aV2); - const double aV2V3 = aV2.Dot(aV3); - const double aNV1 = aV1.Magnitude(); - const double aNV2 = aV2.Magnitude(); - - F = 0.0; - D = 0.0; - - if (aNV2 < THE_D2_MAGNITUDE_THRESHOLD) - { - return true; - } - if (aNV1 * aNV2 < gp::Resolution()) - { - return false; - } - - F = aCP1 / (aNV1 * aNV2); - D = (aCP2 - aCP1 * aV1V2 / (aNV1 * aNV1) - aCP1 * aV2V3 / (aNV2 * aNV2)) / (aNV1 * aNV2); - return true; - } - -private: - const CurveAdaptor* myCurve; -}; - -//! Perform numeric curvature extrema finding on a curve interval. -template -inline void NumericCurvatureExtrema(const CurveAdaptor* theCurve, - const double theUMin, - const double theUMax, - Geom2dProp::CurveAnalysis& theResult) -{ - const double aEpsH = THE_EPSILON_SCALE * (theUMax - theUMin); - - FuncCurExt aFunc(theCurve, aEpsH); - - MathRoot::MultipleConfig aConfig; - aConfig.NbSamples = THE_EXTREMA_NB_SAMPLES; - aConfig.XTolerance = aEpsH; - aConfig.FTolerance = aEpsH; - - MathRoot::MultipleResult aRoots = - MathRoot::FindAllRootsWithDerivative(aFunc, theUMin, theUMax, aConfig); - - if (aRoots.IsDone()) - { - for (int j = 0; j < aRoots.NbRoots(); ++j) - { - double aParam = aRoots[j]; - - MathUtils::Config aBrentCfg; - aBrentCfg.XTolerance = Precision::PConfusion(); - aBrentCfg.FTolerance = Precision::PConfusion(); - MathUtils::ScalarResult aBrent = - MathRoot::Brent(aFunc, aParam - aEpsH, aParam + aEpsH, aBrentCfg); - if (aBrent.IsDone() && aBrent.Root.has_value()) - { - aParam = *aBrent.Root; - } - - const bool aIsMin = aFunc.IsMinKC(aParam); - const Geom2dProp::CIType aType = - aIsMin ? Geom2dProp::CIType::MinCurvature : Geom2dProp::CIType::MaxCurvature; - theResult.Points.Append({aParam, aType}); - } - } - else - { - theResult.IsDone = false; - } -} - -//! Perform numeric inflection finding on a curve interval. -template -inline void NumericInflections(const CurveAdaptor* theCurve, - const double theUMin, - const double theUMax, - Geom2dProp::CurveAnalysis& theResult) -{ - FuncCurNul aFunc(theCurve); - - MathRoot::MultipleConfig aConfig; - aConfig.NbSamples = THE_INFLECTION_NB_SAMPLES; - aConfig.XTolerance = THE_INFLECTION_TOLERANCE; - aConfig.FTolerance = THE_INFLECTION_TOLERANCE; - - MathRoot::MultipleResult aRoots = MathRoot::FindAllRoots(aFunc, theUMin, theUMax, aConfig); - - if (aRoots.IsDone()) - { - for (int j = 0; j < aRoots.NbRoots(); ++j) - { - theResult.Points.Append({aRoots[j], Geom2dProp::CIType::Inflection}); - } - } - else - { - theResult.IsDone = false; - } -} - -//! Remove duplicate points that may appear at shared interval boundaries. -inline void RemoveDuplicatePoints(Geom2dProp::CurveAnalysis& theResult, const double theTol) -{ - const int aNbPts = theResult.Points.Size(); - if (aNbPts <= 1) - { - return; - } - - bool aHasDuplicates = false; - for (int i = 1; i < aNbPts && !aHasDuplicates; ++i) - { - for (int j = 0; j < i; ++j) - { - if (std::abs(theResult.Points[i].Parameter - theResult.Points[j].Parameter) < theTol) - { - aHasDuplicates = true; - break; - } - } - } - if (!aHasDuplicates) - { - return; - } - - NCollection_DynamicArray aFiltered; - aFiltered.Append(theResult.Points[0]); - for (int i = 1; i < aNbPts; ++i) - { - bool aIsDuplicate = false; - for (int j = static_cast(aFiltered.Size()) - 1; j >= 0; --j) - { - if (std::abs(theResult.Points[i].Parameter - aFiltered[j].Parameter) < theTol) - { - aIsDuplicate = true; - break; - } - } - if (!aIsDuplicate) - { - aFiltered.Append(theResult.Points[i]); - } - } - - theResult.Points = std::move(aFiltered); -} - -template -inline Geom2dProp::CurveAnalysis FindWholeRange( - const CurveType* theCurve, - void (*theFunc)(const CurveType*, double, double, Geom2dProp::CurveAnalysis&)) -{ - Geom2dProp::CurveAnalysis aResult; - aResult.IsDone = true; - - if (theCurve == nullptr) - { - aResult.IsDone = false; - return aResult; - } - - theFunc(theCurve, theCurve->FirstParameter(), theCurve->LastParameter(), aResult); - return aResult; -} - -//! Evaluate tangent at a point on a 2D curve with sign correction for null D1. -//! Works with both Adaptor2d_Curve2d and Geom2d_Curve. -template -inline Geom2dProp::TangentResult EvaluateTangent(const CurveType* theCurve, - const double theParam, - const double theTol) -{ - if (theCurve == nullptr) - { - return {{}, false}; - } - - gp_Pnt2d aP; - gp_Vec2d aD1, aD2, aD3; - theCurve->D3(theParam, aP, aD1, aD2, aD3); - - if (aD1.SquareMagnitude() > theTol * theTol) - { - return {gp_Dir2d(aD1), true}; - } - - constexpr double THE_DIV_FACTOR = 1.e-3; - constexpr double THE_MIN_STEP = 1.e-7; - const double anUFirst = theCurve->FirstParameter(); - const double anULast = theCurve->LastParameter(); - double aDu = 0.0; - if (anULast < RealLast() && anUFirst > RealFirst()) - aDu = anULast - anUFirst; - const double aDelta = std::max(aDu * THE_DIV_FACTOR, THE_MIN_STEP); - const double aU = (theParam - anUFirst < aDelta) ? theParam + aDelta : theParam - aDelta; - - gp_Pnt2d aP1, aP2; - theCurve->D0(std::min(theParam, aU), aP1); - theCurve->D0(std::max(theParam, aU), aP2); - return Geom2dProp::ComputeTangent(aD1, aD2, aD3, theTol, aP1, aP2); -} - -//! Evaluate curvature at a point on a 2D curve. -//! Works with both Adaptor2d_Curve2d and Geom2d_Curve. -template -inline Geom2dProp::CurvatureResult EvaluateCurvature(const CurveType* theCurve, - const double theParam, - const double theTol) -{ - if (theCurve == nullptr) - { - return {0.0, false, false}; - } - - gp_Pnt2d aP; - gp_Vec2d aD1, aD2; - theCurve->D2(theParam, aP, aD1, aD2); - return Geom2dProp::ComputeCurvature(aD1, aD2, theTol); -} - -//! Evaluate normal at a point on a 2D curve. -//! Works with both Adaptor2d_Curve2d and Geom2d_Curve. -template -inline Geom2dProp::NormalResult EvaluateNormal(const CurveType* theCurve, - const double theParam, - const double theTol) -{ - if (theCurve == nullptr) - { - return {{}, false}; - } - - gp_Pnt2d aP; - gp_Vec2d aD1, aD2; - theCurve->D2(theParam, aP, aD1, aD2); - return Geom2dProp::ComputeNormal(aD1, aD2, theTol); -} - -//! Evaluate centre of curvature at a point on a 2D curve. -//! Works with both Adaptor2d_Curve2d and Geom2d_Curve. -template -inline Geom2dProp::CentreResult EvaluateCentreOfCurvature(const CurveType* theCurve, - const double theParam, - const double theTol) -{ - if (theCurve == nullptr) - { - return {{}, false}; - } - - gp_Pnt2d aP; - gp_Vec2d aD1, aD2; - theCurve->D2(theParam, aP, aD1, aD2); - return Geom2dProp::ComputeCentreOfCurvature(aP, aD1, aD2, theTol); -} - -//! Find curvature extrema on the full curve domain. -inline Geom2dProp::CurveAnalysis FindCurvatureExtrema(const Adaptor2d_Curve2d* theCurve) -{ - return FindWholeRange(theCurve, NumericCurvatureExtrema); -} - -//! Find inflections on the full curve domain. -inline Geom2dProp::CurveAnalysis FindInflections(const Adaptor2d_Curve2d* theCurve) -{ - return FindWholeRange(theCurve, NumericInflections); -} - -//! Find curvature extrema on a Geom2d_Curve over a given domain. -inline Geom2dProp::CurveAnalysis FindCurvatureExtrema( - const Geom2d_Curve* theCurve, - const std::optional& theDomain) -{ - Geom2dProp::CurveAnalysis aResult; - aResult.IsDone = true; - if (theCurve == nullptr) - { - aResult.IsDone = false; - return aResult; - } - const double aFirst = theDomain.has_value() ? theDomain->First : theCurve->FirstParameter(); - const double aLast = theDomain.has_value() ? theDomain->Last : theCurve->LastParameter(); - NumericCurvatureExtrema(theCurve, aFirst, aLast, aResult); - return aResult; -} - -//! Find inflections on a Geom2d_Curve over a given domain. -inline Geom2dProp::CurveAnalysis FindInflections( - const Geom2d_Curve* theCurve, - const std::optional& theDomain) -{ - Geom2dProp::CurveAnalysis aResult; - aResult.IsDone = true; - if (theCurve == nullptr) - { - aResult.IsDone = false; - return aResult; - } - const double aFirst = theDomain.has_value() ? theDomain->First : theCurve->FirstParameter(); - const double aLast = theDomain.has_value() ? theDomain->Last : theCurve->LastParameter(); - NumericInflections(theCurve, aFirst, aLast, aResult); - return aResult; -} - -//! Find curvature extrema with span-by-span subdivision for low-continuity curves. -inline Geom2dProp::CurveAnalysis FindCurvatureExtremaBySpans(const Geom2dAdaptor_Curve* theCurve, - const GeomAbs_Shape theContinuity) -{ - Geom2dProp::CurveAnalysis aResult; - aResult.IsDone = true; - - if (theCurve == nullptr) - { - aResult.IsDone = false; - return aResult; - } - - if (theCurve->Continuity() >= theContinuity) - { - NumericCurvatureExtrema(theCurve, - theCurve->FirstParameter(), - theCurve->LastParameter(), - aResult); - } - else - { - const int aNbInt = theCurve->NbIntervals(theContinuity); - NCollection_Array1 aParams(1, aNbInt + 1); - theCurve->Intervals(aParams, theContinuity); - for (int i = 1; i <= aNbInt; ++i) - { - NumericCurvatureExtrema(theCurve, aParams(i), aParams(i + 1), aResult); - } - const double aEpsH = - THE_EPSILON_SCALE * (theCurve->LastParameter() - theCurve->FirstParameter()); - RemoveDuplicatePoints(aResult, aEpsH); - } - - return aResult; -} - -//! Find inflections with span-by-span subdivision for low-continuity curves. -inline Geom2dProp::CurveAnalysis FindInflectionsBySpans(const Geom2dAdaptor_Curve* theCurve, - const GeomAbs_Shape theContinuity) -{ - Geom2dProp::CurveAnalysis aResult; - aResult.IsDone = true; - - if (theCurve == nullptr) - { - aResult.IsDone = false; - return aResult; - } - - if (theCurve->Continuity() >= theContinuity) - { - NumericInflections(theCurve, theCurve->FirstParameter(), theCurve->LastParameter(), aResult); - } - else - { - const int aNbInt = theCurve->NbIntervals(theContinuity); - NCollection_Array1 aParams(1, aNbInt + 1); - theCurve->Intervals(aParams, theContinuity); - for (int i = 1; i <= aNbInt; ++i) - { - NumericInflections(theCurve, aParams(i), aParams(i + 1), aResult); - } - RemoveDuplicatePoints(aResult, THE_INFLECTION_TOLERANCE); - } - - return aResult; -} - -//! Populate 2D curve derivative cache at the requested order. -//! Works with both Adaptor2d_Curve2d and Geom2d_Curve (they share the same D0/D1/D2/D3 interface). -template -inline void EnsureCurveDerivatives(const CurveType* theCurve, - double theParam, - Geom2dProp::CurveDerivOrder theNeeded, - Geom2dProp::CurveDerivOrder theRequested, - Geom2dProp::CurveCache& theCache) -{ - if (theCache.IsValid(theParam) && theCache.HasOrder(theNeeded)) - { - return; - } - const int aTarget = std::max(static_cast(theRequested), static_cast(theNeeded)); - theCache.Param = theParam; - switch (static_cast(aTarget)) - { - case Geom2dProp::CurveDerivOrder::Value: { - gp_Pnt2d aP; - theCurve->D0(theParam, aP); - theCache.Data.emplace(aP); - break; - } - case Geom2dProp::CurveDerivOrder::Tangent: { - gp_Pnt2d aP; - gp_Vec2d aD1; - theCurve->D1(theParam, aP, aD1); - theCache.Data.emplace(Geom2d_Curve::ResD1{aP, aD1}); - break; - } - case Geom2dProp::CurveDerivOrder::Curvature: { - gp_Pnt2d aP; - gp_Vec2d aD1, aD2; - theCurve->D2(theParam, aP, aD1, aD2); - theCache.Data.emplace(Geom2d_Curve::ResD2{aP, aD1, aD2}); - break; - } - case Geom2dProp::CurveDerivOrder::CurvatureDeriv: - default: { - gp_Pnt2d aP; - gp_Vec2d aD1, aD2, aD3; - theCurve->D3(theParam, aP, aD1, aD2, aD3); - theCache.Data.emplace(Geom2d_Curve::ResD3{aP, aD1, aD2, aD3}); - break; - } - } -} - -//! Evaluate tangent at a point on a 2D curve using cached derivatives. -//! Works with both Adaptor2d_Curve2d and Geom2d_Curve. -template -inline Geom2dProp::TangentResult EvaluateTangentCached(const CurveType* theCurve, - double theParam, - double theTol, - Geom2dProp::CurveDerivOrder theOrder, - Geom2dProp::CurveCache& theCache) -{ - if (theCurve == nullptr) - { - return {{}, false}; - } - - EnsureCurveDerivatives(theCurve, - theParam, - Geom2dProp::CurveDerivOrder::Tangent, - theOrder, - theCache); - - gp_Vec2d aD1; - std::visit( - [&](const auto& theVal) { - using T = std::decay_t; - if constexpr (std::is_same_v || std::is_same_v - || std::is_same_v) - { - aD1 = theVal.D1; - } - }, - theCache.Data); - - if (aD1.SquareMagnitude() > theTol * theTol) - { - return {gp_Dir2d(aD1), true}; - } - - // Degenerate point - upgrade cache to D3 for sign correction. - // No need to invalidate: EnsureCurveDerivatives re-evaluates when IsValid && !HasOrder. - EnsureCurveDerivatives(theCurve, - theParam, - Geom2dProp::CurveDerivOrder::CurvatureDeriv, - Geom2dProp::CurveDerivOrder::CurvatureDeriv, - theCache); - - const auto& aD3Data = std::get(theCache.Data); - - constexpr double THE_DIV_FACTOR = 1.e-3; - constexpr double THE_MIN_STEP = 1.e-7; - const double anUFirst = theCurve->FirstParameter(); - const double anULast = theCurve->LastParameter(); - double aDu = 0.0; - if (anULast < RealLast() && anUFirst > RealFirst()) - aDu = anULast - anUFirst; - const double aDelta = std::max(aDu * THE_DIV_FACTOR, THE_MIN_STEP); - const double aU = (theParam - anUFirst < aDelta) ? theParam + aDelta : theParam - aDelta; - - // Reuse cached point for the endpoint that matches theParam. - gp_Pnt2d aP1, aP2; - if (theParam <= aU) - { - aP1 = aD3Data.Point; - theCurve->D0(aU, aP2); - } - else - { - theCurve->D0(aU, aP1); - aP2 = aD3Data.Point; - } - return Geom2dProp::ComputeTangent(aD3Data.D1, aD3Data.D2, aD3Data.D3, theTol, aP1, aP2); -} - -//! Evaluate curvature at a point on a 2D curve using cached derivatives. -//! Works with both Adaptor2d_Curve2d and Geom2d_Curve. -template -inline Geom2dProp::CurvatureResult EvaluateCurvatureCached(const CurveType* theCurve, - double theParam, - double theTol, - Geom2dProp::CurveDerivOrder theOrder, - Geom2dProp::CurveCache& theCache) -{ - if (theCurve == nullptr) - { - return {0.0, false, false}; - } - - EnsureCurveDerivatives(theCurve, - theParam, - Geom2dProp::CurveDerivOrder::Curvature, - theOrder, - theCache); - - return std::visit( - [theTol](const auto& theVal) -> Geom2dProp::CurvatureResult { - using T = std::decay_t; - if constexpr (std::is_same_v - || std::is_same_v) - { - return Geom2dProp::ComputeCurvature(theVal.D1, theVal.D2, theTol); - } - else - { - return {0.0, false, false}; - } - }, - theCache.Data); -} - -//! Evaluate normal at a point on a 2D curve using cached derivatives. -//! Works with both Adaptor2d_Curve2d and Geom2d_Curve. -template -inline Geom2dProp::NormalResult EvaluateNormalCached(const CurveType* theCurve, - double theParam, - double theTol, - Geom2dProp::CurveDerivOrder theOrder, - Geom2dProp::CurveCache& theCache) -{ - if (theCurve == nullptr) - { - return {{}, false}; - } - - EnsureCurveDerivatives(theCurve, - theParam, - Geom2dProp::CurveDerivOrder::Curvature, - theOrder, - theCache); - - return std::visit( - [theTol](const auto& theVal) -> Geom2dProp::NormalResult { - using T = std::decay_t; - if constexpr (std::is_same_v - || std::is_same_v) - { - return Geom2dProp::ComputeNormal(theVal.D1, theVal.D2, theTol); - } - else - { - return {{}, false}; - } - }, - theCache.Data); -} - -//! Evaluate centre of curvature at a point on a 2D curve using cached derivatives. -//! Works with both Adaptor2d_Curve2d and Geom2d_Curve. -template -inline Geom2dProp::CentreResult EvaluateCentreOfCurvatureCached( - const CurveType* theCurve, - double theParam, - double theTol, - Geom2dProp::CurveDerivOrder theOrder, - Geom2dProp::CurveCache& theCache) -{ - if (theCurve == nullptr) - { - return {{}, false}; - } - - EnsureCurveDerivatives(theCurve, - theParam, - Geom2dProp::CurveDerivOrder::Curvature, - theOrder, - theCache); - - return std::visit( - [theTol](const auto& theVal) -> Geom2dProp::CentreResult { - using T = std::decay_t; - if constexpr (std::is_same_v - || std::is_same_v) - { - return Geom2dProp::ComputeCentreOfCurvature(theVal.Point, theVal.D1, theVal.D2, theTol); - } - else - { - return {{}, false}; - } - }, - theCache.Data); -} - -} // namespace Geom2dProp_CurveAnalysisTools - -#endif // Geom2dProp_CurveAnalysisTools_PHeaderFile diff --git a/src/ModelingData/TKG2d/Geom2dProp/Geom2dProp_Ellipse.cxx b/src/ModelingData/TKG2d/Geom2dProp/Geom2dProp_Ellipse.cxx deleted file mode 100644 index bc38686f43..0000000000 --- a/src/ModelingData/TKG2d/Geom2dProp/Geom2dProp_Ellipse.cxx +++ /dev/null @@ -1,165 +0,0 @@ -// 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 - -#include - -#include - -namespace -{ -constexpr int THE_ELLIPSE_NB_EXTREMA = 4; //!< Number of curvature extrema on full ellipse -constexpr double THE_ELLIPSE_PERIOD = 2.0 * M_PI; //!< One full period of ellipse parameter -} // namespace - -//================================================================================================= - -Geom2dProp::TangentResult Geom2dProp_Ellipse::Tangent(const double theParam, - const double theTol) const -{ - if (myCurve.IsNull() && myAdaptor == nullptr) - { - return {{}, false}; - } - gp_Pnt2d aPnt; - gp_Vec2d aD1, aD2, aD3; - if (!myCurve.IsNull()) - { - myCurve->D3(theParam, aPnt, aD1, aD2, aD3); - } - else - { - myAdaptor->D3(theParam, aPnt, aD1, aD2, aD3); - } - return Geom2dProp::ComputeTangent(aD1, aD2, aD3, theTol); -} - -//================================================================================================= - -Geom2dProp::CurvatureResult Geom2dProp_Ellipse::Curvature(const double theParam, - const double theTol) const -{ - if (myCurve.IsNull() && myAdaptor == nullptr) - { - return {0.0, false, false}; - } - gp_Pnt2d aPnt; - gp_Vec2d aD1, aD2; - if (!myCurve.IsNull()) - { - myCurve->D2(theParam, aPnt, aD1, aD2); - } - else - { - myAdaptor->D2(theParam, aPnt, aD1, aD2); - } - return Geom2dProp::ComputeCurvature(aD1, aD2, theTol); -} - -//================================================================================================= - -Geom2dProp::NormalResult Geom2dProp_Ellipse::Normal(const double theParam, - const double theTol) const -{ - if (myCurve.IsNull() && myAdaptor == nullptr) - { - return {{}, false}; - } - gp_Pnt2d aPnt; - gp_Vec2d aD1, aD2; - if (!myCurve.IsNull()) - { - myCurve->D2(theParam, aPnt, aD1, aD2); - } - else - { - myAdaptor->D2(theParam, aPnt, aD1, aD2); - } - return Geom2dProp::ComputeNormal(aD1, aD2, theTol); -} - -//================================================================================================= - -Geom2dProp::CentreResult Geom2dProp_Ellipse::CentreOfCurvature(const double theParam, - const double theTol) const -{ - if (myCurve.IsNull() && myAdaptor == nullptr) - { - return {{}, false}; - } - gp_Pnt2d aPnt; - gp_Vec2d aD1, aD2; - if (!myCurve.IsNull()) - { - myCurve->D2(theParam, aPnt, aD1, aD2); - } - else - { - myAdaptor->D2(theParam, aPnt, aD1, aD2); - } - return Geom2dProp::ComputeCentreOfCurvature(aPnt, aD1, aD2, theTol); -} - -//================================================================================================= - -Geom2dProp::CurveAnalysis Geom2dProp_Ellipse::FindCurvatureExtrema() const -{ - Geom2dProp::CurveAnalysis aResult; - aResult.IsDone = true; - - if (myCurve.IsNull() && myAdaptor == nullptr) - { - aResult.IsDone = false; - return aResult; - } - - double aUFirst, aULast; - if (myDomain.has_value()) - { - aUFirst = myDomain->First; - aULast = myDomain->Last; - } - else if (myAdaptor != nullptr) - { - aUFirst = myAdaptor->FirstParameter(); - aULast = myAdaptor->LastParameter(); - } - else - { - aUFirst = myCurve->FirstParameter(); - aULast = myCurve->LastParameter(); - } - - const double aUFPlus2PI = aUFirst + THE_ELLIPSE_PERIOD; - - // Ellipse curvature extrema at 0, PI/2, PI, 3*PI/2 - // At 0 and PI (major axis endpoints): min radius of curvature -> max |curvature| -> MinCurvature - // At PI/2 and 3*PI/2 (minor axis endpoints): max radius of curvature -> min |curvature| -> - // MaxCurvature - const double aCandidates[] = {0.0, M_PI / 2.0, M_PI, 3.0 * M_PI / 2.0}; - const bool aIsMin[] = {true, false, true, false}; - - for (int i = 0; i < THE_ELLIPSE_NB_EXTREMA; ++i) - { - const double aU = ElCLib::InPeriod(aCandidates[i], aUFirst, aUFPlus2PI); - if (aU >= aUFirst && aU <= aULast) - { - const Geom2dProp::CIType aType = - aIsMin[i] ? Geom2dProp::CIType::MinCurvature : Geom2dProp::CIType::MaxCurvature; - aResult.Points.Append({aU, aType}); - } - } - - return aResult; -} diff --git a/src/ModelingData/TKG2d/Geom2dProp/Geom2dProp_Ellipse.hxx b/src/ModelingData/TKG2d/Geom2dProp/Geom2dProp_Ellipse.hxx deleted file mode 100644 index ee12b188e3..0000000000 --- a/src/ModelingData/TKG2d/Geom2dProp/Geom2dProp_Ellipse.hxx +++ /dev/null @@ -1,104 +0,0 @@ -// 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. - -#ifndef _Geom2dProp_Ellipse_HeaderFile -#define _Geom2dProp_Ellipse_HeaderFile - -#include -#include -#include -#include -#include - -#include - -//! @brief Local differential properties for a 2D ellipse. -//! -//! An ellipse has analytically known curvature extrema at the four vertices: -//! - Parameter 0 and PI: endpoints of major axis (min radius of curvature) -//! - Parameter PI/2 and 3*PI/2: endpoints of minor axis (max radius of curvature) -//! -//! Can be constructed from either a Geom2dAdaptor_Curve pointer or a occ::handle. -//! When constructed from a handle, no adaptor is created. -class Geom2dProp_Ellipse -{ -public: - DEFINE_STANDARD_ALLOC - - //! Constructor with adaptor pointer (non-owning). - //! @param theAdaptor the 2D curve adaptor (must wrap an ellipse, must not be null) - Geom2dProp_Ellipse(const Geom2dAdaptor_Curve* theAdaptor, - Geom2dProp::CurveDerivOrder theOrder = Geom2dProp::CurveDerivOrder::Undefined) - : myAdaptor(theAdaptor) - { - (void)theOrder; - } - - //! Constructor from geometry handle. - //! @param theCurve the 2D ellipse geometry - //! @param theDomain optional parameter domain (for trimmed curves) - Geom2dProp_Ellipse(const occ::handle& theCurve, - const std::optional& theDomain = std::nullopt, - Geom2dProp::CurveDerivOrder theOrder = Geom2dProp::CurveDerivOrder::Undefined) - : myAdaptor(nullptr), - myCurve(theCurve), - myDomain(theDomain) - { - (void)theOrder; - } - - //! Non-copyable and non-movable. - Geom2dProp_Ellipse(const Geom2dProp_Ellipse&) = delete; - Geom2dProp_Ellipse& operator=(const Geom2dProp_Ellipse&) = delete; - Geom2dProp_Ellipse(Geom2dProp_Ellipse&&) = delete; - Geom2dProp_Ellipse& operator=(Geom2dProp_Ellipse&&) = delete; - - //! Sets the derivative caching order (no-op for analytical curves). - void SetDerivOrder(Geom2dProp::CurveDerivOrder) {} - - //! Returns the derivative caching order (always Undefined for analytical curves). - Geom2dProp::CurveDerivOrder DerivOrder() const { return Geom2dProp::CurveDerivOrder::Undefined; } - - //! Returns the adaptor pointer (nullptr when constructed from handle). - const Geom2dAdaptor_Curve* Adaptor() const { return myAdaptor; } - - //! Returns pointer to underlying geometry, or nullptr if constructed from adaptor. - const Geom2d_Curve* Geometry() const { return myCurve.get(); } - - //! Compute tangent at given parameter. - Standard_EXPORT Geom2dProp::TangentResult Tangent(double theParam, double theTol) const; - - //! Compute curvature at given parameter. - Standard_EXPORT Geom2dProp::CurvatureResult Curvature(double theParam, double theTol) const; - - //! Compute normal at given parameter. - Standard_EXPORT Geom2dProp::NormalResult Normal(double theParam, double theTol) const; - - //! Compute centre of curvature at given parameter. - Standard_EXPORT Geom2dProp::CentreResult CentreOfCurvature(double theParam, double theTol) const; - - //! Find curvature extrema on the ellipse. - //! Extrema occur analytically at 0, PI/2, PI, and 3*PI/2, filtered to [FirstParam, LastParam]. - Standard_EXPORT Geom2dProp::CurveAnalysis FindCurvatureExtrema() const; - - //! Find inflection points on the ellipse. - //! An ellipse has no inflection points. - Geom2dProp::CurveAnalysis FindInflections() const { return {{}, true}; } - -private: - const Geom2dAdaptor_Curve* myAdaptor; //!< Non-owning adaptor pointer (adaptor path) - occ::handle myCurve; //!< Geometry handle (handle path) - std::optional myDomain; //!< Optional parameter domain -}; - -#endif // _Geom2dProp_Ellipse_HeaderFile diff --git a/src/ModelingData/TKG2d/Geom2dProp/Geom2dProp_Hyperbola.cxx b/src/ModelingData/TKG2d/Geom2dProp/Geom2dProp_Hyperbola.cxx deleted file mode 100644 index 9a97bee289..0000000000 --- a/src/ModelingData/TKG2d/Geom2dProp/Geom2dProp_Hyperbola.cxx +++ /dev/null @@ -1,141 +0,0 @@ -// 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 - -//================================================================================================= - -Geom2dProp::TangentResult Geom2dProp_Hyperbola::Tangent(const double theParam, - const double theTol) const -{ - if (myCurve.IsNull() && myAdaptor == nullptr) - { - return {{}, false}; - } - gp_Pnt2d aPnt; - gp_Vec2d aD1, aD2, aD3; - if (!myCurve.IsNull()) - { - myCurve->D3(theParam, aPnt, aD1, aD2, aD3); - } - else - { - myAdaptor->D3(theParam, aPnt, aD1, aD2, aD3); - } - return Geom2dProp::ComputeTangent(aD1, aD2, aD3, theTol); -} - -//================================================================================================= - -Geom2dProp::CurvatureResult Geom2dProp_Hyperbola::Curvature(const double theParam, - const double theTol) const -{ - if (myCurve.IsNull() && myAdaptor == nullptr) - { - return {0.0, false, false}; - } - gp_Pnt2d aPnt; - gp_Vec2d aD1, aD2; - if (!myCurve.IsNull()) - { - myCurve->D2(theParam, aPnt, aD1, aD2); - } - else - { - myAdaptor->D2(theParam, aPnt, aD1, aD2); - } - return Geom2dProp::ComputeCurvature(aD1, aD2, theTol); -} - -//================================================================================================= - -Geom2dProp::NormalResult Geom2dProp_Hyperbola::Normal(const double theParam, - const double theTol) const -{ - if (myCurve.IsNull() && myAdaptor == nullptr) - { - return {{}, false}; - } - gp_Pnt2d aPnt; - gp_Vec2d aD1, aD2; - if (!myCurve.IsNull()) - { - myCurve->D2(theParam, aPnt, aD1, aD2); - } - else - { - myAdaptor->D2(theParam, aPnt, aD1, aD2); - } - return Geom2dProp::ComputeNormal(aD1, aD2, theTol); -} - -//================================================================================================= - -Geom2dProp::CentreResult Geom2dProp_Hyperbola::CentreOfCurvature(const double theParam, - const double theTol) const -{ - if (myCurve.IsNull() && myAdaptor == nullptr) - { - return {{}, false}; - } - gp_Pnt2d aPnt; - gp_Vec2d aD1, aD2; - if (!myCurve.IsNull()) - { - myCurve->D2(theParam, aPnt, aD1, aD2); - } - else - { - myAdaptor->D2(theParam, aPnt, aD1, aD2); - } - return Geom2dProp::ComputeCentreOfCurvature(aPnt, aD1, aD2, theTol); -} - -//================================================================================================= - -Geom2dProp::CurveAnalysis Geom2dProp_Hyperbola::FindCurvatureExtrema() const -{ - Geom2dProp::CurveAnalysis aResult; - aResult.IsDone = true; - - if (myCurve.IsNull() && myAdaptor == nullptr) - { - aResult.IsDone = false; - return aResult; - } - - double aUFirst, aULast; - if (myDomain.has_value()) - { - aUFirst = myDomain->First; - aULast = myDomain->Last; - } - else if (myAdaptor != nullptr) - { - aUFirst = myAdaptor->FirstParameter(); - aULast = myAdaptor->LastParameter(); - } - else - { - aUFirst = myCurve->FirstParameter(); - aULast = myCurve->LastParameter(); - } - - // Hyperbola has maximum |curvature| at parameter 0 (vertex). - if (aUFirst <= 0.0 && aULast >= 0.0) - { - aResult.Points.Append({0.0, Geom2dProp::CIType::MinCurvature}); - } - - return aResult; -} diff --git a/src/ModelingData/TKG2d/Geom2dProp/Geom2dProp_Hyperbola.hxx b/src/ModelingData/TKG2d/Geom2dProp/Geom2dProp_Hyperbola.hxx deleted file mode 100644 index 762914afd7..0000000000 --- a/src/ModelingData/TKG2d/Geom2dProp/Geom2dProp_Hyperbola.hxx +++ /dev/null @@ -1,105 +0,0 @@ -// 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. - -#ifndef _Geom2dProp_Hyperbola_HeaderFile -#define _Geom2dProp_Hyperbola_HeaderFile - -#include -#include -#include -#include -#include - -#include - -//! @brief Local differential properties for a 2D hyperbola. -//! -//! A hyperbola has a single curvature extremum (maximum |curvature|) at parameter 0 -//! (the vertex). No inflection points exist. -//! -//! Can be constructed from either a Geom2dAdaptor_Curve pointer or a occ::handle. -//! When constructed from a handle, no adaptor is created. -class Geom2dProp_Hyperbola -{ -public: - DEFINE_STANDARD_ALLOC - - //! Constructor with adaptor pointer (non-owning). - //! @param theAdaptor the 2D curve adaptor (must wrap a hyperbola, must not be null) - Geom2dProp_Hyperbola( - const Geom2dAdaptor_Curve* theAdaptor, - Geom2dProp::CurveDerivOrder theOrder = Geom2dProp::CurveDerivOrder::Undefined) - : myAdaptor(theAdaptor) - { - (void)theOrder; - } - - //! Constructor from geometry handle. - //! @param theCurve the 2D hyperbola geometry - //! @param theDomain optional parameter domain (for trimmed curves) - Geom2dProp_Hyperbola( - const occ::handle& theCurve, - const std::optional& theDomain = std::nullopt, - Geom2dProp::CurveDerivOrder theOrder = Geom2dProp::CurveDerivOrder::Undefined) - : myAdaptor(nullptr), - myCurve(theCurve), - myDomain(theDomain) - { - (void)theOrder; - } - - //! Non-copyable and non-movable. - Geom2dProp_Hyperbola(const Geom2dProp_Hyperbola&) = delete; - Geom2dProp_Hyperbola& operator=(const Geom2dProp_Hyperbola&) = delete; - Geom2dProp_Hyperbola(Geom2dProp_Hyperbola&&) = delete; - Geom2dProp_Hyperbola& operator=(Geom2dProp_Hyperbola&&) = delete; - - //! Sets the derivative caching order (no-op for analytical curves). - void SetDerivOrder(Geom2dProp::CurveDerivOrder) {} - - //! Returns the derivative caching order (always Undefined for analytical curves). - Geom2dProp::CurveDerivOrder DerivOrder() const { return Geom2dProp::CurveDerivOrder::Undefined; } - - //! Returns the adaptor pointer (nullptr when constructed from handle). - const Geom2dAdaptor_Curve* Adaptor() const { return myAdaptor; } - - //! Returns pointer to underlying geometry, or nullptr if constructed from adaptor. - const Geom2d_Curve* Geometry() const { return myCurve.get(); } - - //! Compute tangent at given parameter. - Standard_EXPORT Geom2dProp::TangentResult Tangent(double theParam, double theTol) const; - - //! Compute curvature at given parameter. - Standard_EXPORT Geom2dProp::CurvatureResult Curvature(double theParam, double theTol) const; - - //! Compute normal at given parameter. - Standard_EXPORT Geom2dProp::NormalResult Normal(double theParam, double theTol) const; - - //! Compute centre of curvature at given parameter. - Standard_EXPORT Geom2dProp::CentreResult CentreOfCurvature(double theParam, double theTol) const; - - //! Find curvature extrema on the hyperbola. - //! Single extremum at parameter 0 (the vertex), if within parameter range. - Standard_EXPORT Geom2dProp::CurveAnalysis FindCurvatureExtrema() const; - - //! Find inflection points on the hyperbola. - //! A hyperbola has no inflection points. - Geom2dProp::CurveAnalysis FindInflections() const { return {{}, true}; } - -private: - const Geom2dAdaptor_Curve* myAdaptor; //!< Non-owning adaptor pointer (adaptor path) - occ::handle myCurve; //!< Geometry handle (handle path) - std::optional myDomain; //!< Optional parameter domain -}; - -#endif // _Geom2dProp_Hyperbola_HeaderFile diff --git a/src/ModelingData/TKG2d/Geom2dProp/Geom2dProp_Line.hxx b/src/ModelingData/TKG2d/Geom2dProp/Geom2dProp_Line.hxx deleted file mode 100644 index 35f4629de2..0000000000 --- a/src/ModelingData/TKG2d/Geom2dProp/Geom2dProp_Line.hxx +++ /dev/null @@ -1,140 +0,0 @@ -// 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. - -#ifndef _Geom2dProp_Line_HeaderFile -#define _Geom2dProp_Line_HeaderFile - -#include -#include -#include -#include - -#include - -//! @brief Local differential properties for a 2D line. -//! -//! A line has constant tangent, zero curvature, undefined normal and centre. -//! No curvature extrema or inflection points exist. -//! -//! Can be constructed from either a Geom2dAdaptor_Curve pointer or a occ::handle. -//! When constructed from a handle, no adaptor is created. -class Geom2dProp_Line -{ -public: - DEFINE_STANDARD_ALLOC - - //! Constructor with adaptor pointer (non-owning). - //! @param theAdaptor the 2D curve adaptor (must wrap a line, must not be null) - Geom2dProp_Line(const Geom2dAdaptor_Curve* theAdaptor, - Geom2dProp::CurveDerivOrder theOrder = Geom2dProp::CurveDerivOrder::Undefined) - : myAdaptor(theAdaptor), - myCurve(theAdaptor->Curve()) - { - (void)theOrder; - } - - //! Constructor from geometry handle. - //! @param theCurve the 2D line geometry (must be a Geom2d_Line or downcastable to it) - //! @param theDomain optional parameter domain (unused for line) - Geom2dProp_Line(const occ::handle& theCurve, - const std::optional& theDomain = std::nullopt, - Geom2dProp::CurveDerivOrder theOrder = Geom2dProp::CurveDerivOrder::Undefined) - : myAdaptor(nullptr), - myCurve(theCurve) - { - (void)theDomain; - (void)theOrder; - } - - //! Non-copyable and non-movable. - Geom2dProp_Line(const Geom2dProp_Line&) = delete; - Geom2dProp_Line& operator=(const Geom2dProp_Line&) = delete; - Geom2dProp_Line(Geom2dProp_Line&&) = delete; - Geom2dProp_Line& operator=(Geom2dProp_Line&&) = delete; - - //! Sets the derivative caching order (no-op for analytical curves). - void SetDerivOrder(Geom2dProp::CurveDerivOrder) {} - - //! Returns the derivative caching order (always Undefined for analytical curves). - Geom2dProp::CurveDerivOrder DerivOrder() const { return Geom2dProp::CurveDerivOrder::Undefined; } - - //! Returns the adaptor pointer (nullptr when constructed from handle). - const Geom2dAdaptor_Curve* Adaptor() const { return myAdaptor; } - - //! Returns pointer to underlying geometry, or nullptr if constructed from adaptor. - const Geom2d_Curve* Geometry() const { return myCurve.get(); } - - //! Compute tangent at given parameter. - //! For a line, the tangent is always the line direction. - //! @param[in] theParam curve parameter (unused) - //! @param[in] theTol tolerance (unused) - //! @return tangent result (always defined) - Geom2dProp::TangentResult Tangent(double theParam, double theTol) const - { - (void)theParam; - (void)theTol; - return {occ::down_cast(myCurve)->Direction(), true}; - } - - //! Compute curvature at given parameter. - //! For a line, curvature is always zero. - //! @param[in] theParam curve parameter (unused) - //! @param[in] theTol tolerance (unused) - //! @return curvature result (always zero) - Geom2dProp::CurvatureResult Curvature(double theParam, double theTol) const - { - (void)theParam; - (void)theTol; - return {0.0, true, false}; - } - - //! Compute normal at given parameter. - //! For a line, the normal is undefined (zero curvature). - //! @param[in] theParam curve parameter (unused) - //! @param[in] theTol tolerance (unused) - //! @return normal result (always undefined) - Geom2dProp::NormalResult Normal(double theParam, double theTol) const - { - (void)theParam; - (void)theTol; - return {{}, false}; - } - - //! Compute centre of curvature at given parameter. - //! For a line, the centre is undefined (zero curvature). - //! @param[in] theParam curve parameter (unused) - //! @param[in] theTol tolerance (unused) - //! @return centre result (always undefined) - Geom2dProp::CentreResult CentreOfCurvature(double theParam, double theTol) const - { - (void)theParam; - (void)theTol; - return {{}, false}; - } - - //! Find curvature extrema on the line. - //! A line has no curvature extrema. - //! @return empty analysis (always done) - Geom2dProp::CurveAnalysis FindCurvatureExtrema() const { return {{}, true}; } - - //! Find inflection points on the line. - //! A line has no inflection points. - //! @return empty analysis (always done) - Geom2dProp::CurveAnalysis FindInflections() const { return {{}, true}; } - -private: - const Geom2dAdaptor_Curve* myAdaptor = nullptr; //!< Non-owning adaptor pointer (adaptor path) - occ::handle myCurve; //!< Geometry handle (handle path) -}; - -#endif // _Geom2dProp_Line_HeaderFile diff --git a/src/ModelingData/TKG2d/Geom2dProp/Geom2dProp_OffsetCurve.cxx b/src/ModelingData/TKG2d/Geom2dProp/Geom2dProp_OffsetCurve.cxx deleted file mode 100644 index 29e6ed598f..0000000000 --- a/src/ModelingData/TKG2d/Geom2dProp/Geom2dProp_OffsetCurve.cxx +++ /dev/null @@ -1,123 +0,0 @@ -// 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 -#include - -//================================================================================================= - -Geom2dProp::TangentResult Geom2dProp_OffsetCurve::Tangent(const double theParam, - const double theTol) const -{ - if (!myCurve.IsNull()) - { - return Geom2dProp_CurveAnalysisTools::EvaluateTangentCached(myCurve.get(), - theParam, - theTol, - myRequestedOrder, - myCache); - } - return Geom2dProp_CurveAnalysisTools::EvaluateTangentCached(myAdaptor, - theParam, - theTol, - myRequestedOrder, - myCache); -} - -//================================================================================================= - -Geom2dProp::CurvatureResult Geom2dProp_OffsetCurve::Curvature(const double theParam, - const double theTol) const -{ - if (!myCurve.IsNull()) - { - return Geom2dProp_CurveAnalysisTools::EvaluateCurvatureCached(myCurve.get(), - theParam, - theTol, - myRequestedOrder, - myCache); - } - return Geom2dProp_CurveAnalysisTools::EvaluateCurvatureCached(myAdaptor, - theParam, - theTol, - myRequestedOrder, - myCache); -} - -//================================================================================================= - -Geom2dProp::NormalResult Geom2dProp_OffsetCurve::Normal(const double theParam, - const double theTol) const -{ - if (!myCurve.IsNull()) - { - return Geom2dProp_CurveAnalysisTools::EvaluateNormalCached(myCurve.get(), - theParam, - theTol, - myRequestedOrder, - myCache); - } - return Geom2dProp_CurveAnalysisTools::EvaluateNormalCached(myAdaptor, - theParam, - theTol, - myRequestedOrder, - myCache); -} - -//================================================================================================= - -Geom2dProp::CentreResult Geom2dProp_OffsetCurve::CentreOfCurvature(const double theParam, - const double theTol) const -{ - if (!myCurve.IsNull()) - { - return Geom2dProp_CurveAnalysisTools::EvaluateCentreOfCurvatureCached(myCurve.get(), - theParam, - theTol, - myRequestedOrder, - myCache); - } - return Geom2dProp_CurveAnalysisTools::EvaluateCentreOfCurvatureCached(myAdaptor, - theParam, - theTol, - myRequestedOrder, - myCache); -} - -//================================================================================================= - -Geom2dProp::CurveAnalysis Geom2dProp_OffsetCurve::FindCurvatureExtrema() const -{ - if (!myCurve.IsNull()) - { - const double aFirst = myDomain.has_value() ? myDomain->First : myCurve->FirstParameter(); - const double aLast = myDomain.has_value() ? myDomain->Last : myCurve->LastParameter(); - Geom2dAdaptor_Curve anAdaptor(myCurve, aFirst, aLast); - return Geom2dProp_CurveAnalysisTools::FindCurvatureExtrema(&anAdaptor); - } - return Geom2dProp_CurveAnalysisTools::FindCurvatureExtrema(myAdaptor); -} - -//================================================================================================= - -Geom2dProp::CurveAnalysis Geom2dProp_OffsetCurve::FindInflections() const -{ - if (!myCurve.IsNull()) - { - const double aFirst = myDomain.has_value() ? myDomain->First : myCurve->FirstParameter(); - const double aLast = myDomain.has_value() ? myDomain->Last : myCurve->LastParameter(); - Geom2dAdaptor_Curve anAdaptor(myCurve, aFirst, aLast); - return Geom2dProp_CurveAnalysisTools::FindInflections(&anAdaptor); - } - return Geom2dProp_CurveAnalysisTools::FindInflections(myAdaptor); -} diff --git a/src/ModelingData/TKG2d/Geom2dProp/Geom2dProp_OffsetCurve.hxx b/src/ModelingData/TKG2d/Geom2dProp/Geom2dProp_OffsetCurve.hxx deleted file mode 100644 index bc9e11202d..0000000000 --- a/src/ModelingData/TKG2d/Geom2dProp/Geom2dProp_OffsetCurve.hxx +++ /dev/null @@ -1,106 +0,0 @@ -// 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. - -#ifndef _Geom2dProp_OffsetCurve_HeaderFile -#define _Geom2dProp_OffsetCurve_HeaderFile - -#include -#include -#include -#include -#include - -#include - -//! @brief Local differential properties for a 2D offset curve. -//! -//! Uses numeric root-finding for curvature extrema and inflection points. -//! Local properties are computed from the offset curve's own D1/D2/D3. -//! -//! Can be constructed from either a Geom2dAdaptor_Curve pointer or a occ::handle. -//! When constructed from a handle, no adaptor is created; for complex methods -//! (FindCurvatureExtrema, FindInflections) a stack-local adaptor is created on demand. -class Geom2dProp_OffsetCurve -{ -public: - DEFINE_STANDARD_ALLOC - - //! Constructor with adaptor pointer (non-owning). - //! @param theAdaptor the 2D curve adaptor (must wrap an offset curve, must not be null) - Geom2dProp_OffsetCurve( - const Geom2dAdaptor_Curve* theAdaptor, - Geom2dProp::CurveDerivOrder theOrder = Geom2dProp::CurveDerivOrder::Curvature) - : myAdaptor(theAdaptor), - myRequestedOrder(theOrder) - { - } - - //! Constructor from geometry handle. - //! @param theCurve the 2D offset curve geometry - //! @param theDomain optional parameter domain (for trimmed curves) - Geom2dProp_OffsetCurve( - const occ::handle& theCurve, - const std::optional& theDomain = std::nullopt, - Geom2dProp::CurveDerivOrder theOrder = Geom2dProp::CurveDerivOrder::Curvature) - : myAdaptor(nullptr), - myRequestedOrder(theOrder), - myCurve(theCurve), - myDomain(theDomain) - { - } - - //! Non-copyable and non-movable. - Geom2dProp_OffsetCurve(const Geom2dProp_OffsetCurve&) = delete; - Geom2dProp_OffsetCurve& operator=(const Geom2dProp_OffsetCurve&) = delete; - Geom2dProp_OffsetCurve(Geom2dProp_OffsetCurve&&) = delete; - Geom2dProp_OffsetCurve& operator=(Geom2dProp_OffsetCurve&&) = delete; - - //! Sets the derivative caching order. - void SetDerivOrder(Geom2dProp::CurveDerivOrder theOrder) { myRequestedOrder = theOrder; } - - //! Returns the derivative caching order. - Geom2dProp::CurveDerivOrder DerivOrder() const { return myRequestedOrder; } - - //! Returns the adaptor pointer (nullptr when constructed from handle). - const Geom2dAdaptor_Curve* Adaptor() const { return myAdaptor; } - - //! Returns pointer to underlying geometry, or nullptr if constructed from adaptor. - const Geom2d_Curve* Geometry() const { return myCurve.get(); } - - //! Compute tangent at given parameter. - Standard_EXPORT Geom2dProp::TangentResult Tangent(double theParam, double theTol) const; - - //! Compute curvature at given parameter. - Standard_EXPORT Geom2dProp::CurvatureResult Curvature(double theParam, double theTol) const; - - //! Compute normal at given parameter. - Standard_EXPORT Geom2dProp::NormalResult Normal(double theParam, double theTol) const; - - //! Compute centre of curvature at given parameter. - Standard_EXPORT Geom2dProp::CentreResult CentreOfCurvature(double theParam, double theTol) const; - - //! Find curvature extrema using numeric root-finding. - Standard_EXPORT Geom2dProp::CurveAnalysis FindCurvatureExtrema() const; - - //! Find inflection points using numeric root-finding. - Standard_EXPORT Geom2dProp::CurveAnalysis FindInflections() const; - -private: - const Geom2dAdaptor_Curve* myAdaptor; - Geom2dProp::CurveDerivOrder myRequestedOrder; - mutable Geom2dProp::CurveCache myCache; - occ::handle myCurve; //!< Geometry handle (handle path) - std::optional myDomain; //!< Optional parameter domain -}; - -#endif // _Geom2dProp_OffsetCurve_HeaderFile diff --git a/src/ModelingData/TKG2d/Geom2dProp/Geom2dProp_OtherCurve.cxx b/src/ModelingData/TKG2d/Geom2dProp/Geom2dProp_OtherCurve.cxx deleted file mode 100644 index 630edcc3c3..0000000000 --- a/src/ModelingData/TKG2d/Geom2dProp/Geom2dProp_OtherCurve.cxx +++ /dev/null @@ -1,123 +0,0 @@ -// 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 -#include - -//================================================================================================= - -Geom2dProp::TangentResult Geom2dProp_OtherCurve::Tangent(const double theParam, - const double theTol) const -{ - if (!myCurve.IsNull()) - { - return Geom2dProp_CurveAnalysisTools::EvaluateTangentCached(myCurve.get(), - theParam, - theTol, - myRequestedOrder, - myCache); - } - return Geom2dProp_CurveAnalysisTools::EvaluateTangentCached(myAdaptor, - theParam, - theTol, - myRequestedOrder, - myCache); -} - -//================================================================================================= - -Geom2dProp::CurvatureResult Geom2dProp_OtherCurve::Curvature(const double theParam, - const double theTol) const -{ - if (!myCurve.IsNull()) - { - return Geom2dProp_CurveAnalysisTools::EvaluateCurvatureCached(myCurve.get(), - theParam, - theTol, - myRequestedOrder, - myCache); - } - return Geom2dProp_CurveAnalysisTools::EvaluateCurvatureCached(myAdaptor, - theParam, - theTol, - myRequestedOrder, - myCache); -} - -//================================================================================================= - -Geom2dProp::NormalResult Geom2dProp_OtherCurve::Normal(const double theParam, - const double theTol) const -{ - if (!myCurve.IsNull()) - { - return Geom2dProp_CurveAnalysisTools::EvaluateNormalCached(myCurve.get(), - theParam, - theTol, - myRequestedOrder, - myCache); - } - return Geom2dProp_CurveAnalysisTools::EvaluateNormalCached(myAdaptor, - theParam, - theTol, - myRequestedOrder, - myCache); -} - -//================================================================================================= - -Geom2dProp::CentreResult Geom2dProp_OtherCurve::CentreOfCurvature(const double theParam, - const double theTol) const -{ - if (!myCurve.IsNull()) - { - return Geom2dProp_CurveAnalysisTools::EvaluateCentreOfCurvatureCached(myCurve.get(), - theParam, - theTol, - myRequestedOrder, - myCache); - } - return Geom2dProp_CurveAnalysisTools::EvaluateCentreOfCurvatureCached(myAdaptor, - theParam, - theTol, - myRequestedOrder, - myCache); -} - -//================================================================================================= - -Geom2dProp::CurveAnalysis Geom2dProp_OtherCurve::FindCurvatureExtrema() const -{ - if (!myCurve.IsNull()) - { - const double aFirst = myDomain.has_value() ? myDomain->First : myCurve->FirstParameter(); - const double aLast = myDomain.has_value() ? myDomain->Last : myCurve->LastParameter(); - Geom2dAdaptor_Curve anAdaptor(myCurve, aFirst, aLast); - return Geom2dProp_CurveAnalysisTools::FindCurvatureExtrema(&anAdaptor); - } - return Geom2dProp_CurveAnalysisTools::FindCurvatureExtrema(myAdaptor); -} - -//================================================================================================= - -Geom2dProp::CurveAnalysis Geom2dProp_OtherCurve::FindInflections() const -{ - if (!myCurve.IsNull()) - { - const double aFirst = myDomain.has_value() ? myDomain->First : myCurve->FirstParameter(); - const double aLast = myDomain.has_value() ? myDomain->Last : myCurve->LastParameter(); - Geom2dAdaptor_Curve anAdaptor(myCurve, aFirst, aLast); - return Geom2dProp_CurveAnalysisTools::FindInflections(&anAdaptor); - } - return Geom2dProp_CurveAnalysisTools::FindInflections(myAdaptor); -} diff --git a/src/ModelingData/TKG2d/Geom2dProp/Geom2dProp_OtherCurve.hxx b/src/ModelingData/TKG2d/Geom2dProp/Geom2dProp_OtherCurve.hxx deleted file mode 100644 index a468d31a8b..0000000000 --- a/src/ModelingData/TKG2d/Geom2dProp/Geom2dProp_OtherCurve.hxx +++ /dev/null @@ -1,106 +0,0 @@ -// 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. - -#ifndef _Geom2dProp_OtherCurve_HeaderFile -#define _Geom2dProp_OtherCurve_HeaderFile - -#include -#include -#include -#include -#include - -#include - -//! @brief Fallback local differential properties for any 2D curve type. -//! -//! Uses adaptor D1/D2/D3 methods for property computation -//! and numeric root-finding for curvature extrema and inflection points. -//! -//! Can be constructed from an Adaptor2d_Curve2d pointer or a occ::handle. -//! When constructed from a handle, no adaptor is created; -//! for complex methods a stack-local adaptor is created on demand. -class Geom2dProp_OtherCurve -{ -public: - DEFINE_STANDARD_ALLOC - - //! Constructor with adaptor pointer (non-owning). - //! @param theAdaptor the 2D curve adaptor (must not be null) - Geom2dProp_OtherCurve( - const Adaptor2d_Curve2d* theAdaptor, - Geom2dProp::CurveDerivOrder theOrder = Geom2dProp::CurveDerivOrder::Curvature) - : myAdaptor(theAdaptor), - myRequestedOrder(theOrder) - { - } - - //! Constructor from geometry handle. - //! @param theCurve the 2D curve geometry - //! @param theDomain optional parameter domain (for trimmed curves) - Geom2dProp_OtherCurve( - const occ::handle& theCurve, - const std::optional& theDomain = std::nullopt, - Geom2dProp::CurveDerivOrder theOrder = Geom2dProp::CurveDerivOrder::Curvature) - : myAdaptor(nullptr), - myRequestedOrder(theOrder), - myCurve(theCurve), - myDomain(theDomain) - { - } - - //! Non-copyable and non-movable. - Geom2dProp_OtherCurve(const Geom2dProp_OtherCurve&) = delete; - Geom2dProp_OtherCurve& operator=(const Geom2dProp_OtherCurve&) = delete; - Geom2dProp_OtherCurve(Geom2dProp_OtherCurve&&) = delete; - Geom2dProp_OtherCurve& operator=(Geom2dProp_OtherCurve&&) = delete; - - //! Sets the derivative caching order. - void SetDerivOrder(Geom2dProp::CurveDerivOrder theOrder) { myRequestedOrder = theOrder; } - - //! Returns the derivative caching order. - Geom2dProp::CurveDerivOrder DerivOrder() const { return myRequestedOrder; } - - //! Returns the adaptor pointer (nullptr when constructed from handle). - const Adaptor2d_Curve2d* Adaptor() const { return myAdaptor; } - - //! Returns pointer to underlying geometry, or nullptr if constructed from adaptor. - const Geom2d_Curve* Geometry() const { return myCurve.get(); } - - //! Compute tangent at given parameter. - Standard_EXPORT Geom2dProp::TangentResult Tangent(double theParam, double theTol) const; - - //! Compute curvature at given parameter. - Standard_EXPORT Geom2dProp::CurvatureResult Curvature(double theParam, double theTol) const; - - //! Compute normal at given parameter. - Standard_EXPORT Geom2dProp::NormalResult Normal(double theParam, double theTol) const; - - //! Compute centre of curvature at given parameter. - Standard_EXPORT Geom2dProp::CentreResult CentreOfCurvature(double theParam, double theTol) const; - - //! Find curvature extrema using numeric root-finding. - Standard_EXPORT Geom2dProp::CurveAnalysis FindCurvatureExtrema() const; - - //! Find inflection points using numeric root-finding. - Standard_EXPORT Geom2dProp::CurveAnalysis FindInflections() const; - -private: - const Adaptor2d_Curve2d* myAdaptor; - Geom2dProp::CurveDerivOrder myRequestedOrder; - mutable Geom2dProp::CurveCache myCache; - occ::handle myCurve; //!< Geometry handle (handle path) - std::optional myDomain; //!< Optional parameter domain -}; - -#endif // _Geom2dProp_OtherCurve_HeaderFile diff --git a/src/ModelingData/TKG2d/Geom2dProp/Geom2dProp_Parabola.cxx b/src/ModelingData/TKG2d/Geom2dProp/Geom2dProp_Parabola.cxx deleted file mode 100644 index 7366a0f145..0000000000 --- a/src/ModelingData/TKG2d/Geom2dProp/Geom2dProp_Parabola.cxx +++ /dev/null @@ -1,141 +0,0 @@ -// 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 - -//================================================================================================= - -Geom2dProp::TangentResult Geom2dProp_Parabola::Tangent(const double theParam, - const double theTol) const -{ - if (myCurve.IsNull() && myAdaptor == nullptr) - { - return {{}, false}; - } - gp_Pnt2d aPnt; - gp_Vec2d aD1, aD2, aD3; - if (!myCurve.IsNull()) - { - myCurve->D3(theParam, aPnt, aD1, aD2, aD3); - } - else - { - myAdaptor->D3(theParam, aPnt, aD1, aD2, aD3); - } - return Geom2dProp::ComputeTangent(aD1, aD2, aD3, theTol); -} - -//================================================================================================= - -Geom2dProp::CurvatureResult Geom2dProp_Parabola::Curvature(const double theParam, - const double theTol) const -{ - if (myCurve.IsNull() && myAdaptor == nullptr) - { - return {0.0, false, false}; - } - gp_Pnt2d aPnt; - gp_Vec2d aD1, aD2; - if (!myCurve.IsNull()) - { - myCurve->D2(theParam, aPnt, aD1, aD2); - } - else - { - myAdaptor->D2(theParam, aPnt, aD1, aD2); - } - return Geom2dProp::ComputeCurvature(aD1, aD2, theTol); -} - -//================================================================================================= - -Geom2dProp::NormalResult Geom2dProp_Parabola::Normal(const double theParam, - const double theTol) const -{ - if (myCurve.IsNull() && myAdaptor == nullptr) - { - return {{}, false}; - } - gp_Pnt2d aPnt; - gp_Vec2d aD1, aD2; - if (!myCurve.IsNull()) - { - myCurve->D2(theParam, aPnt, aD1, aD2); - } - else - { - myAdaptor->D2(theParam, aPnt, aD1, aD2); - } - return Geom2dProp::ComputeNormal(aD1, aD2, theTol); -} - -//================================================================================================= - -Geom2dProp::CentreResult Geom2dProp_Parabola::CentreOfCurvature(const double theParam, - const double theTol) const -{ - if (myCurve.IsNull() && myAdaptor == nullptr) - { - return {{}, false}; - } - gp_Pnt2d aPnt; - gp_Vec2d aD1, aD2; - if (!myCurve.IsNull()) - { - myCurve->D2(theParam, aPnt, aD1, aD2); - } - else - { - myAdaptor->D2(theParam, aPnt, aD1, aD2); - } - return Geom2dProp::ComputeCentreOfCurvature(aPnt, aD1, aD2, theTol); -} - -//================================================================================================= - -Geom2dProp::CurveAnalysis Geom2dProp_Parabola::FindCurvatureExtrema() const -{ - Geom2dProp::CurveAnalysis aResult; - aResult.IsDone = true; - - if (myCurve.IsNull() && myAdaptor == nullptr) - { - aResult.IsDone = false; - return aResult; - } - - double aUFirst, aULast; - if (myDomain.has_value()) - { - aUFirst = myDomain->First; - aULast = myDomain->Last; - } - else if (myAdaptor != nullptr) - { - aUFirst = myAdaptor->FirstParameter(); - aULast = myAdaptor->LastParameter(); - } - else - { - aUFirst = myCurve->FirstParameter(); - aULast = myCurve->LastParameter(); - } - - // Parabola has maximum |curvature| at parameter 0 (vertex). - if (aUFirst <= 0.0 && aULast >= 0.0) - { - aResult.Points.Append({0.0, Geom2dProp::CIType::MinCurvature}); - } - - return aResult; -} diff --git a/src/ModelingData/TKG2d/Geom2dProp/Geom2dProp_Parabola.hxx b/src/ModelingData/TKG2d/Geom2dProp/Geom2dProp_Parabola.hxx deleted file mode 100644 index aa601e3cc8..0000000000 --- a/src/ModelingData/TKG2d/Geom2dProp/Geom2dProp_Parabola.hxx +++ /dev/null @@ -1,103 +0,0 @@ -// 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. - -#ifndef _Geom2dProp_Parabola_HeaderFile -#define _Geom2dProp_Parabola_HeaderFile - -#include -#include -#include -#include -#include - -#include - -//! @brief Local differential properties for a 2D parabola. -//! -//! A parabola has a single curvature extremum (maximum |curvature|) at parameter 0 -//! (the vertex). No inflection points exist. -//! -//! Can be constructed from either a Geom2dAdaptor_Curve pointer or a occ::handle. -//! When constructed from a handle, no adaptor is created. -class Geom2dProp_Parabola -{ -public: - DEFINE_STANDARD_ALLOC - - //! Constructor with adaptor pointer (non-owning). - //! @param theAdaptor the 2D curve adaptor (must wrap a parabola, must not be null) - Geom2dProp_Parabola(const Geom2dAdaptor_Curve* theAdaptor, - Geom2dProp::CurveDerivOrder theOrder = Geom2dProp::CurveDerivOrder::Undefined) - : myAdaptor(theAdaptor) - { - (void)theOrder; - } - - //! Constructor from geometry handle. - //! @param theCurve the 2D parabola geometry - //! @param theDomain optional parameter domain (for trimmed curves) - Geom2dProp_Parabola(const occ::handle& theCurve, - const std::optional& theDomain = std::nullopt, - Geom2dProp::CurveDerivOrder theOrder = Geom2dProp::CurveDerivOrder::Undefined) - : myAdaptor(nullptr), - myCurve(theCurve), - myDomain(theDomain) - { - (void)theOrder; - } - - //! Non-copyable and non-movable. - Geom2dProp_Parabola(const Geom2dProp_Parabola&) = delete; - Geom2dProp_Parabola& operator=(const Geom2dProp_Parabola&) = delete; - Geom2dProp_Parabola(Geom2dProp_Parabola&&) = delete; - Geom2dProp_Parabola& operator=(Geom2dProp_Parabola&&) = delete; - - //! Sets the derivative caching order (no-op for analytical curves). - void SetDerivOrder(Geom2dProp::CurveDerivOrder) {} - - //! Returns the derivative caching order (always Undefined for analytical curves). - Geom2dProp::CurveDerivOrder DerivOrder() const { return Geom2dProp::CurveDerivOrder::Undefined; } - - //! Returns the adaptor pointer (nullptr when constructed from handle). - const Geom2dAdaptor_Curve* Adaptor() const { return myAdaptor; } - - //! Returns pointer to underlying geometry, or nullptr if constructed from adaptor. - const Geom2d_Curve* Geometry() const { return myCurve.get(); } - - //! Compute tangent at given parameter. - Standard_EXPORT Geom2dProp::TangentResult Tangent(double theParam, double theTol) const; - - //! Compute curvature at given parameter. - Standard_EXPORT Geom2dProp::CurvatureResult Curvature(double theParam, double theTol) const; - - //! Compute normal at given parameter. - Standard_EXPORT Geom2dProp::NormalResult Normal(double theParam, double theTol) const; - - //! Compute centre of curvature at given parameter. - Standard_EXPORT Geom2dProp::CentreResult CentreOfCurvature(double theParam, double theTol) const; - - //! Find curvature extrema on the parabola. - //! Single extremum at parameter 0 (the vertex), if within parameter range. - Standard_EXPORT Geom2dProp::CurveAnalysis FindCurvatureExtrema() const; - - //! Find inflection points on the parabola. - //! A parabola has no inflection points. - Geom2dProp::CurveAnalysis FindInflections() const { return {{}, true}; } - -private: - const Geom2dAdaptor_Curve* myAdaptor; //!< Non-owning adaptor pointer (adaptor path) - occ::handle myCurve; //!< Geometry handle (handle path) - std::optional myDomain; //!< Optional parameter domain -}; - -#endif // _Geom2dProp_Parabola_HeaderFile diff --git a/src/ModelingData/TKG2d/PACKAGES.cmake b/src/ModelingData/TKG2d/PACKAGES.cmake index 731d38f1c2..f22570041f 100644 --- a/src/ModelingData/TKG2d/PACKAGES.cmake +++ b/src/ModelingData/TKG2d/PACKAGES.cmake @@ -8,5 +8,4 @@ set(OCCT_TKG2d_LIST_OF_PACKAGES Geom2dHash Geom2dGridEval Geom2dEval - Geom2dProp ) diff --git a/src/ModelingData/TKG3d/GTests/FILES.cmake b/src/ModelingData/TKG3d/GTests/FILES.cmake index 698885e2d7..e32630123a 100644 --- a/src/ModelingData/TKG3d/GTests/FILES.cmake +++ b/src/ModelingData/TKG3d/GTests/FILES.cmake @@ -46,27 +46,4 @@ set(OCCT_TKG3d_GTests_FILES GeomGridEval_Torus_Test.cxx GeomHash_CurveHasher_Test.cxx GeomHash_SurfaceHasher_Test.cxx - GeomProp_BezierCurve_Test.cxx - GeomProp_BezierSurface_Test.cxx - GeomProp_BSplineCurve_Test.cxx - GeomProp_BSplineSurface_Test.cxx - GeomProp_Circle_Test.cxx - GeomProp_Cone_Test.cxx - GeomProp_Cylinder_Test.cxx - GeomProp_Ellipse_Test.cxx - GeomProp_Hyperbola_Test.cxx - GeomProp_Line_Test.cxx - GeomProp_OffsetCurve_Test.cxx - GeomProp_OffsetSurface_Test.cxx - GeomProp_OtherCurve_Test.cxx - GeomProp_OtherSurface_Test.cxx - GeomProp_Parabola_Test.cxx - GeomProp_Plane_Test.cxx - GeomProp_Sphere_Test.cxx - GeomProp_SurfaceOfExtrusion_Test.cxx - GeomProp_SurfaceOfRevolution_Test.cxx - GeomProp_Test.cxx - GeomProp_Torus_Test.cxx - GeomProp_VsCLProps_Test.cxx - GeomProp_VsSLProps_Test.cxx ) diff --git a/src/ModelingData/TKG3d/GTests/GeomProp_BSplineCurve_Test.cxx b/src/ModelingData/TKG3d/GTests/GeomProp_BSplineCurve_Test.cxx deleted file mode 100644 index afb53e2274..0000000000 --- a/src/ModelingData/TKG3d/GTests/GeomProp_BSplineCurve_Test.cxx +++ /dev/null @@ -1,529 +0,0 @@ -// 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. - -// Tests for GeomProp_Curve with BSpline curves: piecewise polynomial curves -// with knots, span-by-span analysis, and numerical property evaluation. - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -namespace -{ -constexpr double THE_LIN_TOL = Precision::PConfusion(); -constexpr double THE_CURV_TOL = 1.0e-8; -constexpr double THE_DIR_TOL = 1.0e-6; -constexpr double THE_POINT_TOL = 1.0e-6; - -void compareTangent(const occ::handle& theCurve, const double theParam) -{ - GeomProp_Curve aProp(theCurve); - const GeomProp::TangentResult aNew = aProp.Tangent(theParam, THE_LIN_TOL); - GeomLProp_CLProps anOld(theCurve, theParam, 2, THE_LIN_TOL); - if (anOld.IsTangentDefined()) - { - ASSERT_TRUE(aNew.IsDefined); - gp_Dir anOldDir; - anOld.Tangent(anOldDir); - EXPECT_NEAR(std::abs(aNew.Direction.Dot(anOldDir)), 1.0, THE_DIR_TOL); - } -} - -void compareCurvature(const occ::handle& theCurve, const double theParam) -{ - GeomProp_Curve aProp(theCurve); - const GeomProp::CurvatureResult aNew = aProp.Curvature(theParam, THE_LIN_TOL); - GeomLProp_CLProps anOld(theCurve, theParam, 2, THE_LIN_TOL); - if (anOld.IsTangentDefined()) - { - ASSERT_TRUE(aNew.IsDefined); - EXPECT_NEAR(aNew.Value, anOld.Curvature(), THE_CURV_TOL); - } -} - -void compareNormal(const occ::handle& theCurve, const double theParam) -{ - GeomProp_Curve aProp(theCurve); - const GeomProp::NormalResult aNew = aProp.Normal(theParam, THE_LIN_TOL); - GeomLProp_CLProps anOld(theCurve, theParam, 2, THE_LIN_TOL); - if (anOld.IsTangentDefined() && std::abs(anOld.Curvature()) > THE_LIN_TOL) - { - ASSERT_TRUE(aNew.IsDefined); - gp_Dir anOldNorm; - anOld.Normal(anOldNorm); - EXPECT_NEAR(std::abs(aNew.Direction.Dot(anOldNorm)), 1.0, THE_DIR_TOL); - } -} - -void compareCentre(const occ::handle& theCurve, const double theParam) -{ - GeomProp_Curve aProp(theCurve); - const GeomProp::CentreResult aNew = aProp.CentreOfCurvature(theParam, THE_LIN_TOL); - GeomLProp_CLProps anOld(theCurve, theParam, 2, THE_LIN_TOL); - if (anOld.IsTangentDefined() && std::abs(anOld.Curvature()) > THE_LIN_TOL) - { - ASSERT_TRUE(aNew.IsDefined); - gp_Pnt anOldCentre; - anOld.CentreOfCurvature(anOldCentre); - EXPECT_NEAR(aNew.Centre.Distance(anOldCentre), 0.0, THE_POINT_TOL); - } -} - -void compareAll(const occ::handle& theCurve, - const double theFirst, - const double theLast, - const int theNbSamples = 10) -{ - const double aStep = (theLast - theFirst) / theNbSamples; - for (int i = 0; i <= theNbSamples; ++i) - { - const double aParam = theFirst + i * aStep; - compareTangent(theCurve, aParam); - compareCurvature(theCurve, aParam); - compareNormal(theCurve, aParam); - compareCentre(theCurve, aParam); - } -} - -//! Create a cubic C2 BSpline with 6 poles, knots [0, 0.33, 0.66, 1], mults [4,1,1,4]. -occ::handle makeCubicC2() -{ - NCollection_Array1 aPoles(1, 6); - aPoles(1) = gp_Pnt(0, 0, 0); - aPoles(2) = gp_Pnt(1, 3, 0); - aPoles(3) = gp_Pnt(2, 1, 1); - aPoles(4) = gp_Pnt(3, 4, 0); - aPoles(5) = gp_Pnt(4, 2, 1); - aPoles(6) = gp_Pnt(5, 0, 0); - - NCollection_Array1 aKnots(1, 4); - aKnots(1) = 0.0; - aKnots(2) = 0.33; - aKnots(3) = 0.66; - aKnots(4) = 1.0; - - NCollection_Array1 aMults(1, 4); - aMults(1) = 4; - aMults(2) = 1; - aMults(3) = 1; - aMults(4) = 4; - - return new Geom_BSplineCurve(aPoles, aKnots, aMults, 3); -} - -//! Create a quadratic C1 BSpline with 5 poles, knots [0, 0.33, 0.66, 1], mults [3,1,1,3]. -occ::handle makeQuadraticC1() -{ - NCollection_Array1 aPoles(1, 5); - aPoles(1) = gp_Pnt(0, 0, 0); - aPoles(2) = gp_Pnt(1, 2, 0); - aPoles(3) = gp_Pnt(2, -1, 1); - aPoles(4) = gp_Pnt(3, 3, 0); - aPoles(5) = gp_Pnt(4, 0, 0); - - NCollection_Array1 aKnots(1, 4); - aKnots(1) = 0.0; - aKnots(2) = 0.33; - aKnots(3) = 0.66; - aKnots(4) = 1.0; - - NCollection_Array1 aMults(1, 4); - aMults(1) = 3; - aMults(2) = 1; - aMults(3) = 1; - aMults(4) = 3; - - return new Geom_BSplineCurve(aPoles, aKnots, aMults, 2); -} - -//! Create a degree 4 single-span BSpline (Bezier-like), knots [0,1], mults [5,5]. -occ::handle makeDegree4() -{ - NCollection_Array1 aPoles(1, 5); - aPoles(1) = gp_Pnt(0, 0, 0); - aPoles(2) = gp_Pnt(1, 4, 0); - aPoles(3) = gp_Pnt(2, -2, 1); - aPoles(4) = gp_Pnt(3, 3, 0); - aPoles(5) = gp_Pnt(4, 0, 0); - - NCollection_Array1 aKnots(1, 2); - aKnots(1) = 0.0; - aKnots(2) = 1.0; - - NCollection_Array1 aMults(1, 2); - aMults(1) = 5; - aMults(2) = 5; - - return new Geom_BSplineCurve(aPoles, aKnots, aMults, 4); -} - -//! Create a multi-span cubic BSpline with 8 poles and 6 knots. -occ::handle makeMultiSpanCubic() -{ - NCollection_Array1 aPoles(1, 8); - aPoles(1) = gp_Pnt(0, 0, 0); - aPoles(2) = gp_Pnt(1, 3, 0); - aPoles(3) = gp_Pnt(2, -1, 1); - aPoles(4) = gp_Pnt(3, 2, 0); - aPoles(5) = gp_Pnt(4, -2, 1); - aPoles(6) = gp_Pnt(5, 3, 0); - aPoles(7) = gp_Pnt(6, 1, 1); - aPoles(8) = gp_Pnt(7, 0, 0); - - NCollection_Array1 aKnots(1, 6); - aKnots(1) = 0.0; - aKnots(2) = 0.2; - aKnots(3) = 0.4; - aKnots(4) = 0.6; - aKnots(5) = 0.8; - aKnots(6) = 1.0; - - NCollection_Array1 aMults(1, 6); - aMults(1) = 4; - aMults(2) = 1; - aMults(3) = 1; - aMults(4) = 1; - aMults(5) = 1; - aMults(6) = 4; - - return new Geom_BSplineCurve(aPoles, aKnots, aMults, 3); -} - -} // namespace - -// ============================================================================ -// Tangent tests -// ============================================================================ - -TEST(GeomProp_BSplineCurveTest, Tangent_CubicEndpoints) -{ - occ::handle aBSpline = makeCubicC2(); - GeomProp_Curve aProp(aBSpline); - - const GeomProp::TangentResult aTanFirst = aProp.Tangent(0.0, THE_LIN_TOL); - ASSERT_TRUE(aTanFirst.IsDefined); - // gp_Dir is always unit length; just verify it's defined - (void)aTanFirst.Direction; - - const GeomProp::TangentResult aTanLast = aProp.Tangent(1.0, THE_LIN_TOL); - ASSERT_TRUE(aTanLast.IsDefined); - (void)aTanLast.Direction; -} - -TEST(GeomProp_BSplineCurveTest, Tangent_AtKnots) -{ - occ::handle aBSpline = makeCubicC2(); - GeomProp_Curve aProp(aBSpline); - - // Internal knots at 0.33 and 0.66 - const GeomProp::TangentResult aTan1 = aProp.Tangent(0.33, THE_LIN_TOL); - ASSERT_TRUE(aTan1.IsDefined); - - const GeomProp::TangentResult aTan2 = aProp.Tangent(0.66, THE_LIN_TOL); - ASSERT_TRUE(aTan2.IsDefined); -} - -// ============================================================================ -// Curvature tests -// ============================================================================ - -TEST(GeomProp_BSplineCurveTest, Curvature_CubicSmooth) -{ - occ::handle aBSpline = makeCubicC2(); - GeomProp_Curve aProp(aBSpline); - - for (double aParam = 0.0; aParam <= 1.0; aParam += 0.25) - { - const GeomProp::CurvatureResult aCurv = aProp.Curvature(aParam, THE_LIN_TOL); - ASSERT_TRUE(aCurv.IsDefined) << "Curvature undefined at param=" << aParam; - EXPECT_GE(aCurv.Value, 0.0) << "Curvature negative at param=" << aParam; - } -} - -TEST(GeomProp_BSplineCurveTest, Curvature_AtKnots) -{ - occ::handle aBSpline = makeCubicC2(); - GeomProp_Curve aProp(aBSpline); - - const GeomProp::CurvatureResult aCurv1 = aProp.Curvature(0.33, THE_LIN_TOL); - ASSERT_TRUE(aCurv1.IsDefined); - - const GeomProp::CurvatureResult aCurv2 = aProp.Curvature(0.66, THE_LIN_TOL); - ASSERT_TRUE(aCurv2.IsDefined); -} - -TEST(GeomProp_BSplineCurveTest, Curvature_Degree4_Bezier) -{ - occ::handle aBSpline = makeDegree4(); - GeomProp_Curve aProp(aBSpline); - - for (double aParam = 0.0; aParam <= 1.0; aParam += 0.2) - { - const GeomProp::CurvatureResult aCurv = aProp.Curvature(aParam, THE_LIN_TOL); - ASSERT_TRUE(aCurv.IsDefined) << "Curvature undefined at param=" << aParam; - EXPECT_GE(aCurv.Value, 0.0) << "Curvature negative at param=" << aParam; - } -} - -// ============================================================================ -// Normal tests -// ============================================================================ - -TEST(GeomProp_BSplineCurveTest, Normal_CubicSmooth) -{ - occ::handle aBSpline = makeCubicC2(); - GeomProp_Curve aProp(aBSpline); - - for (double aParam = 0.1; aParam <= 0.9; aParam += 0.2) - { - const GeomProp::NormalResult aNorm = aProp.Normal(aParam, THE_LIN_TOL); - if (aNorm.IsDefined) - { - (void)aNorm.Direction; - } - } -} - -// ============================================================================ -// Centre of curvature tests -// ============================================================================ - -TEST(GeomProp_BSplineCurveTest, Centre_CubicSmooth) -{ - occ::handle aBSpline = makeCubicC2(); - GeomProp_Curve aProp(aBSpline); - - for (double aParam = 0.1; aParam <= 0.9; aParam += 0.2) - { - const GeomProp::CentreResult aCentre = aProp.CentreOfCurvature(aParam, THE_LIN_TOL); - const GeomProp::CurvatureResult aCurv = aProp.Curvature(aParam, THE_LIN_TOL); - if (aCentre.IsDefined && aCurv.IsDefined && aCurv.Value > THE_LIN_TOL) - { - // Centre should be at distance 1/curvature from the curve point - gp_Pnt aPntOnCurve; - aBSpline->D0(aParam, aPntOnCurve); - const double aExpectedDist = 1.0 / aCurv.Value; - EXPECT_NEAR(aCentre.Centre.Distance(aPntOnCurve), aExpectedDist, THE_POINT_TOL); - } - } -} - -// ============================================================================ -// FindCurvatureExtrema tests -// ============================================================================ - -TEST(GeomProp_BSplineCurveTest, FindCurvatureExtrema_Cubic) -{ - occ::handle aBSpline = makeCubicC2(); - GeomProp_Curve aProp(aBSpline); - - const GeomProp::CurveAnalysis aResult = aProp.FindCurvatureExtrema(); - ASSERT_TRUE(aResult.IsDone); - // Cubic BSpline with varying curvature should have at least one extremum - for (int i = 0; i < aResult.Points.Length(); ++i) - { - EXPECT_GE(aResult.Points[i].Parameter, 0.0); - EXPECT_LE(aResult.Points[i].Parameter, 1.0); - EXPECT_TRUE(aResult.Points[i].Type == GeomProp::CIType::MinCurvature - || aResult.Points[i].Type == GeomProp::CIType::MaxCurvature); - } -} - -TEST(GeomProp_BSplineCurveTest, FindCurvatureExtrema_LowContinuity) -{ - occ::handle aBSpline = makeQuadraticC1(); - GeomProp_Curve aProp(aBSpline); - - const GeomProp::CurveAnalysis aResult = aProp.FindCurvatureExtrema(); - ASSERT_TRUE(aResult.IsDone); - for (int i = 0; i < aResult.Points.Length(); ++i) - { - EXPECT_GE(aResult.Points[i].Parameter, 0.0); - EXPECT_LE(aResult.Points[i].Parameter, 1.0); - } -} - -TEST(GeomProp_BSplineCurveTest, FindCurvatureExtrema_MultipleSpans) -{ - occ::handle aBSpline = makeMultiSpanCubic(); - GeomProp_Curve aProp(aBSpline); - - const GeomProp::CurveAnalysis aResult = aProp.FindCurvatureExtrema(); - ASSERT_TRUE(aResult.IsDone); - for (int i = 0; i < aResult.Points.Length(); ++i) - { - EXPECT_GE(aResult.Points[i].Parameter, 0.0); - EXPECT_LE(aResult.Points[i].Parameter, 1.0); - } -} - -// ============================================================================ -// FindInflections tests -// ============================================================================ - -TEST(GeomProp_BSplineCurveTest, FindInflections_Cubic) -{ - occ::handle aBSpline = makeCubicC2(); - GeomProp_Curve aProp(aBSpline); - - const GeomProp::CurveAnalysis aResult = aProp.FindInflections(); - ASSERT_TRUE(aResult.IsDone); - for (int i = 0; i < aResult.Points.Length(); ++i) - { - EXPECT_GE(aResult.Points[i].Parameter, 0.0); - EXPECT_LE(aResult.Points[i].Parameter, 1.0); - EXPECT_EQ(aResult.Points[i].Type, GeomProp::CIType::Inflection); - } -} - -TEST(GeomProp_BSplineCurveTest, FindInflections_LowContinuity) -{ - occ::handle aBSpline = makeQuadraticC1(); - GeomProp_Curve aProp(aBSpline); - - const GeomProp::CurveAnalysis aResult = aProp.FindInflections(); - ASSERT_TRUE(aResult.IsDone); - for (int i = 0; i < aResult.Points.Length(); ++i) - { - EXPECT_GE(aResult.Points[i].Parameter, 0.0); - EXPECT_LE(aResult.Points[i].Parameter, 1.0); - EXPECT_EQ(aResult.Points[i].Type, GeomProp::CIType::Inflection); - } -} - -TEST(GeomProp_BSplineCurveTest, FindInflections_MultipleSpans) -{ - occ::handle aBSpline = makeMultiSpanCubic(); - GeomProp_Curve aProp(aBSpline); - - const GeomProp::CurveAnalysis aResult = aProp.FindInflections(); - ASSERT_TRUE(aResult.IsDone); - for (int i = 0; i < aResult.Points.Length(); ++i) - { - EXPECT_GE(aResult.Points[i].Parameter, 0.0); - EXPECT_LE(aResult.Points[i].Parameter, 1.0); - EXPECT_EQ(aResult.Points[i].Type, GeomProp::CIType::Inflection); - } -} - -// ============================================================================ -// GetType test -// ============================================================================ - -TEST(GeomProp_BSplineCurveTest, GetType_IsBSpline) -{ - occ::handle aBSpline = makeCubicC2(); - GeomProp_Curve aProp(aBSpline); - EXPECT_EQ(aProp.GetType(), GeomAbs_BSplineCurve); -} - -// ============================================================================ -// VsCLProps comparison tests -// ============================================================================ - -TEST(GeomProp_BSplineCurveTest, VsCLProps_CubicSmooth) -{ - occ::handle aBSpline = makeCubicC2(); - compareAll(aBSpline, 0.0, 1.0); -} - -TEST(GeomProp_BSplineCurveTest, VsCLProps_Quadratic) -{ - occ::handle aBSpline = makeQuadraticC1(); - compareAll(aBSpline, 0.0, 1.0); -} - -TEST(GeomProp_BSplineCurveTest, VsCLProps_Degree4) -{ - occ::handle aBSpline = makeDegree4(); - compareAll(aBSpline, 0.0, 1.0); -} - -TEST(GeomProp_BSplineCurveTest, VsCLProps_AllProperties_Cubic) -{ - occ::handle aBSpline = makeCubicC2(); - compareAll(aBSpline, 0.0, 1.0, 20); -} - -TEST(GeomProp_BSplineCurveTest, VsCLProps_AllProperties_Degree4) -{ - occ::handle aBSpline = makeDegree4(); - compareAll(aBSpline, 0.0, 1.0, 20); -} - -TEST(GeomProp_BSplineCurveTest, VsCLProps_LowContinuity) -{ - occ::handle aBSpline = makeQuadraticC1(); - compareAll(aBSpline, 0.0, 1.0); -} - -TEST(GeomProp_BSplineCurveTest, VsCLProps_MultipleSpans) -{ - occ::handle aBSpline = makeMultiSpanCubic(); - compareAll(aBSpline, 0.0, 1.0, 20); -} - -TEST(GeomProp_BSplineCurveTest, VsCLProps_CriticalPoints) -{ - // Cubic C2 BSpline with uniform knots - NCollection_Array1 aPoles(1, 6); - aPoles(1) = gp_Pnt(0, 0, 0); - aPoles(2) = gp_Pnt(1, 2, 0); - aPoles(3) = gp_Pnt(2, -1, 1); - aPoles(4) = gp_Pnt(3, 1, 0); - aPoles(5) = gp_Pnt(4, -2, 1); - aPoles(6) = gp_Pnt(5, 0, 0); - NCollection_Array1 aKnots(1, 4); - aKnots(1) = 0.0; - aKnots(2) = 0.33; - aKnots(3) = 0.66; - aKnots(4) = 1.0; - NCollection_Array1 aMults(1, 4); - aMults(1) = 4; - aMults(2) = 1; - aMults(3) = 1; - aMults(4) = 4; - occ::handle aBSpline = new Geom_BSplineCurve(aPoles, aKnots, aMults, 3); - // Critical: endpoints, knots, near-knots, span midpoints - const double aParams[] = {0.0, - 1.0e-10, - 1.0e-6, - 0.33, - 0.33 + 1.0e-6, - 0.33 - 1.0e-6, - 0.66, - 0.66 + 1.0e-6, - 0.66 - 1.0e-6, - 1.0 - 1.0e-6, - 1.0 - 1.0e-10, - 1.0, - 0.165, - 0.495, - 0.83}; - for (const double aParam : aParams) - { - compareTangent(aBSpline, aParam); - compareCurvature(aBSpline, aParam); - compareNormal(aBSpline, aParam); - compareCentre(aBSpline, aParam); - } -} diff --git a/src/ModelingData/TKG3d/GTests/GeomProp_BSplineSurface_Test.cxx b/src/ModelingData/TKG3d/GTests/GeomProp_BSplineSurface_Test.cxx deleted file mode 100644 index b67ad57fe9..0000000000 --- a/src/ModelingData/TKG3d/GTests/GeomProp_BSplineSurface_Test.cxx +++ /dev/null @@ -1,471 +0,0 @@ -// 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. - -// Tests for GeomProp_Surface with Geom_BSplineSurface. -// Validates normal, curvatures, mean/Gaussian curvature for flat and curved -// bicubic BSpline patches. Cross-validates against GeomLProp_SLProps. - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -namespace -{ -constexpr double THE_LIN_TOL = Precision::PConfusion(); -constexpr double THE_CURV_TOL = 1.0e-6; -constexpr double THE_DIR_TOL = 1.0e-4; - -//! Compare surface normal from new GeomProp_Surface vs old GeomLProp_SLProps. -void compareNormal(const occ::handle& theSurf, const double theU, const double theV) -{ - GeomProp_Surface aProp(theSurf); - const GeomProp::SurfaceNormalResult aNew = aProp.Normal(theU, theV, THE_LIN_TOL); - - GeomLProp_SLProps anOld(theSurf, theU, theV, 2, THE_LIN_TOL); - if (anOld.IsNormalDefined()) - { - ASSERT_TRUE(aNew.IsDefined) << "New normal undefined at (" << theU << "," << theV << ")"; - const double aDot = aNew.Direction.Dot(anOld.Normal()); - EXPECT_NEAR(std::abs(aDot), 1.0, THE_DIR_TOL) - << "Normal mismatch at (" << theU << "," << theV << ")"; - } -} - -//! Compare curvatures from new GeomProp_Surface vs old GeomLProp_SLProps. -void compareCurvatures(const occ::handle& theSurf, - const double theU, - const double theV) -{ - GeomProp_Surface aProp(theSurf); - const GeomProp::SurfaceCurvatureResult aNew = aProp.Curvatures(theU, theV, THE_LIN_TOL); - - GeomLProp_SLProps anOld(theSurf, theU, theV, 2, THE_LIN_TOL); - if (anOld.IsCurvatureDefined()) - { - ASSERT_TRUE(aNew.IsDefined) << "New curvatures undefined at (" << theU << "," << theV << ")"; - EXPECT_NEAR(aNew.MinCurvature, anOld.MinCurvature(), THE_CURV_TOL) - << "MinCurvature mismatch at (" << theU << "," << theV << ")"; - EXPECT_NEAR(aNew.MaxCurvature, anOld.MaxCurvature(), THE_CURV_TOL) - << "MaxCurvature mismatch at (" << theU << "," << theV << ")"; - } -} - -//! Compare mean and Gaussian curvatures. -void compareMeanGaussian(const occ::handle& theSurf, - const double theU, - const double theV) -{ - GeomProp_Surface aProp(theSurf); - const GeomProp::MeanGaussianResult aNew = aProp.MeanGaussian(theU, theV, THE_LIN_TOL); - - GeomLProp_SLProps anOld(theSurf, theU, theV, 2, THE_LIN_TOL); - if (anOld.IsCurvatureDefined()) - { - ASSERT_TRUE(aNew.IsDefined) << "New MeanGaussian undefined at (" << theU << "," << theV << ")"; - EXPECT_NEAR(aNew.MeanCurvature, anOld.MeanCurvature(), THE_CURV_TOL) - << "Mean curvature mismatch at (" << theU << "," << theV << ")"; - EXPECT_NEAR(aNew.GaussianCurvature, anOld.GaussianCurvature(), THE_CURV_TOL) - << "Gaussian curvature mismatch at (" << theU << "," << theV << ")"; - } -} - -//! Run all surface comparisons at a grid of parameter values. -void compareAllSurface(const occ::handle& theSurf, - const double theUMin, - const double theUMax, - const double theVMin, - const double theVMax, - const int theNbU = 5, - const int theNbV = 5) -{ - const double aUStep = (theUMax - theUMin) / theNbU; - const double aVStep = (theVMax - theVMin) / theNbV; - for (int i = 0; i <= theNbU; ++i) - { - for (int j = 0; j <= theNbV; ++j) - { - const double aU = theUMin + i * aUStep; - const double aV = theVMin + j * aVStep; - compareNormal(theSurf, aU, aV); - compareCurvatures(theSurf, aU, aV); - compareMeanGaussian(theSurf, aU, aV); - } - } -} - -//! Create a flat (planar) 4x4 bicubic BSpline patch. -occ::handle makeFlatBSpline() -{ - NCollection_Array2 aPoles(1, 4, 1, 4); - for (int i = 1; i <= 4; ++i) - { - for (int j = 1; j <= 4; ++j) - { - aPoles.SetValue(i, j, gp_Pnt((i - 1) * 1.0, (j - 1) * 1.0, 0.0)); - } - } - - NCollection_Array1 aUKnots(1, 2), aVKnots(1, 2); - NCollection_Array1 aUMults(1, 2), aVMults(1, 2); - aUKnots(1) = 0.0; - aUKnots(2) = 1.0; - aVKnots(1) = 0.0; - aVKnots(2) = 1.0; - aUMults(1) = 4; - aUMults(2) = 4; - aVMults(1) = 4; - aVMults(2) = 4; - - return new Geom_BSplineSurface(aPoles, aUKnots, aVKnots, aUMults, aVMults, 3, 3); -} - -//! Create a curved 4x4 bicubic BSpline patch with wavy Z variation. -occ::handle makeCurvedBSpline() -{ - NCollection_Array2 aPoles(1, 4, 1, 4); - for (int i = 1; i <= 4; ++i) - { - for (int j = 1; j <= 4; ++j) - { - const double aX = (i - 1) * 1.0; - const double aY = (j - 1) * 1.0; - const double aZ = std::sin(aX * 0.5) * std::cos(aY * 0.5); - aPoles.SetValue(i, j, gp_Pnt(aX, aY, aZ)); - } - } - - NCollection_Array1 aUKnots(1, 2), aVKnots(1, 2); - NCollection_Array1 aUMults(1, 2), aVMults(1, 2); - aUKnots(1) = 0.0; - aUKnots(2) = 1.0; - aVKnots(1) = 0.0; - aVKnots(2) = 1.0; - aUMults(1) = 4; - aUMults(2) = 4; - aVMults(1) = 4; - aVMults(2) = 4; - - return new Geom_BSplineSurface(aPoles, aUKnots, aVKnots, aUMults, aVMults, 3, 3); -} -} // namespace - -// Normal at center of curved BSpline patch -TEST(GeomProp_BSplineSurfaceTest, Normal_AtCenter) -{ - occ::handle aSurf = makeCurvedBSpline(); - GeomProp_Surface aProp(aSurf); - - const GeomProp::SurfaceNormalResult aResult = aProp.Normal(0.5, 0.5, THE_LIN_TOL); - ASSERT_TRUE(aResult.IsDefined); - EXPECT_GT(std::abs(aResult.Direction.Z()), 0.1); -} - -// Normal at all four corners -TEST(GeomProp_BSplineSurfaceTest, Normal_AtCorners) -{ - occ::handle aSurf = makeCurvedBSpline(); - GeomProp_Surface aProp(aSurf); - - const double aCorners[][2] = {{0.0, 0.0}, {1.0, 0.0}, {0.0, 1.0}, {1.0, 1.0}}; - for (const auto& aUV : aCorners) - { - const GeomProp::SurfaceNormalResult aResult = aProp.Normal(aUV[0], aUV[1], THE_LIN_TOL); - ASSERT_TRUE(aResult.IsDefined) << "Normal undefined at (" << aUV[0] << "," << aUV[1] << ")"; - } -} - -// Normal at 5x5 grid -TEST(GeomProp_BSplineSurfaceTest, Normal_Grid) -{ - occ::handle aSurf = makeCurvedBSpline(); - GeomProp_Surface aProp(aSurf); - - for (int i = 0; i <= 4; ++i) - { - for (int j = 0; j <= 4; ++j) - { - const double aU = i / 4.0; - const double aV = j / 4.0; - const GeomProp::SurfaceNormalResult aResult = aProp.Normal(aU, aV, THE_LIN_TOL); - ASSERT_TRUE(aResult.IsDefined) << "Normal undefined at (" << aU << "," << aV << ")"; - } - } -} - -// Curvatures at center -TEST(GeomProp_BSplineSurfaceTest, Curvatures_AtCenter) -{ - occ::handle aSurf = makeCurvedBSpline(); - GeomProp_Surface aProp(aSurf); - - const GeomProp::SurfaceCurvatureResult aResult = aProp.Curvatures(0.5, 0.5, THE_LIN_TOL); - ASSERT_TRUE(aResult.IsDefined); - EXPECT_LE(aResult.MinCurvature, aResult.MaxCurvature); -} - -// Curvatures at corners -TEST(GeomProp_BSplineSurfaceTest, Curvatures_AtCorners) -{ - occ::handle aSurf = makeCurvedBSpline(); - GeomProp_Surface aProp(aSurf); - - const double aCorners[][2] = {{0.0, 0.0}, {1.0, 0.0}, {0.0, 1.0}, {1.0, 1.0}}; - for (const auto& aUV : aCorners) - { - const GeomProp::SurfaceCurvatureResult aResult = aProp.Curvatures(aUV[0], aUV[1], THE_LIN_TOL); - ASSERT_TRUE(aResult.IsDefined) << "Curvatures undefined at (" << aUV[0] << "," << aUV[1] << ")"; - EXPECT_LE(aResult.MinCurvature, aResult.MaxCurvature); - } -} - -// Mean and Gaussian curvature at center -TEST(GeomProp_BSplineSurfaceTest, MeanGaussian_AtCenter) -{ - occ::handle aSurf = makeCurvedBSpline(); - GeomProp_Surface aProp(aSurf); - - const GeomProp::MeanGaussianResult aResult = aProp.MeanGaussian(0.5, 0.5, THE_LIN_TOL); - ASSERT_TRUE(aResult.IsDefined); -} - -// GetType returns GeomAbs_BSplineSurface -TEST(GeomProp_BSplineSurfaceTest, GetType_IsBSplineSurface) -{ - occ::handle aSurf = makeCurvedBSpline(); - GeomProp_Surface aProp(aSurf); - EXPECT_EQ(aProp.GetType(), GeomAbs_BSplineSurface); -} - -// Flat BSpline: curvatures are all zero -TEST(GeomProp_BSplineSurfaceTest, Curvatures_FlatPatch) -{ - occ::handle aSurf = makeFlatBSpline(); - GeomProp_Surface aProp(aSurf); - - for (double aU = 0.0; aU <= 1.0; aU += 0.25) - { - for (double aV = 0.0; aV <= 1.0; aV += 0.25) - { - const GeomProp::SurfaceCurvatureResult aResult = aProp.Curvatures(aU, aV, THE_LIN_TOL); - ASSERT_TRUE(aResult.IsDefined) << "Curvatures undefined at (" << aU << "," << aV << ")"; - EXPECT_NEAR(aResult.MinCurvature, 0.0, THE_CURV_TOL); - EXPECT_NEAR(aResult.MaxCurvature, 0.0, THE_CURV_TOL); - } - } -} - -// Flat BSpline: H=K=0 -TEST(GeomProp_BSplineSurfaceTest, MeanGaussian_FlatPatch) -{ - occ::handle aSurf = makeFlatBSpline(); - GeomProp_Surface aProp(aSurf); - - for (double aU = 0.0; aU <= 1.0; aU += 0.25) - { - for (double aV = 0.0; aV <= 1.0; aV += 0.25) - { - const GeomProp::MeanGaussianResult aResult = aProp.MeanGaussian(aU, aV, THE_LIN_TOL); - ASSERT_TRUE(aResult.IsDefined); - EXPECT_NEAR(aResult.MeanCurvature, 0.0, THE_CURV_TOL); - EXPECT_NEAR(aResult.GaussianCurvature, 0.0, THE_CURV_TOL); - } - } -} - -// Cross-validate normal against SLProps -TEST(GeomProp_BSplineSurfaceTest, VsSLProps_Normal) -{ - occ::handle aSurf = makeCurvedBSpline(); - for (int i = 0; i <= 4; ++i) - { - for (int j = 0; j <= 4; ++j) - { - compareNormal(aSurf, i / 4.0, j / 4.0); - } - } -} - -// Cross-validate curvatures against SLProps -TEST(GeomProp_BSplineSurfaceTest, VsSLProps_Curvatures) -{ - occ::handle aSurf = makeCurvedBSpline(); - for (int i = 0; i <= 4; ++i) - { - for (int j = 0; j <= 4; ++j) - { - compareCurvatures(aSurf, i / 4.0, j / 4.0); - } - } -} - -// Cross-validate mean/Gaussian against SLProps -TEST(GeomProp_BSplineSurfaceTest, VsSLProps_MeanGaussian) -{ - occ::handle aSurf = makeCurvedBSpline(); - for (int i = 0; i <= 4; ++i) - { - for (int j = 0; j <= 4; ++j) - { - compareMeanGaussian(aSurf, i / 4.0, j / 4.0); - } - } -} - -// Dense cross-validation of all properties -TEST(GeomProp_BSplineSurfaceTest, VsSLProps_AllProperties) -{ - occ::handle aSurf = makeCurvedBSpline(); - compareAllSurface(aSurf, 0.0, 1.0, 0.0, 1.0, 6, 6); -} - -// Cross-validate flat patch -TEST(GeomProp_BSplineSurfaceTest, VsSLProps_FlatPatch) -{ - occ::handle aSurf = makeFlatBSpline(); - compareAllSurface(aSurf, 0.0, 1.0, 0.0, 1.0); -} - -// Curved patch has non-zero curvatures -TEST(GeomProp_BSplineSurfaceTest, Curvatures_CurvedPatch) -{ - occ::handle aSurf = makeCurvedBSpline(); - GeomProp_Surface aProp(aSurf); - - const GeomProp::SurfaceCurvatureResult aResult = aProp.Curvatures(0.5, 0.5, THE_LIN_TOL); - ASSERT_TRUE(aResult.IsDefined); - const double aMaxAbsK = std::max(std::abs(aResult.MinCurvature), std::abs(aResult.MaxCurvature)); - EXPECT_GT(aMaxAbsK, THE_CURV_TOL); -} - -// Curved patch: non-trivial mean and Gaussian curvatures -TEST(GeomProp_BSplineSurfaceTest, MeanGaussian_CurvedPatch) -{ - occ::handle aSurf = makeCurvedBSpline(); - GeomProp_Surface aProp(aSurf); - - const GeomProp::MeanGaussianResult aResult = aProp.MeanGaussian(0.5, 0.5, THE_LIN_TOL); - ASSERT_TRUE(aResult.IsDefined); - const double aAbsH = std::abs(aResult.MeanCurvature); - const double aAbsK = std::abs(aResult.GaussianCurvature); - EXPECT_GT(aAbsH + aAbsK, THE_CURV_TOL); -} - -// Normal varies smoothly across the patch -TEST(GeomProp_BSplineSurfaceTest, Normal_SmoothVariation) -{ - occ::handle aSurf = makeCurvedBSpline(); - GeomProp_Surface aProp(aSurf); - - constexpr int aNbSteps = 20; - constexpr double aStep = 1.0 / aNbSteps; - gp_Dir aPrevNormal; - bool aHasPrev = false; - - for (int i = 0; i <= aNbSteps; ++i) - { - const double aU = i * aStep; - const GeomProp::SurfaceNormalResult aResult = aProp.Normal(aU, 0.5, THE_LIN_TOL); - ASSERT_TRUE(aResult.IsDefined) << "Normal undefined at u=" << aU; - - if (aHasPrev) - { - const double aDot = aResult.Direction.Dot(aPrevNormal); - EXPECT_GT(aDot, 0.9) << "Normal changed abruptly at u=" << aU; - } - aPrevNormal = aResult.Direction; - aHasPrev = true; - } -} - -// Dense 8x8 grid cross-validation -TEST(GeomProp_BSplineSurfaceTest, VsSLProps_DenseGrid) -{ - occ::handle aSurf = makeCurvedBSpline(); - compareAllSurface(aSurf, 0.0, 1.0, 0.0, 1.0, 8, 8); -} - -// Evaluate curvatures at knot values -TEST(GeomProp_BSplineSurfaceTest, Curvatures_AtKnots) -{ - occ::handle aSurf = makeCurvedBSpline(); - GeomProp_Surface aProp(aSurf); - - // Knots are at 0.0 and 1.0 for this simple patch - const double aKnots[] = {0.0, 1.0}; - for (const double aUKnot : aKnots) - { - for (const double aVKnot : aKnots) - { - const GeomProp::SurfaceCurvatureResult aResult = - aProp.Curvatures(aUKnot, aVKnot, THE_LIN_TOL); - ASSERT_TRUE(aResult.IsDefined) - << "Curvatures undefined at knot (" << aUKnot << "," << aVKnot << ")"; - EXPECT_LE(aResult.MinCurvature, aResult.MaxCurvature); - } - } -} - -// Normal at knot values -TEST(GeomProp_BSplineSurfaceTest, Normal_AtKnots) -{ - occ::handle aSurf = makeCurvedBSpline(); - GeomProp_Surface aProp(aSurf); - - const double aKnots[] = {0.0, 1.0}; - for (const double aUKnot : aKnots) - { - for (const double aVKnot : aKnots) - { - const GeomProp::SurfaceNormalResult aResult = aProp.Normal(aUKnot, aVKnot, THE_LIN_TOL); - ASSERT_TRUE(aResult.IsDefined) - << "Normal undefined at knot (" << aUKnot << "," << aVKnot << ")"; - } - } -} - -TEST(GeomProp_BSplineSurfaceTest, VsSLProps_CriticalPoints) -{ - occ::handle aSurf = makeCurvedBSpline(); - // Critical: corners, edges, center, near-corners - const double aParams[][2] = {{0.0, 0.0}, - {1.0, 1.0}, - {0.0, 1.0}, - {1.0, 0.0}, - {0.5, 0.5}, - {0.5, 0.0}, - {0.0, 0.5}, - {1.0, 0.5}, - {0.5, 1.0}, - {1.0e-10, 1.0e-10}, - {1.0 - 1.0e-10, 1.0 - 1.0e-10}, - {0.25, 0.25}, - {0.75, 0.75}, - {0.25, 0.75}}; - for (const auto& aUV : aParams) - { - compareNormal(aSurf, aUV[0], aUV[1]); - compareCurvatures(aSurf, aUV[0], aUV[1]); - compareMeanGaussian(aSurf, aUV[0], aUV[1]); - } -} diff --git a/src/ModelingData/TKG3d/GTests/GeomProp_BezierCurve_Test.cxx b/src/ModelingData/TKG3d/GTests/GeomProp_BezierCurve_Test.cxx deleted file mode 100644 index 4e7027845d..0000000000 --- a/src/ModelingData/TKG3d/GTests/GeomProp_BezierCurve_Test.cxx +++ /dev/null @@ -1,469 +0,0 @@ -// 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. - -// Tests for GeomProp_Curve with Geom_BezierCurve curves. -// Validates curvature, tangent, normal, and centre of curvature properties -// for linear, quadratic, cubic, and high-degree Bezier curves. -// Cross-validates against GeomLProp_CLProps. - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -namespace -{ -constexpr double THE_LIN_TOL = Precision::PConfusion(); -constexpr double THE_CURV_TOL = 1.0e-8; -constexpr double THE_DIR_TOL = 1.0e-6; -constexpr double THE_POINT_TOL = 1.0e-6; - -//! Compare tangent from new GeomProp_Curve vs old GeomLProp_CLProps. -void compareTangent(const occ::handle& theCurve, const double theParam) -{ - GeomProp_Curve aProp(theCurve); - const GeomProp::TangentResult aNew = aProp.Tangent(theParam, THE_LIN_TOL); - - GeomLProp_CLProps anOld(theCurve, theParam, 2, THE_LIN_TOL); - if (anOld.IsTangentDefined()) - { - ASSERT_TRUE(aNew.IsDefined) << "New tangent undefined but old is defined at param=" << theParam; - gp_Dir anOldDir; - anOld.Tangent(anOldDir); - const double aDot = aNew.Direction.Dot(anOldDir); - EXPECT_NEAR(std::abs(aDot), 1.0, THE_DIR_TOL) - << "Tangent direction mismatch at param=" << theParam; - } -} - -//! Compare curvature from new GeomProp_Curve vs old GeomLProp_CLProps. -void compareCurvature(const occ::handle& theCurve, const double theParam) -{ - GeomProp_Curve aProp(theCurve); - const GeomProp::CurvatureResult aNew = aProp.Curvature(theParam, THE_LIN_TOL); - - GeomLProp_CLProps anOld(theCurve, theParam, 2, THE_LIN_TOL); - if (anOld.IsTangentDefined()) - { - ASSERT_TRUE(aNew.IsDefined) << "New curvature undefined at param=" << theParam; - EXPECT_NEAR(aNew.Value, anOld.Curvature(), THE_CURV_TOL) - << "Curvature mismatch at param=" << theParam; - } -} - -//! Compare normal from new GeomProp_Curve vs old GeomLProp_CLProps. -void compareNormal(const occ::handle& theCurve, const double theParam) -{ - GeomProp_Curve aProp(theCurve); - const GeomProp::NormalResult aNew = aProp.Normal(theParam, THE_LIN_TOL); - - GeomLProp_CLProps anOld(theCurve, theParam, 2, THE_LIN_TOL); - if (anOld.IsTangentDefined() && std::abs(anOld.Curvature()) > THE_LIN_TOL) - { - ASSERT_TRUE(aNew.IsDefined) << "New normal undefined at param=" << theParam; - gp_Dir anOldNorm; - anOld.Normal(anOldNorm); - const double aDot = aNew.Direction.Dot(anOldNorm); - EXPECT_NEAR(std::abs(aDot), 1.0, THE_DIR_TOL) - << "Normal direction mismatch at param=" << theParam; - } -} - -//! Compare centre of curvature from new vs old. -void compareCentre(const occ::handle& theCurve, const double theParam) -{ - GeomProp_Curve aProp(theCurve); - const GeomProp::CentreResult aNew = aProp.CentreOfCurvature(theParam, THE_LIN_TOL); - - GeomLProp_CLProps anOld(theCurve, theParam, 2, THE_LIN_TOL); - if (anOld.IsTangentDefined() && std::abs(anOld.Curvature()) > THE_LIN_TOL) - { - ASSERT_TRUE(aNew.IsDefined) << "New centre undefined at param=" << theParam; - gp_Pnt anOldCentre; - anOld.CentreOfCurvature(anOldCentre); - EXPECT_NEAR(aNew.Centre.Distance(anOldCentre), 0.0, THE_POINT_TOL) - << "Centre mismatch at param=" << theParam; - } -} - -//! Run all comparisons at several parameter values. -void compareAll(const occ::handle& theCurve, - const double theFirst, - const double theLast, - const int theNbSamples = 10) -{ - const double aStep = (theLast - theFirst) / theNbSamples; - for (int i = 0; i <= theNbSamples; ++i) - { - const double aParam = theFirst + i * aStep; - compareTangent(theCurve, aParam); - compareCurvature(theCurve, aParam); - compareNormal(theCurve, aParam); - compareCentre(theCurve, aParam); - } -} - -//! Create a linear (degree 1) Bezier curve. -occ::handle makeLinear() -{ - NCollection_Array1 aPoles(1, 2); - aPoles(1) = gp_Pnt(0, 0, 0); - aPoles(2) = gp_Pnt(4, 0, 0); - return new Geom_BezierCurve(aPoles); -} - -//! Create a quadratic (degree 2) Bezier curve. -occ::handle makeQuadratic() -{ - NCollection_Array1 aPoles(1, 3); - aPoles(1) = gp_Pnt(0, 0, 0); - aPoles(2) = gp_Pnt(2, 4, 0); - aPoles(3) = gp_Pnt(4, 0, 0); - return new Geom_BezierCurve(aPoles); -} - -//! Create a cubic S-shaped Bezier curve. -occ::handle makeCubicS() -{ - NCollection_Array1 aPoles(1, 4); - aPoles(1) = gp_Pnt(0, 0, 0); - aPoles(2) = gp_Pnt(1, 2, 1); - aPoles(3) = gp_Pnt(3, -1, 0); - aPoles(4) = gp_Pnt(4, 1, 1); - return new Geom_BezierCurve(aPoles); -} - -//! Create a degree 5 Bezier curve. -occ::handle makeDegree5() -{ - NCollection_Array1 aPoles(1, 6); - aPoles(1) = gp_Pnt(0, 0, 0); - aPoles(2) = gp_Pnt(1, 3, 0); - aPoles(3) = gp_Pnt(2, -1, 1); - aPoles(4) = gp_Pnt(3, 2, 0); - aPoles(5) = gp_Pnt(4, -2, 1); - aPoles(6) = gp_Pnt(5, 1, 0); - return new Geom_BezierCurve(aPoles); -} -} // namespace - -// Tangent at endpoints of cubic: at t=0 aligned with P1->P2, at t=1 with P3->P4 -TEST(GeomProp_BezierCurveTest, Tangent_CubicEndpoints) -{ - occ::handle aBezier = makeCubicS(); - GeomProp_Curve aProp(aBezier); - - // At t=0, tangent should align with P1->P2 direction - const gp_Dir aDirStart(gp_Pnt(1, 2, 1).XYZ() - gp_Pnt(0, 0, 0).XYZ()); - const GeomProp::TangentResult aTan0 = aProp.Tangent(0.0, THE_LIN_TOL); - ASSERT_TRUE(aTan0.IsDefined); - EXPECT_NEAR(std::abs(aTan0.Direction.Dot(aDirStart)), 1.0, THE_DIR_TOL); - - // At t=1, tangent should align with P3->P4 direction - const gp_Dir aDirEnd(gp_Pnt(4, 1, 1).XYZ() - gp_Pnt(3, -1, 0).XYZ()); - const GeomProp::TangentResult aTan1 = aProp.Tangent(1.0, THE_LIN_TOL); - ASSERT_TRUE(aTan1.IsDefined); - EXPECT_NEAR(std::abs(aTan1.Direction.Dot(aDirEnd)), 1.0, THE_DIR_TOL); -} - -// Tangent at midpoint of quadratic -TEST(GeomProp_BezierCurveTest, Tangent_QuadraticMidpoint) -{ - occ::handle aBezier = makeQuadratic(); - GeomProp_Curve aProp(aBezier); - - const GeomProp::TangentResult aTan = aProp.Tangent(0.5, THE_LIN_TOL); - ASSERT_TRUE(aTan.IsDefined); - // For symmetric quadratic P1(0,0,0), P2(2,4,0), P3(4,0,0), - // tangent at t=0.5 should be along X-axis (horizontal) - EXPECT_NEAR(std::abs(aTan.Direction.X()), 1.0, THE_DIR_TOL); -} - -// Quadratic: curvature doesn't change sign (convex curve) -TEST(GeomProp_BezierCurveTest, Curvature_QuadraticConstantSign) -{ - occ::handle aBezier = makeQuadratic(); - GeomProp_Curve aProp(aBezier); - - const GeomProp::CurvatureResult aCurv0 = aProp.Curvature(0.0, THE_LIN_TOL); - ASSERT_TRUE(aCurv0.IsDefined); - for (double aT = 0.1; aT <= 1.0; aT += 0.1) - { - const GeomProp::CurvatureResult aCurv = aProp.Curvature(aT, THE_LIN_TOL); - ASSERT_TRUE(aCurv.IsDefined); - // Curvature is always non-negative from the API, so just verify it stays positive - EXPECT_GT(aCurv.Value, 0.0) << "Curvature became zero/negative at t=" << aT; - } -} - -// Cubic S-curve: curvature passes through zero (inflection) -TEST(GeomProp_BezierCurveTest, Curvature_CubicInflection) -{ - occ::handle aBezier = makeCubicS(); - GeomProp_Curve aProp(aBezier); - - // Sample curvature at many points and check if it gets very small near inflection - bool aFoundSmall = false; - for (double aT = 0.0; aT <= 1.0; aT += 0.01) - { - const GeomProp::CurvatureResult aCurv = aProp.Curvature(aT, THE_LIN_TOL); - ASSERT_TRUE(aCurv.IsDefined); - if (aCurv.Value < 0.1) - { - aFoundSmall = true; - } - } - EXPECT_TRUE(aFoundSmall) << "Expected to find near-zero curvature at inflection"; -} - -// Normal defined where curvature is non-zero on cubic -TEST(GeomProp_BezierCurveTest, Normal_Cubic) -{ - occ::handle aBezier = makeCubicS(); - GeomProp_Curve aProp(aBezier); - - // At endpoints, curvature is typically non-zero for an S-curve - const GeomProp::CurvatureResult aCurv = aProp.Curvature(0.0, THE_LIN_TOL); - if (aCurv.IsDefined && aCurv.Value > THE_LIN_TOL) - { - const GeomProp::NormalResult aNorm = aProp.Normal(0.0, THE_LIN_TOL); - ASSERT_TRUE(aNorm.IsDefined); - // Normal should be perpendicular to tangent - const GeomProp::TangentResult aTan = aProp.Tangent(0.0, THE_LIN_TOL); - ASSERT_TRUE(aTan.IsDefined); - EXPECT_NEAR(std::abs(aNorm.Direction.Dot(aTan.Direction)), 0.0, THE_DIR_TOL); - } -} - -// Centre of curvature at several params on cubic -TEST(GeomProp_BezierCurveTest, Centre_Cubic) -{ - occ::handle aBezier = makeCubicS(); - GeomProp_Curve aProp(aBezier); - - for (double aT = 0.0; aT <= 1.0; aT += 0.25) - { - const GeomProp::CurvatureResult aCurv = aProp.Curvature(aT, THE_LIN_TOL); - const GeomProp::CentreResult aCentre = aProp.CentreOfCurvature(aT, THE_LIN_TOL); - if (aCurv.IsDefined && aCurv.Value > THE_LIN_TOL) - { - ASSERT_TRUE(aCentre.IsDefined) << "Centre undefined at t=" << aT; - // Distance from curve point to centre = 1/curvature - gp_Pnt aPnt; - aBezier->D0(aT, aPnt); - const double aRadius = 1.0 / aCurv.Value; - EXPECT_NEAR(aCentre.Centre.Distance(aPnt), aRadius, THE_POINT_TOL) - << "Radius mismatch at t=" << aT; - } - } -} - -// Cubic S-curve curvature extrema -TEST(GeomProp_BezierCurveTest, FindCurvatureExtrema_Cubic) -{ - occ::handle aBezier = makeCubicS(); - GeomProp_Curve aProp(aBezier); - - const GeomProp::CurveAnalysis aResult = aProp.FindCurvatureExtrema(); - ASSERT_TRUE(aResult.IsDone); - // A cubic S-curve should have at least one curvature extremum - EXPECT_GE(aResult.Points.Length(), 1); -} - -// S-shaped cubic has at least one inflection -TEST(GeomProp_BezierCurveTest, FindInflections_CubicS) -{ - occ::handle aBezier = makeCubicS(); - GeomProp_Curve aProp(aBezier); - - const GeomProp::CurveAnalysis aResult = aProp.FindInflections(); - ASSERT_TRUE(aResult.IsDone); - EXPECT_GE(aResult.Points.Length(), 1); -} - -// Quadratic has no inflections -TEST(GeomProp_BezierCurveTest, FindInflections_QuadraticNone) -{ - occ::handle aBezier = makeQuadratic(); - GeomProp_Curve aProp(aBezier); - - const GeomProp::CurveAnalysis aResult = aProp.FindInflections(); - ASSERT_TRUE(aResult.IsDone); - EXPECT_EQ(aResult.Points.Length(), 0); -} - -// Quadratic curvature extrema -TEST(GeomProp_BezierCurveTest, FindCurvatureExtrema_Quadratic) -{ - occ::handle aBezier = makeQuadratic(); - GeomProp_Curve aProp(aBezier); - - const GeomProp::CurveAnalysis aResult = aProp.FindCurvatureExtrema(); - ASSERT_TRUE(aResult.IsDone); - // Quadratic Bezier should have at least one extremum - EXPECT_GE(aResult.Points.Length(), 1); -} - -// GetType returns GeomAbs_BezierCurve -TEST(GeomProp_BezierCurveTest, GetType_IsBezier) -{ - occ::handle aBezier = makeQuadratic(); - GeomProp_Curve aProp(aBezier); - EXPECT_EQ(aProp.GetType(), GeomAbs_BezierCurve); -} - -// Cross-validate cubic S vs CLProps -TEST(GeomProp_BezierCurveTest, VsCLProps_CubicS) -{ - occ::handle aBezier = makeCubicS(); - compareAll(aBezier, 0.0, 1.0); -} - -// Cross-validate quadratic vs CLProps -TEST(GeomProp_BezierCurveTest, VsCLProps_Quadratic) -{ - occ::handle aBezier = makeQuadratic(); - compareAll(aBezier, 0.0, 1.0); -} - -// Cross-validate degree 5 vs CLProps -TEST(GeomProp_BezierCurveTest, VsCLProps_HighDegree) -{ - occ::handle aBezier = makeDegree5(); - compareAll(aBezier, 0.0, 1.0); -} - -// Dense cross-validation for cubic -TEST(GeomProp_BezierCurveTest, VsCLProps_AllProperties_Cubic) -{ - occ::handle aBezier = makeCubicS(); - compareAll(aBezier, 0.0, 1.0, 20); -} - -// Dense cross-validation for degree 5 -TEST(GeomProp_BezierCurveTest, VsCLProps_AllProperties_Degree5) -{ - occ::handle aBezier = makeDegree5(); - compareAll(aBezier, 0.0, 1.0, 20); -} - -// Linear Bezier (degree 1) has zero curvature everywhere -TEST(GeomProp_BezierCurveTest, Curvature_LinearBezier) -{ - occ::handle aBezier = makeLinear(); - GeomProp_Curve aProp(aBezier); - - for (double aT = 0.0; aT <= 1.0; aT += 0.1) - { - const GeomProp::CurvatureResult aCurv = aProp.Curvature(aT, THE_LIN_TOL); - ASSERT_TRUE(aCurv.IsDefined); - EXPECT_NEAR(aCurv.Value, 0.0, THE_CURV_TOL) << "Non-zero curvature on line at t=" << aT; - } -} - -// Linear Bezier (degree 1) has constant tangent direction -TEST(GeomProp_BezierCurveTest, Tangent_LinearBezier) -{ - occ::handle aBezier = makeLinear(); - GeomProp_Curve aProp(aBezier); - - const GeomProp::TangentResult aTanRef = aProp.Tangent(0.0, THE_LIN_TOL); - ASSERT_TRUE(aTanRef.IsDefined); - - for (double aT = 0.1; aT <= 1.0; aT += 0.1) - { - const GeomProp::TangentResult aTan = aProp.Tangent(aT, THE_LIN_TOL); - ASSERT_TRUE(aTan.IsDefined); - EXPECT_NEAR(std::abs(aTan.Direction.Dot(aTanRef.Direction)), 1.0, THE_DIR_TOL) - << "Tangent changed direction at t=" << aT; - } -} - -// Degree 5 S-curve inflections -TEST(GeomProp_BezierCurveTest, FindInflections_HighDegree) -{ - occ::handle aBezier = makeDegree5(); - GeomProp_Curve aProp(aBezier); - - const GeomProp::CurveAnalysis aResult = aProp.FindInflections(); - ASSERT_TRUE(aResult.IsDone); - // 3D curve inflections depend on the cross product of D1 and D2; - // verify the analysis completes without requiring a specific count - EXPECT_GE(aResult.Points.Length(), 0); -} - -// Degree 5 curvature extrema -TEST(GeomProp_BezierCurveTest, FindCurvatureExtrema_HighDegree) -{ - occ::handle aBezier = makeDegree5(); - GeomProp_Curve aProp(aBezier); - - const GeomProp::CurveAnalysis aResult = aProp.FindCurvatureExtrema(); - ASSERT_TRUE(aResult.IsDone); - // High-degree curve with varied control points should have multiple extrema - EXPECT_GE(aResult.Points.Length(), 1); -} - -// 3D Bezier with z-variation: curvature comparison -TEST(GeomProp_BezierCurveTest, Curvature_PlanarVs3D) -{ - // Planar quadratic - occ::handle aPlanar = makeQuadratic(); - - // 3D quadratic with z-variation - NCollection_Array1 aPoles3D(1, 3); - aPoles3D(1) = gp_Pnt(0, 0, 0); - aPoles3D(2) = gp_Pnt(2, 4, 3); - aPoles3D(3) = gp_Pnt(4, 0, 0); - occ::handle a3D = new Geom_BezierCurve(aPoles3D); - - GeomProp_Curve aPropPlanar(aPlanar); - GeomProp_Curve aProp3D(a3D); - - // Both should have well-defined curvature at midpoint - const GeomProp::CurvatureResult aCurvPlanar = aPropPlanar.Curvature(0.5, THE_LIN_TOL); - const GeomProp::CurvatureResult aCurv3D = aProp3D.Curvature(0.5, THE_LIN_TOL); - ASSERT_TRUE(aCurvPlanar.IsDefined); - ASSERT_TRUE(aCurv3D.IsDefined); - // The 3D curve has additional z-component, so curvature should differ - // but both should be positive - EXPECT_GT(aCurvPlanar.Value, 0.0); - EXPECT_GT(aCurv3D.Value, 0.0); -} - -TEST(GeomProp_BezierCurveTest, VsCLProps_CriticalPoints) -{ - NCollection_Array1 aPoles(1, 4); - aPoles(1) = gp_Pnt(0, 0, 0); - aPoles(2) = gp_Pnt(1, 2, 0); - aPoles(3) = gp_Pnt(3, -1, 0); - aPoles(4) = gp_Pnt(4, 0, 0); - occ::handle aBezier = new Geom_BezierCurve(aPoles); - const double aParams[] = - {0.0, 1.0e-10, 1.0e-6, 0.01, 0.25, 0.5, 0.75, 0.99, 1.0 - 1.0e-6, 1.0 - 1.0e-10, 1.0}; - for (const double aParam : aParams) - { - compareTangent(aBezier, aParam); - compareCurvature(aBezier, aParam); - compareNormal(aBezier, aParam); - compareCentre(aBezier, aParam); - } -} diff --git a/src/ModelingData/TKG3d/GTests/GeomProp_BezierSurface_Test.cxx b/src/ModelingData/TKG3d/GTests/GeomProp_BezierSurface_Test.cxx deleted file mode 100644 index b6d7d68097..0000000000 --- a/src/ModelingData/TKG3d/GTests/GeomProp_BezierSurface_Test.cxx +++ /dev/null @@ -1,459 +0,0 @@ -// 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. - -// Tests for GeomProp_Surface with Geom_BezierSurface. -// Validates normal, curvatures, mean/Gaussian curvature for flat and curved -// bicubic Bezier patches. Cross-validates against GeomLProp_SLProps. - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -namespace -{ -constexpr double THE_LIN_TOL = Precision::PConfusion(); -constexpr double THE_CURV_TOL = 1.0e-6; -constexpr double THE_DIR_TOL = 1.0e-4; - -//! Compare surface normal from new GeomProp_Surface vs old GeomLProp_SLProps. -void compareNormal(const occ::handle& theSurf, const double theU, const double theV) -{ - GeomProp_Surface aProp(theSurf); - const GeomProp::SurfaceNormalResult aNew = aProp.Normal(theU, theV, THE_LIN_TOL); - - GeomLProp_SLProps anOld(theSurf, theU, theV, 2, THE_LIN_TOL); - if (anOld.IsNormalDefined()) - { - ASSERT_TRUE(aNew.IsDefined) << "New normal undefined at (" << theU << "," << theV << ")"; - const double aDot = aNew.Direction.Dot(anOld.Normal()); - EXPECT_NEAR(std::abs(aDot), 1.0, THE_DIR_TOL) - << "Normal mismatch at (" << theU << "," << theV << ")"; - } -} - -//! Compare curvatures from new GeomProp_Surface vs old GeomLProp_SLProps. -void compareCurvatures(const occ::handle& theSurf, - const double theU, - const double theV) -{ - GeomProp_Surface aProp(theSurf); - const GeomProp::SurfaceCurvatureResult aNew = aProp.Curvatures(theU, theV, THE_LIN_TOL); - - GeomLProp_SLProps anOld(theSurf, theU, theV, 2, THE_LIN_TOL); - if (anOld.IsCurvatureDefined()) - { - ASSERT_TRUE(aNew.IsDefined) << "New curvatures undefined at (" << theU << "," << theV << ")"; - EXPECT_NEAR(aNew.MinCurvature, anOld.MinCurvature(), THE_CURV_TOL) - << "MinCurvature mismatch at (" << theU << "," << theV << ")"; - EXPECT_NEAR(aNew.MaxCurvature, anOld.MaxCurvature(), THE_CURV_TOL) - << "MaxCurvature mismatch at (" << theU << "," << theV << ")"; - } -} - -//! Compare mean and Gaussian curvatures. -void compareMeanGaussian(const occ::handle& theSurf, - const double theU, - const double theV) -{ - GeomProp_Surface aProp(theSurf); - const GeomProp::MeanGaussianResult aNew = aProp.MeanGaussian(theU, theV, THE_LIN_TOL); - - GeomLProp_SLProps anOld(theSurf, theU, theV, 2, THE_LIN_TOL); - if (anOld.IsCurvatureDefined()) - { - ASSERT_TRUE(aNew.IsDefined) << "New MeanGaussian undefined at (" << theU << "," << theV << ")"; - EXPECT_NEAR(aNew.MeanCurvature, anOld.MeanCurvature(), THE_CURV_TOL) - << "Mean curvature mismatch at (" << theU << "," << theV << ")"; - EXPECT_NEAR(aNew.GaussianCurvature, anOld.GaussianCurvature(), THE_CURV_TOL) - << "Gaussian curvature mismatch at (" << theU << "," << theV << ")"; - } -} - -//! Run all surface comparisons at a grid of parameter values. -void compareAllSurface(const occ::handle& theSurf, - const double theUMin, - const double theUMax, - const double theVMin, - const double theVMax, - const int theNbU = 5, - const int theNbV = 5) -{ - const double aUStep = (theUMax - theUMin) / theNbU; - const double aVStep = (theVMax - theVMin) / theNbV; - for (int i = 0; i <= theNbU; ++i) - { - for (int j = 0; j <= theNbV; ++j) - { - const double aU = theUMin + i * aUStep; - const double aV = theVMin + j * aVStep; - compareNormal(theSurf, aU, aV); - compareCurvatures(theSurf, aU, aV); - compareMeanGaussian(theSurf, aU, aV); - } - } -} - -//! Create a flat (planar) 4x4 Bezier patch on the XY plane. -occ::handle makeFlatPatch() -{ - NCollection_Array2 aPoles(1, 4, 1, 4); - for (int i = 1; i <= 4; ++i) - { - for (int j = 1; j <= 4; ++j) - { - aPoles.SetValue(i, j, gp_Pnt((i - 1) * 1.0, (j - 1) * 1.0, 0.0)); - } - } - return new Geom_BezierSurface(aPoles); -} - -//! Create a curved 4x4 Bezier patch with z = sin(x)*cos(y) variation. -occ::handle makeCurvedPatch() -{ - NCollection_Array2 aPoles(1, 4, 1, 4); - for (int i = 1; i <= 4; ++i) - { - for (int j = 1; j <= 4; ++j) - { - const double aX = (i - 1) * 1.0; - const double aY = (j - 1) * 1.0; - const double aZ = std::sin(aX) * std::cos(aY); - aPoles.SetValue(i, j, gp_Pnt(aX, aY, aZ)); - } - } - return new Geom_BezierSurface(aPoles); -} -} // namespace - -// Normal at center of curved Bezier patch -TEST(GeomProp_BezierSurfaceTest, Normal_AtCenter) -{ - occ::handle aSurf = makeCurvedPatch(); - GeomProp_Surface aProp(aSurf); - - const GeomProp::SurfaceNormalResult aResult = aProp.Normal(0.5, 0.5, THE_LIN_TOL); - ASSERT_TRUE(aResult.IsDefined); - // Normal should have a non-trivial Z component for a curved surface - EXPECT_GT(std::abs(aResult.Direction.Z()), 0.1); -} - -// Normal at all four corners -TEST(GeomProp_BezierSurfaceTest, Normal_AtCorners) -{ - occ::handle aSurf = makeCurvedPatch(); - GeomProp_Surface aProp(aSurf); - - const double aCorners[][2] = {{0.0, 0.0}, {1.0, 0.0}, {0.0, 1.0}, {1.0, 1.0}}; - for (const auto& aUV : aCorners) - { - const GeomProp::SurfaceNormalResult aResult = aProp.Normal(aUV[0], aUV[1], THE_LIN_TOL); - ASSERT_TRUE(aResult.IsDefined) << "Normal undefined at (" << aUV[0] << "," << aUV[1] << ")"; - } -} - -// Normal at 4x4 grid -TEST(GeomProp_BezierSurfaceTest, Normal_Grid) -{ - occ::handle aSurf = makeCurvedPatch(); - GeomProp_Surface aProp(aSurf); - - for (int i = 0; i <= 3; ++i) - { - for (int j = 0; j <= 3; ++j) - { - const double aU = i / 3.0; - const double aV = j / 3.0; - const GeomProp::SurfaceNormalResult aResult = aProp.Normal(aU, aV, THE_LIN_TOL); - ASSERT_TRUE(aResult.IsDefined) << "Normal undefined at (" << aU << "," << aV << ")"; - } - } -} - -// Curvatures at center of curved patch -TEST(GeomProp_BezierSurfaceTest, Curvatures_AtCenter) -{ - occ::handle aSurf = makeCurvedPatch(); - GeomProp_Surface aProp(aSurf); - - const GeomProp::SurfaceCurvatureResult aResult = aProp.Curvatures(0.5, 0.5, THE_LIN_TOL); - ASSERT_TRUE(aResult.IsDefined); - // MinCurvature <= MaxCurvature - EXPECT_LE(aResult.MinCurvature, aResult.MaxCurvature); -} - -// Curvatures at corners -TEST(GeomProp_BezierSurfaceTest, Curvatures_AtCorners) -{ - occ::handle aSurf = makeCurvedPatch(); - GeomProp_Surface aProp(aSurf); - - const double aCorners[][2] = {{0.0, 0.0}, {1.0, 0.0}, {0.0, 1.0}, {1.0, 1.0}}; - for (const auto& aUV : aCorners) - { - const GeomProp::SurfaceCurvatureResult aResult = aProp.Curvatures(aUV[0], aUV[1], THE_LIN_TOL); - ASSERT_TRUE(aResult.IsDefined) << "Curvatures undefined at (" << aUV[0] << "," << aUV[1] << ")"; - EXPECT_LE(aResult.MinCurvature, aResult.MaxCurvature); - } -} - -// Mean and Gaussian curvature at center -TEST(GeomProp_BezierSurfaceTest, MeanGaussian_AtCenter) -{ - occ::handle aSurf = makeCurvedPatch(); - GeomProp_Surface aProp(aSurf); - - const GeomProp::MeanGaussianResult aResult = aProp.MeanGaussian(0.5, 0.5, THE_LIN_TOL); - ASSERT_TRUE(aResult.IsDefined); - // For a saddle-like surface, Gaussian curvature is typically negative - // Just verify the relationship: H = (k1+k2)/2 is well-defined - const GeomProp::SurfaceCurvatureResult aCurv = aProp.Curvatures(0.5, 0.5, THE_LIN_TOL); - if (aCurv.IsDefined) - { - const double aExpectedH = (aCurv.MinCurvature + aCurv.MaxCurvature) / 2.0; - EXPECT_NEAR(aResult.MeanCurvature, aExpectedH, THE_CURV_TOL); - } -} - -// Mean and Gaussian curvature at corners -TEST(GeomProp_BezierSurfaceTest, MeanGaussian_AtCorners) -{ - occ::handle aSurf = makeCurvedPatch(); - GeomProp_Surface aProp(aSurf); - - const double aCorners[][2] = {{0.0, 0.0}, {1.0, 0.0}, {0.0, 1.0}, {1.0, 1.0}}; - for (const auto& aUV : aCorners) - { - const GeomProp::MeanGaussianResult aResult = aProp.MeanGaussian(aUV[0], aUV[1], THE_LIN_TOL); - ASSERT_TRUE(aResult.IsDefined) - << "MeanGaussian undefined at (" << aUV[0] << "," << aUV[1] << ")"; - } -} - -// GetType returns GeomAbs_BezierSurface -TEST(GeomProp_BezierSurfaceTest, GetType_IsBezierSurface) -{ - occ::handle aSurf = makeCurvedPatch(); - GeomProp_Surface aProp(aSurf); - EXPECT_EQ(aProp.GetType(), GeomAbs_BezierSurface); -} - -// Flat patch: curvatures are all zero -TEST(GeomProp_BezierSurfaceTest, Curvatures_FlatPatch) -{ - occ::handle aSurf = makeFlatPatch(); - GeomProp_Surface aProp(aSurf); - - for (double aU = 0.0; aU <= 1.0; aU += 0.25) - { - for (double aV = 0.0; aV <= 1.0; aV += 0.25) - { - const GeomProp::SurfaceCurvatureResult aResult = aProp.Curvatures(aU, aV, THE_LIN_TOL); - ASSERT_TRUE(aResult.IsDefined) << "Curvatures undefined at (" << aU << "," << aV << ")"; - EXPECT_NEAR(aResult.MinCurvature, 0.0, THE_CURV_TOL) - << "MinCurvature non-zero at (" << aU << "," << aV << ")"; - EXPECT_NEAR(aResult.MaxCurvature, 0.0, THE_CURV_TOL) - << "MaxCurvature non-zero at (" << aU << "," << aV << ")"; - } - } -} - -// Flat patch: H=K=0 -TEST(GeomProp_BezierSurfaceTest, MeanGaussian_FlatPatch) -{ - occ::handle aSurf = makeFlatPatch(); - GeomProp_Surface aProp(aSurf); - - for (double aU = 0.0; aU <= 1.0; aU += 0.25) - { - for (double aV = 0.0; aV <= 1.0; aV += 0.25) - { - const GeomProp::MeanGaussianResult aResult = aProp.MeanGaussian(aU, aV, THE_LIN_TOL); - ASSERT_TRUE(aResult.IsDefined) << "MeanGaussian undefined at (" << aU << "," << aV << ")"; - EXPECT_NEAR(aResult.MeanCurvature, 0.0, THE_CURV_TOL) - << "Mean curvature non-zero at (" << aU << "," << aV << ")"; - EXPECT_NEAR(aResult.GaussianCurvature, 0.0, THE_CURV_TOL) - << "Gaussian curvature non-zero at (" << aU << "," << aV << ")"; - } - } -} - -// Flat patch: constant normal pointing in Z direction -TEST(GeomProp_BezierSurfaceTest, Normal_FlatPatch) -{ - occ::handle aSurf = makeFlatPatch(); - GeomProp_Surface aProp(aSurf); - - const gp_Dir aExpectedNormal(0.0, 0.0, 1.0); - for (double aU = 0.0; aU <= 1.0; aU += 0.25) - { - for (double aV = 0.0; aV <= 1.0; aV += 0.25) - { - const GeomProp::SurfaceNormalResult aResult = aProp.Normal(aU, aV, THE_LIN_TOL); - ASSERT_TRUE(aResult.IsDefined) << "Normal undefined at (" << aU << "," << aV << ")"; - const double aDot = aResult.Direction.Dot(aExpectedNormal); - EXPECT_NEAR(std::abs(aDot), 1.0, THE_DIR_TOL) - << "Normal not along Z at (" << aU << "," << aV << ")"; - } - } -} - -// Cross-validate normal against SLProps on grid -TEST(GeomProp_BezierSurfaceTest, VsSLProps_Normal) -{ - occ::handle aSurf = makeCurvedPatch(); - for (int i = 0; i <= 4; ++i) - { - for (int j = 0; j <= 4; ++j) - { - compareNormal(aSurf, i / 4.0, j / 4.0); - } - } -} - -// Cross-validate curvatures against SLProps on grid -TEST(GeomProp_BezierSurfaceTest, VsSLProps_Curvatures) -{ - occ::handle aSurf = makeCurvedPatch(); - for (int i = 0; i <= 4; ++i) - { - for (int j = 0; j <= 4; ++j) - { - compareCurvatures(aSurf, i / 4.0, j / 4.0); - } - } -} - -// Cross-validate mean/Gaussian against SLProps on grid -TEST(GeomProp_BezierSurfaceTest, VsSLProps_MeanGaussian) -{ - occ::handle aSurf = makeCurvedPatch(); - for (int i = 0; i <= 4; ++i) - { - for (int j = 0; j <= 4; ++j) - { - compareMeanGaussian(aSurf, i / 4.0, j / 4.0); - } - } -} - -// Dense cross-validation of all properties -TEST(GeomProp_BezierSurfaceTest, VsSLProps_AllProperties) -{ - occ::handle aSurf = makeCurvedPatch(); - compareAllSurface(aSurf, 0.0, 1.0, 0.0, 1.0, 6, 6); -} - -// Cross-validate flat patch -TEST(GeomProp_BezierSurfaceTest, VsSLProps_FlatPatch) -{ - occ::handle aSurf = makeFlatPatch(); - compareAllSurface(aSurf, 0.0, 1.0, 0.0, 1.0); -} - -// Curved patch has non-zero curvatures -TEST(GeomProp_BezierSurfaceTest, Curvatures_CurvedPatch) -{ - occ::handle aSurf = makeCurvedPatch(); - GeomProp_Surface aProp(aSurf); - - const GeomProp::SurfaceCurvatureResult aResult = aProp.Curvatures(0.5, 0.5, THE_LIN_TOL); - ASSERT_TRUE(aResult.IsDefined); - // At least one principal curvature should be non-zero for a curved patch - const double aMaxAbsK = std::max(std::abs(aResult.MinCurvature), std::abs(aResult.MaxCurvature)); - EXPECT_GT(aMaxAbsK, THE_CURV_TOL) << "Curved patch has zero curvatures at center"; -} - -// Curved patch: non-trivial mean and Gaussian curvatures -TEST(GeomProp_BezierSurfaceTest, MeanGaussian_CurvedPatch) -{ - occ::handle aSurf = makeCurvedPatch(); - GeomProp_Surface aProp(aSurf); - - const GeomProp::MeanGaussianResult aResult = aProp.MeanGaussian(0.5, 0.5, THE_LIN_TOL); - ASSERT_TRUE(aResult.IsDefined); - // For sin(x)*cos(y) surface, both H and K should be non-trivial near center - const double aAbsH = std::abs(aResult.MeanCurvature); - const double aAbsK = std::abs(aResult.GaussianCurvature); - EXPECT_GT(aAbsH + aAbsK, THE_CURV_TOL) - << "Both mean and Gaussian curvature are zero on curved patch"; -} - -// Normal varies smoothly across the patch -TEST(GeomProp_BezierSurfaceTest, Normal_SmoothVariation) -{ - occ::handle aSurf = makeCurvedPatch(); - GeomProp_Surface aProp(aSurf); - - constexpr int aNbSteps = 20; - constexpr double aStep = 1.0 / aNbSteps; - gp_Dir aPrevNormal; - bool aHasPrev = false; - - for (int i = 0; i <= aNbSteps; ++i) - { - const double aU = i * aStep; - const GeomProp::SurfaceNormalResult aResult = aProp.Normal(aU, 0.5, THE_LIN_TOL); - ASSERT_TRUE(aResult.IsDefined) << "Normal undefined at u=" << aU; - - if (aHasPrev) - { - // Consecutive normals should not change abruptly - const double aDot = aResult.Direction.Dot(aPrevNormal); - EXPECT_GT(aDot, 0.9) << "Normal changed abruptly at u=" << aU; - } - aPrevNormal = aResult.Direction; - aHasPrev = true; - } -} - -// Dense 8x8 grid cross-validation -TEST(GeomProp_BezierSurfaceTest, VsSLProps_DenseGrid) -{ - occ::handle aSurf = makeCurvedPatch(); - compareAllSurface(aSurf, 0.0, 1.0, 0.0, 1.0, 8, 8); -} - -TEST(GeomProp_BezierSurfaceTest, VsSLProps_CriticalPoints) -{ - occ::handle aSurf = makeCurvedPatch(); - // Critical: corners, edge midpoints, center, near-corners - const double aParams[][2] = {{0.0, 0.0}, - {1.0, 0.0}, - {0.0, 1.0}, - {1.0, 1.0}, - {0.5, 0.0}, - {0.5, 1.0}, - {0.0, 0.5}, - {1.0, 0.5}, - {0.5, 0.5}, - {1.0e-10, 1.0e-10}, - {1.0 - 1.0e-10, 1.0 - 1.0e-10}, - {1.0e-6, 0.5}, - {0.5, 1.0e-6}}; - for (const auto& aUV : aParams) - { - compareNormal(aSurf, aUV[0], aUV[1]); - compareCurvatures(aSurf, aUV[0], aUV[1]); - compareMeanGaussian(aSurf, aUV[0], aUV[1]); - } -} diff --git a/src/ModelingData/TKG3d/GTests/GeomProp_Circle_Test.cxx b/src/ModelingData/TKG3d/GTests/GeomProp_Circle_Test.cxx deleted file mode 100644 index b83f5ae814..0000000000 --- a/src/ModelingData/TKG3d/GTests/GeomProp_Circle_Test.cxx +++ /dev/null @@ -1,440 +0,0 @@ -// 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. - -// Unit tests for GeomProp_Curve with Circle geometry. - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -namespace -{ -constexpr double THE_LIN_TOL = Precision::PConfusion(); -constexpr double THE_CURV_TOL = 1.0e-8; -constexpr double THE_DIR_TOL = 1.0e-6; -constexpr double THE_POINT_TOL = 1.0e-6; - -//! Compare tangent from new GeomProp_Curve vs old GeomLProp_CLProps. -void compareTangent(const occ::handle& theCurve, const double theParam) -{ - GeomProp_Curve aProp(theCurve); - const GeomProp::TangentResult aNew = aProp.Tangent(theParam, THE_LIN_TOL); - - GeomLProp_CLProps anOld(theCurve, theParam, 2, THE_LIN_TOL); - if (anOld.IsTangentDefined()) - { - ASSERT_TRUE(aNew.IsDefined) << "New tangent undefined but old is defined at param=" << theParam; - gp_Dir anOldDir; - anOld.Tangent(anOldDir); - const double aDot = aNew.Direction.Dot(anOldDir); - EXPECT_NEAR(std::abs(aDot), 1.0, THE_DIR_TOL) - << "Tangent direction mismatch at param=" << theParam; - } -} - -//! Compare curvature from new GeomProp_Curve vs old GeomLProp_CLProps. -void compareCurvature(const occ::handle& theCurve, const double theParam) -{ - GeomProp_Curve aProp(theCurve); - const GeomProp::CurvatureResult aNew = aProp.Curvature(theParam, THE_LIN_TOL); - - GeomLProp_CLProps anOld(theCurve, theParam, 2, THE_LIN_TOL); - if (anOld.IsTangentDefined()) - { - ASSERT_TRUE(aNew.IsDefined) << "New curvature undefined at param=" << theParam; - EXPECT_NEAR(aNew.Value, anOld.Curvature(), THE_CURV_TOL) - << "Curvature mismatch at param=" << theParam; - } -} - -//! Compare normal from new GeomProp_Curve vs old GeomLProp_CLProps. -void compareNormal(const occ::handle& theCurve, const double theParam) -{ - GeomProp_Curve aProp(theCurve); - const GeomProp::NormalResult aNew = aProp.Normal(theParam, THE_LIN_TOL); - - GeomLProp_CLProps anOld(theCurve, theParam, 2, THE_LIN_TOL); - if (anOld.IsTangentDefined() && std::abs(anOld.Curvature()) > THE_LIN_TOL) - { - ASSERT_TRUE(aNew.IsDefined) << "New normal undefined at param=" << theParam; - gp_Dir anOldNorm; - anOld.Normal(anOldNorm); - const double aDot = aNew.Direction.Dot(anOldNorm); - EXPECT_NEAR(std::abs(aDot), 1.0, THE_DIR_TOL) - << "Normal direction mismatch at param=" << theParam; - } -} - -//! Compare centre of curvature from new vs old. -void compareCentre(const occ::handle& theCurve, const double theParam) -{ - GeomProp_Curve aProp(theCurve); - const GeomProp::CentreResult aNew = aProp.CentreOfCurvature(theParam, THE_LIN_TOL); - - GeomLProp_CLProps anOld(theCurve, theParam, 2, THE_LIN_TOL); - if (anOld.IsTangentDefined() && std::abs(anOld.Curvature()) > THE_LIN_TOL) - { - ASSERT_TRUE(aNew.IsDefined) << "New centre undefined at param=" << theParam; - gp_Pnt anOldCentre; - anOld.CentreOfCurvature(anOldCentre); - EXPECT_NEAR(aNew.Centre.Distance(anOldCentre), 0.0, THE_POINT_TOL) - << "Centre mismatch at param=" << theParam; - } -} - -//! Run all comparisons at several parameter values. -void compareAll(const occ::handle& theCurve, - const double theFirst, - const double theLast, - const int theNbSamples = 10) -{ - const double aStep = (theLast - theFirst) / theNbSamples; - for (int i = 0; i <= theNbSamples; ++i) - { - const double aParam = theFirst + i * aStep; - compareTangent(theCurve, aParam); - compareCurvature(theCurve, aParam); - compareNormal(theCurve, aParam); - compareCentre(theCurve, aParam); - } -} -} // namespace - -// ============================================================================ -// Analytical reference tests -// ============================================================================ - -TEST(GeomProp_CircleTest, Curvature_IsConstant) -{ - const double aRadius = 5.0; - gp_Circ aCirc(gp_Ax2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), aRadius); - occ::handle aCircle = new Geom_Circle(aCirc); - GeomProp_Curve aProp(aCircle); - - const GeomProp::CurvatureResult aCurv = aProp.Curvature(0.0, THE_LIN_TOL); - ASSERT_TRUE(aCurv.IsDefined); - EXPECT_FALSE(aCurv.IsInfinite); - EXPECT_NEAR(aCurv.Value, 1.0 / aRadius, THE_CURV_TOL); -} - -TEST(GeomProp_CircleTest, Curvature_AllParams) -{ - const double aRadius = 7.0; - gp_Circ aCirc(gp_Ax2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), aRadius); - occ::handle aCircle = new Geom_Circle(aCirc); - GeomProp_Curve aProp(aCircle); - - const double aExpected = 1.0 / aRadius; - for (int i = 0; i < 12; ++i) - { - const double aParam = i * M_PI / 6.0; - const GeomProp::CurvatureResult aCurv = aProp.Curvature(aParam, THE_LIN_TOL); - ASSERT_TRUE(aCurv.IsDefined) << "Curvature undefined at param=" << aParam; - EXPECT_NEAR(aCurv.Value, aExpected, THE_CURV_TOL) - << "Curvature not constant at param=" << aParam; - } -} - -TEST(GeomProp_CircleTest, Curvature_SmallRadius) -{ - const double aRadius = 0.01; - gp_Circ aCirc(gp_Ax2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), aRadius); - occ::handle aCircle = new Geom_Circle(aCirc); - GeomProp_Curve aProp(aCircle); - - const GeomProp::CurvatureResult aCurv = aProp.Curvature(0.0, THE_LIN_TOL); - ASSERT_TRUE(aCurv.IsDefined); - EXPECT_NEAR(aCurv.Value, 100.0, THE_CURV_TOL); -} - -TEST(GeomProp_CircleTest, Curvature_LargeRadius) -{ - const double aRadius = 1000.0; - gp_Circ aCirc(gp_Ax2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), aRadius); - occ::handle aCircle = new Geom_Circle(aCirc); - GeomProp_Curve aProp(aCircle); - - const GeomProp::CurvatureResult aCurv = aProp.Curvature(0.0, THE_LIN_TOL); - ASSERT_TRUE(aCurv.IsDefined); - EXPECT_NEAR(aCurv.Value, 0.001, THE_CURV_TOL); -} - -TEST(GeomProp_CircleTest, Tangent_AtZero) -{ - gp_Circ aCirc(gp_Ax2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), 5.0); - occ::handle aCircle = new Geom_Circle(aCirc); - GeomProp_Curve aProp(aCircle); - - // At param=0, point is (R,0,0), tangent should be (0,1,0). - const GeomProp::TangentResult aTan = aProp.Tangent(0.0, THE_LIN_TOL); - ASSERT_TRUE(aTan.IsDefined); - EXPECT_NEAR(aTan.Direction.X(), 0.0, THE_DIR_TOL); - EXPECT_NEAR(aTan.Direction.Y(), 1.0, THE_DIR_TOL); - EXPECT_NEAR(aTan.Direction.Z(), 0.0, THE_DIR_TOL); -} - -TEST(GeomProp_CircleTest, Tangent_AtPiOver2) -{ - gp_Circ aCirc(gp_Ax2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), 5.0); - occ::handle aCircle = new Geom_Circle(aCirc); - GeomProp_Curve aProp(aCircle); - - // At param=PI/2, point is (0,R,0), tangent should be (-1,0,0). - const GeomProp::TangentResult aTan = aProp.Tangent(M_PI / 2.0, THE_LIN_TOL); - ASSERT_TRUE(aTan.IsDefined); - EXPECT_NEAR(aTan.Direction.X(), -1.0, THE_DIR_TOL); - EXPECT_NEAR(aTan.Direction.Y(), 0.0, THE_DIR_TOL); - EXPECT_NEAR(aTan.Direction.Z(), 0.0, THE_DIR_TOL); -} - -TEST(GeomProp_CircleTest, Tangent_AtPi) -{ - gp_Circ aCirc(gp_Ax2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), 5.0); - occ::handle aCircle = new Geom_Circle(aCirc); - GeomProp_Curve aProp(aCircle); - - // At param=PI, point is (-R,0,0), tangent should be (0,-1,0). - const GeomProp::TangentResult aTan = aProp.Tangent(M_PI, THE_LIN_TOL); - ASSERT_TRUE(aTan.IsDefined); - EXPECT_NEAR(aTan.Direction.X(), 0.0, THE_DIR_TOL); - EXPECT_NEAR(aTan.Direction.Y(), -1.0, THE_DIR_TOL); - EXPECT_NEAR(aTan.Direction.Z(), 0.0, THE_DIR_TOL); -} - -TEST(GeomProp_CircleTest, RepeatedCalls_SameParameter_AreStable) -{ - gp_Circ aCirc(gp_Ax2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), 5.0); - occ::handle aCircle = new Geom_Circle(aCirc); - GeomProp_Curve aProp(aCircle); - GeomProp_Curve aFreshProp(aCircle); - const double aParam = M_PI / 3.0; - - const GeomProp::TangentResult aTangent = aProp.Tangent(aParam, THE_LIN_TOL); - const GeomProp::CurvatureResult aCurv = aProp.Curvature(aParam, THE_LIN_TOL); - const GeomProp::NormalResult aNorm = aProp.Normal(aParam, THE_LIN_TOL); - const GeomProp::CentreResult aCentre = aProp.CentreOfCurvature(aParam, THE_LIN_TOL); - - const GeomProp::CurvatureResult aFreshCurv = aFreshProp.Curvature(aParam, THE_LIN_TOL); - const GeomProp::NormalResult aFreshNorm = aFreshProp.Normal(aParam, THE_LIN_TOL); - const GeomProp::CentreResult aFreshCentre = aFreshProp.CentreOfCurvature(aParam, THE_LIN_TOL); - - ASSERT_TRUE(aTangent.IsDefined); - ASSERT_TRUE(aCurv.IsDefined); - ASSERT_TRUE(aNorm.IsDefined); - ASSERT_TRUE(aCentre.IsDefined); - ASSERT_TRUE(aFreshCurv.IsDefined); - ASSERT_TRUE(aFreshNorm.IsDefined); - ASSERT_TRUE(aFreshCentre.IsDefined); - - EXPECT_NEAR(aCurv.Value, aFreshCurv.Value, THE_CURV_TOL); - EXPECT_NEAR(std::abs(aNorm.Direction.Dot(aFreshNorm.Direction)), 1.0, THE_DIR_TOL); - EXPECT_NEAR(aCentre.Centre.Distance(aFreshCentre.Centre), 0.0, THE_POINT_TOL); -} - -TEST(GeomProp_CircleTest, Normal_PointsToCenter) -{ - gp_Circ aCirc(gp_Ax2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), 5.0); - occ::handle aCircle = new Geom_Circle(aCirc); - GeomProp_Curve aProp(aCircle); - - // At param=0, point is (5,0,0), normal toward center = (-1,0,0). - const GeomProp::NormalResult aNorm = aProp.Normal(0.0, THE_LIN_TOL); - ASSERT_TRUE(aNorm.IsDefined); - EXPECT_NEAR(aNorm.Direction.X(), -1.0, THE_DIR_TOL); - EXPECT_NEAR(aNorm.Direction.Y(), 0.0, THE_DIR_TOL); - EXPECT_NEAR(aNorm.Direction.Z(), 0.0, THE_DIR_TOL); -} - -TEST(GeomProp_CircleTest, Normal_AllParams) -{ - const double aRadius = 5.0; - const gp_Pnt aCenter(0, 0, 0); - gp_Circ aCirc(gp_Ax2(aCenter, gp_Dir(0, 0, 1)), aRadius); - occ::handle aCircle = new Geom_Circle(aCirc); - GeomProp_Curve aProp(aCircle); - - // Normal should always point from the curve point toward the center. - for (int i = 0; i < 12; ++i) - { - const double aParam = i * M_PI / 6.0; - // Compute expected normal direction from the curve point toward the center. - const double aCosT = std::cos(aParam); - const double aSinT = std::sin(aParam); - const gp_Pnt aPntOnCurve(aRadius * aCosT, aRadius * aSinT, 0.0); - const gp_Dir aExpectedNorm(aCenter.X() - aPntOnCurve.X(), - aCenter.Y() - aPntOnCurve.Y(), - aCenter.Z() - aPntOnCurve.Z()); - - const GeomProp::NormalResult aNorm = aProp.Normal(aParam, THE_LIN_TOL); - ASSERT_TRUE(aNorm.IsDefined) << "Normal undefined at param=" << aParam; - const double aDot = aNorm.Direction.Dot(aExpectedNorm); - EXPECT_NEAR(std::abs(aDot), 1.0, THE_DIR_TOL) - << "Normal does not point toward center at param=" << aParam; - } -} - -TEST(GeomProp_CircleTest, Centre_IsCircleCenter) -{ - const gp_Pnt aCenter(0, 0, 0); - gp_Circ aCirc(gp_Ax2(aCenter, gp_Dir(0, 0, 1)), 5.0); - occ::handle aCircle = new Geom_Circle(aCirc); - GeomProp_Curve aProp(aCircle); - - for (int i = 0; i < 8; ++i) - { - const double aParam = i * M_PI / 4.0; - const GeomProp::CentreResult aCentre = aProp.CentreOfCurvature(aParam, THE_LIN_TOL); - ASSERT_TRUE(aCentre.IsDefined) << "Centre undefined at param=" << aParam; - EXPECT_NEAR(aCentre.Centre.Distance(aCenter), 0.0, THE_POINT_TOL) - << "Centre not at circle center, param=" << aParam; - } -} - -TEST(GeomProp_CircleTest, Centre_OffCenter) -{ - const gp_Pnt aCenter(1, 2, 3); - gp_Circ aCirc(gp_Ax2(aCenter, gp_Dir(0, 0, 1)), 5.0); - occ::handle aCircle = new Geom_Circle(aCirc); - GeomProp_Curve aProp(aCircle); - - const GeomProp::CentreResult aCentre = aProp.CentreOfCurvature(1.0, THE_LIN_TOL); - ASSERT_TRUE(aCentre.IsDefined); - EXPECT_NEAR(aCentre.Centre.X(), 1.0, THE_POINT_TOL); - EXPECT_NEAR(aCentre.Centre.Y(), 2.0, THE_POINT_TOL); - EXPECT_NEAR(aCentre.Centre.Z(), 3.0, THE_POINT_TOL); -} - -TEST(GeomProp_CircleTest, FindCurvatureExtrema_Empty) -{ - gp_Circ aCirc(gp_Ax2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), 5.0); - occ::handle aCircle = new Geom_Circle(aCirc); - GeomProp_Curve aProp(aCircle); - - const GeomProp::CurveAnalysis aResult = aProp.FindCurvatureExtrema(); - ASSERT_TRUE(aResult.IsDone); - EXPECT_EQ(aResult.Points.Length(), 0); -} - -TEST(GeomProp_CircleTest, FindInflections_Empty) -{ - gp_Circ aCirc(gp_Ax2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), 5.0); - occ::handle aCircle = new Geom_Circle(aCirc); - GeomProp_Curve aProp(aCircle); - - const GeomProp::CurveAnalysis aResult = aProp.FindInflections(); - ASSERT_TRUE(aResult.IsDone); - EXPECT_EQ(aResult.Points.Length(), 0); -} - -TEST(GeomProp_CircleTest, GetType_IsCircle) -{ - gp_Circ aCirc(gp_Ax2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), 5.0); - occ::handle aCircle = new Geom_Circle(aCirc); - GeomProp_Curve aProp(aCircle); - - EXPECT_EQ(aProp.GetType(), GeomAbs_Circle); -} - -TEST(GeomProp_CircleTest, Tangent_Perpendicular_ToRadius) -{ - const double aRadius = 5.0; - gp_Circ aCirc(gp_Ax2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), aRadius); - occ::handle aCircle = new Geom_Circle(aCirc); - GeomProp_Curve aProp(aCircle); - - for (int i = 0; i < 12; ++i) - { - const double aParam = i * M_PI / 6.0; - // Radius direction at this parameter. - const double aCosT = std::cos(aParam); - const double aSinT = std::sin(aParam); - const gp_Dir aRadDir(aCosT, aSinT, 0.0); - - const GeomProp::TangentResult aTan = aProp.Tangent(aParam, THE_LIN_TOL); - ASSERT_TRUE(aTan.IsDefined); - EXPECT_NEAR(aTan.Direction.Dot(aRadDir), 0.0, THE_DIR_TOL) - << "Tangent not perpendicular to radius at param=" << aParam; - } -} - -// ============================================================================ -// Cross-validation tests vs GeomLProp_CLProps -// ============================================================================ - -TEST(GeomProp_CircleTest, VsCLProps_AllProperties) -{ - gp_Circ aCirc(gp_Ax2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), 5.0); - occ::handle aCircle = new Geom_Circle(aCirc); - compareAll(aCircle, 0.0, 2.0 * M_PI, 20); -} - -TEST(GeomProp_CircleTest, VsCLProps_SmallRadius) -{ - gp_Circ aCirc(gp_Ax2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), 0.01); - occ::handle aCircle = new Geom_Circle(aCirc); - compareAll(aCircle, 0.0, 2.0 * M_PI); -} - -TEST(GeomProp_CircleTest, VsCLProps_LargeRadius) -{ - gp_Circ aCirc(gp_Ax2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), 1000.0); - occ::handle aCircle = new Geom_Circle(aCirc); - compareAll(aCircle, 0.0, 2.0 * M_PI); -} - -TEST(GeomProp_CircleTest, VsCLProps_OffCenter) -{ - gp_Circ aCirc(gp_Ax2(gp_Pnt(1, 2, 3), gp_Dir(0, 0, 1)), 5.0); - occ::handle aCircle = new Geom_Circle(aCirc); - compareAll(aCircle, 0.0, 2.0 * M_PI); -} - -TEST(GeomProp_CircleTest, VsCLProps_TiltedPlane) -{ - // Circle in a tilted plane with axis not along Z. - const gp_Dir anAxis(1, 1, 1); - gp_Circ aCirc(gp_Ax2(gp_Pnt(0, 0, 0), anAxis), 5.0); - occ::handle aCircle = new Geom_Circle(aCirc); - compareAll(aCircle, 0.0, 2.0 * M_PI); -} - -TEST(GeomProp_CircleTest, VsCLProps_CriticalPoints) -{ - occ::handle aCircle = new Geom_Circle(gp_Ax2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), 5.0); - const double aParams[] = {0.0, - 1.0e-10, - M_PI / 4.0, - M_PI / 2.0, - M_PI, - 3.0 * M_PI / 2.0, - 2.0 * M_PI - 1.0e-10, - M_PI / 2.0 + 1.0e-6, - M_PI / 2.0 - 1.0e-6}; - for (const double aParam : aParams) - { - compareTangent(aCircle, aParam); - compareCurvature(aCircle, aParam); - compareNormal(aCircle, aParam); - compareCentre(aCircle, aParam); - } -} diff --git a/src/ModelingData/TKG3d/GTests/GeomProp_Cone_Test.cxx b/src/ModelingData/TKG3d/GTests/GeomProp_Cone_Test.cxx deleted file mode 100644 index ebdd89b4bf..0000000000 --- a/src/ModelingData/TKG3d/GTests/GeomProp_Cone_Test.cxx +++ /dev/null @@ -1,407 +0,0 @@ -// 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. - -// Unit tests for GeomProp_Surface with ConicalSurface geometry. - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -namespace -{ -constexpr double THE_LIN_TOL = Precision::PConfusion(); -constexpr double THE_CURV_TOL = 1.0e-6; -constexpr double THE_DIR_TOL = 1.0e-4; - -void compareNormal(const occ::handle& theSurf, const double theU, const double theV) -{ - GeomProp_Surface aProp(theSurf); - const GeomProp::SurfaceNormalResult aNew = aProp.Normal(theU, theV, THE_LIN_TOL); - - GeomLProp_SLProps anOld(theSurf, theU, theV, 2, THE_LIN_TOL); - if (anOld.IsNormalDefined()) - { - ASSERT_TRUE(aNew.IsDefined) << "New normal undefined at (" << theU << "," << theV << ")"; - const double aDot = aNew.Direction.Dot(anOld.Normal()); - EXPECT_NEAR(std::abs(aDot), 1.0, THE_DIR_TOL) - << "Normal mismatch at (" << theU << "," << theV << ")"; - } -} - -void compareCurvatures(const occ::handle& theSurf, - const double theU, - const double theV) -{ - GeomProp_Surface aProp(theSurf); - const GeomProp::SurfaceCurvatureResult aNew = aProp.Curvatures(theU, theV, THE_LIN_TOL); - - GeomLProp_SLProps anOld(theSurf, theU, theV, 2, THE_LIN_TOL); - if (anOld.IsCurvatureDefined()) - { - ASSERT_TRUE(aNew.IsDefined) << "New curvatures undefined at (" << theU << "," << theV << ")"; - EXPECT_NEAR(aNew.MinCurvature, anOld.MinCurvature(), THE_CURV_TOL) - << "MinCurvature mismatch at (" << theU << "," << theV << ")"; - EXPECT_NEAR(aNew.MaxCurvature, anOld.MaxCurvature(), THE_CURV_TOL) - << "MaxCurvature mismatch at (" << theU << "," << theV << ")"; - } -} - -void compareMeanGaussian(const occ::handle& theSurf, - const double theU, - const double theV) -{ - GeomProp_Surface aProp(theSurf); - const GeomProp::MeanGaussianResult aNew = aProp.MeanGaussian(theU, theV, THE_LIN_TOL); - - GeomLProp_SLProps anOld(theSurf, theU, theV, 2, THE_LIN_TOL); - if (anOld.IsCurvatureDefined()) - { - ASSERT_TRUE(aNew.IsDefined) << "New MeanGaussian undefined at (" << theU << "," << theV << ")"; - EXPECT_NEAR(aNew.MeanCurvature, anOld.MeanCurvature(), THE_CURV_TOL) - << "Mean curvature mismatch at (" << theU << "," << theV << ")"; - EXPECT_NEAR(aNew.GaussianCurvature, anOld.GaussianCurvature(), THE_CURV_TOL) - << "Gaussian curvature mismatch at (" << theU << "," << theV << ")"; - } -} - -void compareAllSurface(const occ::handle& theSurf, - const double theUMin, - const double theUMax, - const double theVMin, - const double theVMax, - const int theNbU = 5, - const int theNbV = 5) -{ - const double aUStep = (theUMax - theUMin) / theNbU; - const double aVStep = (theVMax - theVMin) / theNbV; - for (int i = 0; i <= theNbU; ++i) - { - for (int j = 0; j <= theNbV; ++j) - { - const double aU = theUMin + i * aUStep; - const double aV = theVMin + j * aVStep; - compareNormal(theSurf, aU, aV); - compareCurvatures(theSurf, aU, aV); - compareMeanGaussian(theSurf, aU, aV); - } - } -} -} // namespace - -// ============================================================================ -// Analytical reference tests -// ============================================================================ - -TEST(GeomProp_ConeTest, Normal_NotParallelToAxis) -{ - const double aHalfAngle = M_PI / 6.0; - const double aRefRadius = 5.0; - occ::handle aCone = - new Geom_ConicalSurface(gp_Ax3(), aHalfAngle, aRefRadius); - GeomProp_Surface aProp(aCone); - - const GeomProp::SurfaceNormalResult aNorm = aProp.Normal(0.0, 1.0, THE_LIN_TOL); - ASSERT_TRUE(aNorm.IsDefined); - // Normal should not be parallel to Z axis for a cone. - EXPECT_LT(std::abs(aNorm.Direction.Z()), 1.0 - THE_DIR_TOL); -} - -TEST(GeomProp_ConeTest, Normal_Grid) -{ - const double aHalfAngle = M_PI / 6.0; - const double aRefRadius = 5.0; - occ::handle aCone = - new Geom_ConicalSurface(gp_Ax3(), aHalfAngle, aRefRadius); - GeomProp_Surface aProp(aCone); - - for (int i = 0; i < 8; ++i) - { - for (int j = 1; j <= 5; ++j) - { - const double aU = i * M_PI / 4.0; - const double aV = j * 2.0; - const GeomProp::SurfaceNormalResult aNorm = aProp.Normal(aU, aV, THE_LIN_TOL); - ASSERT_TRUE(aNorm.IsDefined) << "Normal undefined at (" << aU << "," << aV << ")"; - } - } -} - -TEST(GeomProp_ConeTest, Curvatures_OneZero) -{ - const double aHalfAngle = M_PI / 6.0; - const double aRefRadius = 5.0; - occ::handle aCone = - new Geom_ConicalSurface(gp_Ax3(), aHalfAngle, aRefRadius); - GeomProp_Surface aProp(aCone); - - const GeomProp::SurfaceCurvatureResult aCurv = aProp.Curvatures(1.0, 2.0, THE_LIN_TOL); - ASSERT_TRUE(aCurv.IsDefined); - // MaxCurvature is zero (along the ruling), MinCurvature is negative (concave). - EXPECT_NEAR(aCurv.MaxCurvature, 0.0, THE_CURV_TOL); - EXPECT_LT(aCurv.MinCurvature, -THE_CURV_TOL); -} - -TEST(GeomProp_ConeTest, Curvatures_VaryWithV) -{ - const double aHalfAngle = M_PI / 6.0; - const double aRefRadius = 5.0; - occ::handle aCone = - new Geom_ConicalSurface(gp_Ax3(), aHalfAngle, aRefRadius); - GeomProp_Surface aProp(aCone); - - const GeomProp::SurfaceCurvatureResult aCurv1 = aProp.Curvatures(0.0, 1.0, THE_LIN_TOL); - const GeomProp::SurfaceCurvatureResult aCurv2 = aProp.Curvatures(0.0, 5.0, THE_LIN_TOL); - ASSERT_TRUE(aCurv1.IsDefined); - ASSERT_TRUE(aCurv2.IsDefined); - // The non-zero curvature is MinCurvature (negative, concave), varies with V. - EXPECT_NE(aCurv1.MinCurvature, aCurv2.MinCurvature); -} - -TEST(GeomProp_ConeTest, Curvatures_DecreasesWithV) -{ - const double aHalfAngle = M_PI / 6.0; - const double aRefRadius = 5.0; - occ::handle aCone = - new Geom_ConicalSurface(gp_Ax3(), aHalfAngle, aRefRadius); - GeomProp_Surface aProp(aCone); - - // As v increases, the cross-section radius grows and curvature magnitude decreases. - const GeomProp::SurfaceCurvatureResult aCurv1 = aProp.Curvatures(0.0, 1.0, THE_LIN_TOL); - const GeomProp::SurfaceCurvatureResult aCurv2 = aProp.Curvatures(0.0, 5.0, THE_LIN_TOL); - const GeomProp::SurfaceCurvatureResult aCurv3 = aProp.Curvatures(0.0, 10.0, THE_LIN_TOL); - ASSERT_TRUE(aCurv1.IsDefined); - ASSERT_TRUE(aCurv2.IsDefined); - ASSERT_TRUE(aCurv3.IsDefined); - // The non-zero curvature is MinCurvature (negative); magnitude decreases with V. - EXPECT_GT(std::abs(aCurv1.MinCurvature), std::abs(aCurv2.MinCurvature)); - EXPECT_GT(std::abs(aCurv2.MinCurvature), std::abs(aCurv3.MinCurvature)); -} - -TEST(GeomProp_ConeTest, MeanGaussian_GaussianZero) -{ - const double aHalfAngle = M_PI / 6.0; - const double aRefRadius = 5.0; - occ::handle aCone = - new Geom_ConicalSurface(gp_Ax3(), aHalfAngle, aRefRadius); - GeomProp_Surface aProp(aCone); - - const GeomProp::MeanGaussianResult aMG = aProp.MeanGaussian(1.0, 3.0, THE_LIN_TOL); - ASSERT_TRUE(aMG.IsDefined); - EXPECT_NEAR(aMG.GaussianCurvature, 0.0, THE_CURV_TOL); -} - -TEST(GeomProp_ConeTest, MeanGaussian_MeanVaries) -{ - const double aHalfAngle = M_PI / 6.0; - const double aRefRadius = 5.0; - occ::handle aCone = - new Geom_ConicalSurface(gp_Ax3(), aHalfAngle, aRefRadius); - GeomProp_Surface aProp(aCone); - - const GeomProp::MeanGaussianResult aMG1 = aProp.MeanGaussian(0.0, 1.0, THE_LIN_TOL); - const GeomProp::MeanGaussianResult aMG2 = aProp.MeanGaussian(0.0, 5.0, THE_LIN_TOL); - ASSERT_TRUE(aMG1.IsDefined); - ASSERT_TRUE(aMG2.IsDefined); - EXPECT_NE(aMG1.MeanCurvature, aMG2.MeanCurvature); -} - -TEST(GeomProp_ConeTest, GetType_IsCone) -{ - occ::handle aCone = new Geom_ConicalSurface(gp_Ax3(), M_PI / 6.0, 5.0); - GeomProp_Surface aProp(aCone); - - EXPECT_EQ(aProp.GetType(), GeomAbs_Cone); -} - -TEST(GeomProp_ConeTest, Curvatures_AwayFromApex) -{ - const double aHalfAngle = M_PI / 6.0; - const double aRefRadius = 5.0; - occ::handle aCone = - new Geom_ConicalSurface(gp_Ax3(), aHalfAngle, aRefRadius); - GeomProp_Surface aProp(aCone); - - // At v=0 (reference circle). MaxCurvature is 0 (along ruling). - const GeomProp::SurfaceCurvatureResult aCurvAtV0 = aProp.Curvatures(0.0, 0.0, THE_LIN_TOL); - ASSERT_TRUE(aCurvAtV0.IsDefined); - EXPECT_NEAR(aCurvAtV0.MaxCurvature, 0.0, THE_CURV_TOL); - - // At v=10 (farther from apex). MaxCurvature is still 0 (along ruling). - const GeomProp::SurfaceCurvatureResult aCurvAtV10 = aProp.Curvatures(0.0, 10.0, THE_LIN_TOL); - ASSERT_TRUE(aCurvAtV10.IsDefined); - EXPECT_NEAR(aCurvAtV10.MaxCurvature, 0.0, THE_CURV_TOL); -} - -TEST(GeomProp_ConeTest, Normal_Symmetric) -{ - const double aHalfAngle = M_PI / 6.0; - const double aRefRadius = 5.0; - occ::handle aCone = - new Geom_ConicalSurface(gp_Ax3(), aHalfAngle, aRefRadius); - GeomProp_Surface aProp(aCone); - - // At u and u+PI, the normals should be related by reflection through the axis. - const double aV = 3.0; - const GeomProp::SurfaceNormalResult aNorm1 = aProp.Normal(0.0, aV, THE_LIN_TOL); - const GeomProp::SurfaceNormalResult aNorm2 = aProp.Normal(M_PI, aV, THE_LIN_TOL); - ASSERT_TRUE(aNorm1.IsDefined); - ASSERT_TRUE(aNorm2.IsDefined); - // Z components should be the same. - EXPECT_NEAR(aNorm1.Direction.Z(), aNorm2.Direction.Z(), THE_DIR_TOL); -} - -// ============================================================================ -// Cross-validation tests vs GeomLProp_SLProps -// ============================================================================ - -TEST(GeomProp_ConeTest, VsSLProps_Normal) -{ - occ::handle aCone = new Geom_ConicalSurface(gp_Ax3(), M_PI / 6.0, 5.0); - const double aUStep = M_PI / 3.0; - for (int i = 0; i <= 6; ++i) - { - for (int j = 1; j <= 5; ++j) - { - compareNormal(aCone, i * aUStep, j * 2.0); - } - } -} - -TEST(GeomProp_ConeTest, VsSLProps_Curvatures) -{ - occ::handle aCone = new Geom_ConicalSurface(gp_Ax3(), M_PI / 6.0, 5.0); - const double aUStep = M_PI / 3.0; - for (int i = 0; i <= 6; ++i) - { - for (int j = 1; j <= 5; ++j) - { - compareCurvatures(aCone, i * aUStep, j * 2.0); - } - } -} - -TEST(GeomProp_ConeTest, VsSLProps_MeanGaussian) -{ - occ::handle aCone = new Geom_ConicalSurface(gp_Ax3(), M_PI / 6.0, 5.0); - const double aUStep = M_PI / 3.0; - for (int i = 0; i <= 6; ++i) - { - for (int j = 1; j <= 5; ++j) - { - compareMeanGaussian(aCone, i * aUStep, j * 2.0); - } - } -} - -TEST(GeomProp_ConeTest, VsSLProps_AllProperties) -{ - occ::handle aCone = new Geom_ConicalSurface(gp_Ax3(), M_PI / 6.0, 5.0); - compareAllSurface(aCone, 0.0, 2.0 * M_PI, 1.0, 10.0, 8, 8); -} - -TEST(GeomProp_ConeTest, VsSLProps_SmallAngle) -{ - occ::handle aCone = new Geom_ConicalSurface(gp_Ax3(), M_PI / 12.0, 5.0); - compareAllSurface(aCone, 0.0, 2.0 * M_PI, 1.0, 10.0); -} - -TEST(GeomProp_ConeTest, VsSLProps_LargeAngle) -{ - occ::handle aCone = new Geom_ConicalSurface(gp_Ax3(), M_PI / 3.0, 5.0); - compareAllSurface(aCone, 0.0, 2.0 * M_PI, 1.0, 10.0); -} - -TEST(GeomProp_ConeTest, VsSLProps_LargeRadius) -{ - occ::handle aCone = new Geom_ConicalSurface(gp_Ax3(), M_PI / 6.0, 100.0); - compareAllSurface(aCone, 0.0, 2.0 * M_PI, 1.0, 20.0); -} - -TEST(GeomProp_ConeTest, VsSLProps_SmallRadius) -{ - occ::handle aCone = new Geom_ConicalSurface(gp_Ax3(), M_PI / 6.0, 0.5); - compareAllSurface(aCone, 0.0, 2.0 * M_PI, 1.0, 10.0); -} - -TEST(GeomProp_ConeTest, Curvatures_CompareV0_V5) -{ - const double aHalfAngle = M_PI / 6.0; - const double aRefRadius = 5.0; - occ::handle aCone = - new Geom_ConicalSurface(gp_Ax3(), aHalfAngle, aRefRadius); - GeomProp_Surface aProp(aCone); - - const GeomProp::SurfaceCurvatureResult aCurvV0 = aProp.Curvatures(0.0, 0.0, THE_LIN_TOL); - const GeomProp::SurfaceCurvatureResult aCurvV5 = aProp.Curvatures(0.0, 5.0, THE_LIN_TOL); - ASSERT_TRUE(aCurvV0.IsDefined); - ASSERT_TRUE(aCurvV5.IsDefined); - // At v=0 the cross-section radius is smaller, so |MinCurvature| is larger. - // MinCurvature is the non-zero (negative) curvature; MaxCurvature is 0. - EXPECT_GT(std::abs(aCurvV0.MinCurvature), std::abs(aCurvV5.MinCurvature)); -} - -TEST(GeomProp_ConeTest, MeanGaussian_Consistent) -{ - const double aHalfAngle = M_PI / 6.0; - const double aRefRadius = 5.0; - occ::handle aCone = - new Geom_ConicalSurface(gp_Ax3(), aHalfAngle, aRefRadius); - GeomProp_Surface aProp(aCone); - - // Verify H = (k1+k2)/2 and K = k1*k2 = 0. - for (int j = 1; j <= 5; ++j) - { - const double aV = j * 2.0; - const GeomProp::SurfaceCurvatureResult aCurv = aProp.Curvatures(0.0, aV, THE_LIN_TOL); - const GeomProp::MeanGaussianResult aMG = aProp.MeanGaussian(0.0, aV, THE_LIN_TOL); - ASSERT_TRUE(aCurv.IsDefined); - ASSERT_TRUE(aMG.IsDefined); - const double aExpectedMean = (aCurv.MinCurvature + aCurv.MaxCurvature) / 2.0; - const double aExpectedGauss = aCurv.MinCurvature * aCurv.MaxCurvature; - EXPECT_NEAR(aMG.MeanCurvature, aExpectedMean, THE_CURV_TOL) << "H != (k1+k2)/2 at v=" << aV; - EXPECT_NEAR(aMG.GaussianCurvature, aExpectedGauss, THE_CURV_TOL) << "K != k1*k2 at v=" << aV; - } -} - -TEST(GeomProp_ConeTest, VsSLProps_CriticalPoints) -{ - occ::handle aCone = new Geom_ConicalSurface(gp_Ax3(), M_PI / 6.0, 5.0); - // Critical: near apex (small v), seam, various angles - const double aParams[][2] = {{0.0, 0.0}, - {1.0e-10, 0.0}, - {0.0, 1.0e-10}, - {0.0, 0.1}, - {0.0, 1.0}, - {0.0, 10.0}, - {0.0, 100.0}, - {M_PI / 2.0, 0.5}, - {M_PI, 1.0}, - {3.0 * M_PI / 2.0, 2.0}, - {2.0 * M_PI - 1.0e-10, 0.5}, - {M_PI / 4.0, 1.0e-6}}; - for (const auto& aUV : aParams) - { - compareNormal(aCone, aUV[0], aUV[1]); - compareCurvatures(aCone, aUV[0], aUV[1]); - compareMeanGaussian(aCone, aUV[0], aUV[1]); - } -} diff --git a/src/ModelingData/TKG3d/GTests/GeomProp_Cylinder_Test.cxx b/src/ModelingData/TKG3d/GTests/GeomProp_Cylinder_Test.cxx deleted file mode 100644 index 94e0ff3987..0000000000 --- a/src/ModelingData/TKG3d/GTests/GeomProp_Cylinder_Test.cxx +++ /dev/null @@ -1,397 +0,0 @@ -// 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. - -// Unit tests for GeomProp_Surface with CylindricalSurface geometry. - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -namespace -{ -constexpr double THE_LIN_TOL = Precision::PConfusion(); -constexpr double THE_CURV_TOL = 1.0e-6; -constexpr double THE_DIR_TOL = 1.0e-4; - -void compareNormal(const occ::handle& theSurf, const double theU, const double theV) -{ - GeomProp_Surface aProp(theSurf); - const GeomProp::SurfaceNormalResult aNew = aProp.Normal(theU, theV, THE_LIN_TOL); - - GeomLProp_SLProps anOld(theSurf, theU, theV, 2, THE_LIN_TOL); - if (anOld.IsNormalDefined()) - { - ASSERT_TRUE(aNew.IsDefined) << "New normal undefined at (" << theU << "," << theV << ")"; - const double aDot = aNew.Direction.Dot(anOld.Normal()); - EXPECT_NEAR(std::abs(aDot), 1.0, THE_DIR_TOL) - << "Normal mismatch at (" << theU << "," << theV << ")"; - } -} - -void compareCurvatures(const occ::handle& theSurf, - const double theU, - const double theV) -{ - GeomProp_Surface aProp(theSurf); - const GeomProp::SurfaceCurvatureResult aNew = aProp.Curvatures(theU, theV, THE_LIN_TOL); - - GeomLProp_SLProps anOld(theSurf, theU, theV, 2, THE_LIN_TOL); - if (anOld.IsCurvatureDefined()) - { - ASSERT_TRUE(aNew.IsDefined) << "New curvatures undefined at (" << theU << "," << theV << ")"; - EXPECT_NEAR(aNew.MinCurvature, anOld.MinCurvature(), THE_CURV_TOL) - << "MinCurvature mismatch at (" << theU << "," << theV << ")"; - EXPECT_NEAR(aNew.MaxCurvature, anOld.MaxCurvature(), THE_CURV_TOL) - << "MaxCurvature mismatch at (" << theU << "," << theV << ")"; - } -} - -void compareMeanGaussian(const occ::handle& theSurf, - const double theU, - const double theV) -{ - GeomProp_Surface aProp(theSurf); - const GeomProp::MeanGaussianResult aNew = aProp.MeanGaussian(theU, theV, THE_LIN_TOL); - - GeomLProp_SLProps anOld(theSurf, theU, theV, 2, THE_LIN_TOL); - if (anOld.IsCurvatureDefined()) - { - ASSERT_TRUE(aNew.IsDefined) << "New MeanGaussian undefined at (" << theU << "," << theV << ")"; - EXPECT_NEAR(aNew.MeanCurvature, anOld.MeanCurvature(), THE_CURV_TOL) - << "Mean curvature mismatch at (" << theU << "," << theV << ")"; - EXPECT_NEAR(aNew.GaussianCurvature, anOld.GaussianCurvature(), THE_CURV_TOL) - << "Gaussian curvature mismatch at (" << theU << "," << theV << ")"; - } -} - -void compareAllSurface(const occ::handle& theSurf, - const double theUMin, - const double theUMax, - const double theVMin, - const double theVMax, - const int theNbU = 5, - const int theNbV = 5) -{ - const double aUStep = (theUMax - theUMin) / theNbU; - const double aVStep = (theVMax - theVMin) / theNbV; - for (int i = 0; i <= theNbU; ++i) - { - for (int j = 0; j <= theNbV; ++j) - { - const double aU = theUMin + i * aUStep; - const double aV = theVMin + j * aVStep; - compareNormal(theSurf, aU, aV); - compareCurvatures(theSurf, aU, aV); - compareMeanGaussian(theSurf, aU, aV); - } - } -} -} // namespace - -// ============================================================================ -// Analytical reference tests -// ============================================================================ - -TEST(GeomProp_CylinderTest, Normal_PointsOutward) -{ - const double aRadius = 5.0; - occ::handle aCyl = new Geom_CylindricalSurface(gp_Ax3(), aRadius); - GeomProp_Surface aProp(aCyl); - - // At u=0, v=0, the surface point is (R,0,0), normal should point radially outward. - const GeomProp::SurfaceNormalResult aNorm = aProp.Normal(0.0, 0.0, THE_LIN_TOL); - ASSERT_TRUE(aNorm.IsDefined); - EXPECT_NEAR(std::abs(aNorm.Direction.X()), 1.0, THE_DIR_TOL); - EXPECT_NEAR(aNorm.Direction.Y(), 0.0, THE_DIR_TOL); - EXPECT_NEAR(aNorm.Direction.Z(), 0.0, THE_DIR_TOL); -} - -TEST(GeomProp_CylinderTest, Normal_AllParams) -{ - const double aRadius = 5.0; - occ::handle aCyl = new Geom_CylindricalSurface(gp_Ax3(), aRadius); - GeomProp_Surface aProp(aCyl); - - for (int i = 0; i < 12; ++i) - { - const double aU = i * M_PI / 6.0; - for (int j = -3; j <= 3; ++j) - { - const double aV = j * 2.0; - const GeomProp::SurfaceNormalResult aNorm = aProp.Normal(aU, aV, THE_LIN_TOL); - ASSERT_TRUE(aNorm.IsDefined) << "Normal undefined at (" << aU << "," << aV << ")"; - // Normal should be perpendicular to the axis (Z component = 0). - EXPECT_NEAR(aNorm.Direction.Z(), 0.0, THE_DIR_TOL) - << "Normal not perpendicular to axis at (" << aU << "," << aV << ")"; - } - } -} - -TEST(GeomProp_CylinderTest, Curvatures_OneZero) -{ - const double aRadius = 5.0; - occ::handle aCyl = new Geom_CylindricalSurface(gp_Ax3(), aRadius); - GeomProp_Surface aProp(aCyl); - - const GeomProp::SurfaceCurvatureResult aCurv = aProp.Curvatures(1.0, 1.0, THE_LIN_TOL); - ASSERT_TRUE(aCurv.IsDefined); - // MinCurvature is -1/R (concave direction), MaxCurvature is 0 (along axis). - EXPECT_NEAR(aCurv.MinCurvature, -1.0 / aRadius, THE_CURV_TOL); - EXPECT_NEAR(aCurv.MaxCurvature, 0.0, THE_CURV_TOL); -} - -TEST(GeomProp_CylinderTest, Curvatures_OtherIsInvR) -{ - const double aRadius = 5.0; - occ::handle aCyl = new Geom_CylindricalSurface(gp_Ax3(), aRadius); - GeomProp_Surface aProp(aCyl); - - const GeomProp::SurfaceCurvatureResult aCurv = aProp.Curvatures(1.0, 1.0, THE_LIN_TOL); - ASSERT_TRUE(aCurv.IsDefined); - // The non-zero curvature is MinCurvature = -1/R (signed, concave). - EXPECT_NEAR(aCurv.MinCurvature, -1.0 / aRadius, THE_CURV_TOL); -} - -TEST(GeomProp_CylinderTest, Curvatures_Constant) -{ - const double aRadius = 5.0; - occ::handle aCyl = new Geom_CylindricalSurface(gp_Ax3(), aRadius); - GeomProp_Surface aProp(aCyl); - - const GeomProp::SurfaceCurvatureResult aRef = aProp.Curvatures(0.0, 0.0, THE_LIN_TOL); - ASSERT_TRUE(aRef.IsDefined); - - for (int i = 0; i < 8; ++i) - { - for (int j = -3; j <= 3; ++j) - { - const double aU = i * M_PI / 4.0; - const double aV = j * 3.0; - const GeomProp::SurfaceCurvatureResult aCurv = aProp.Curvatures(aU, aV, THE_LIN_TOL); - ASSERT_TRUE(aCurv.IsDefined); - EXPECT_NEAR(aCurv.MinCurvature, aRef.MinCurvature, THE_CURV_TOL) - << "MinCurvature not constant at (" << aU << "," << aV << ")"; - EXPECT_NEAR(aCurv.MaxCurvature, aRef.MaxCurvature, THE_CURV_TOL) - << "MaxCurvature not constant at (" << aU << "," << aV << ")"; - } - } -} - -TEST(GeomProp_CylinderTest, MeanGaussian_GaussianZero) -{ - const double aRadius = 5.0; - occ::handle aCyl = new Geom_CylindricalSurface(gp_Ax3(), aRadius); - GeomProp_Surface aProp(aCyl); - - const GeomProp::MeanGaussianResult aMG = aProp.MeanGaussian(1.0, 1.0, THE_LIN_TOL); - ASSERT_TRUE(aMG.IsDefined); - EXPECT_NEAR(aMG.GaussianCurvature, 0.0, THE_CURV_TOL); -} - -TEST(GeomProp_CylinderTest, MeanGaussian_MeanHalfInvR) -{ - const double aRadius = 5.0; - occ::handle aCyl = new Geom_CylindricalSurface(gp_Ax3(), aRadius); - GeomProp_Surface aProp(aCyl); - - const GeomProp::MeanGaussianResult aMG = aProp.MeanGaussian(1.0, 1.0, THE_LIN_TOL); - ASSERT_TRUE(aMG.IsDefined); - EXPECT_NEAR(std::abs(aMG.MeanCurvature), 1.0 / (2.0 * aRadius), THE_CURV_TOL); -} - -TEST(GeomProp_CylinderTest, GetType_IsCylinder) -{ - occ::handle aCyl = new Geom_CylindricalSurface(gp_Ax3(), 5.0); - GeomProp_Surface aProp(aCyl); - - EXPECT_EQ(aProp.GetType(), GeomAbs_Cylinder); -} - -TEST(GeomProp_CylinderTest, Curvatures_SmallRadius) -{ - const double aRadius = 0.1; - occ::handle aCyl = new Geom_CylindricalSurface(gp_Ax3(), aRadius); - GeomProp_Surface aProp(aCyl); - - const GeomProp::SurfaceCurvatureResult aCurv = aProp.Curvatures(0.5, 0.5, THE_LIN_TOL); - ASSERT_TRUE(aCurv.IsDefined); - // MinCurvature = -1/R (concave), MaxCurvature = 0 (along axis). - EXPECT_NEAR(aCurv.MinCurvature, -1.0 / aRadius, THE_CURV_TOL); - EXPECT_NEAR(aCurv.MaxCurvature, 0.0, THE_CURV_TOL); -} - -TEST(GeomProp_CylinderTest, Curvatures_LargeRadius) -{ - const double aRadius = 100.0; - occ::handle aCyl = new Geom_CylindricalSurface(gp_Ax3(), aRadius); - GeomProp_Surface aProp(aCyl); - - const GeomProp::SurfaceCurvatureResult aCurv = aProp.Curvatures(0.5, 0.5, THE_LIN_TOL); - ASSERT_TRUE(aCurv.IsDefined); - // MinCurvature = -1/R (concave), MaxCurvature = 0 (along axis). - EXPECT_NEAR(aCurv.MinCurvature, -1.0 / aRadius, THE_CURV_TOL); - EXPECT_NEAR(aCurv.MaxCurvature, 0.0, THE_CURV_TOL); -} - -TEST(GeomProp_CylinderTest, VsSLProps_Normal) -{ - occ::handle aCyl = new Geom_CylindricalSurface(gp_Ax3(), 5.0); - const double aUStep = M_PI / 3.0; - const double aVStep = 2.0; - for (int i = 0; i <= 6; ++i) - { - for (int j = -3; j <= 3; ++j) - { - compareNormal(aCyl, i * aUStep, j * aVStep); - } - } -} - -TEST(GeomProp_CylinderTest, VsSLProps_Curvatures) -{ - occ::handle aCyl = new Geom_CylindricalSurface(gp_Ax3(), 5.0); - const double aUStep = M_PI / 3.0; - const double aVStep = 2.0; - for (int i = 0; i <= 6; ++i) - { - for (int j = -3; j <= 3; ++j) - { - compareCurvatures(aCyl, i * aUStep, j * aVStep); - } - } -} - -TEST(GeomProp_CylinderTest, VsSLProps_MeanGaussian) -{ - occ::handle aCyl = new Geom_CylindricalSurface(gp_Ax3(), 5.0); - const double aUStep = M_PI / 3.0; - const double aVStep = 2.0; - for (int i = 0; i <= 6; ++i) - { - for (int j = -3; j <= 3; ++j) - { - compareMeanGaussian(aCyl, i * aUStep, j * aVStep); - } - } -} - -TEST(GeomProp_CylinderTest, VsSLProps_AllProperties) -{ - occ::handle aCyl = new Geom_CylindricalSurface(gp_Ax3(), 5.0); - compareAllSurface(aCyl, 0.0, 2.0 * M_PI, -10.0, 10.0, 8, 8); -} - -TEST(GeomProp_CylinderTest, VsSLProps_SmallRadius) -{ - occ::handle aCyl = new Geom_CylindricalSurface(gp_Ax3(), 0.1); - compareAllSurface(aCyl, 0.0, 2.0 * M_PI, -5.0, 5.0); -} - -TEST(GeomProp_CylinderTest, VsSLProps_LargeRadius) -{ - occ::handle aCyl = new Geom_CylindricalSurface(gp_Ax3(), 100.0); - compareAllSurface(aCyl, 0.0, 2.0 * M_PI, -5.0, 5.0); -} - -TEST(GeomProp_CylinderTest, Normal_ConsistentOrientation) -{ - const double aRadius = 5.0; - occ::handle aCyl = new Geom_CylindricalSurface(gp_Ax3(), aRadius); - GeomProp_Surface aProp(aCyl); - - // Normal at any (u, v) should be radial and independent of v. - for (int i = 0; i < 8; ++i) - { - const double aU = i * M_PI / 4.0; - const GeomProp::SurfaceNormalResult aNorm1 = aProp.Normal(aU, 0.0, THE_LIN_TOL); - const GeomProp::SurfaceNormalResult aNorm2 = aProp.Normal(aU, 10.0, THE_LIN_TOL); - ASSERT_TRUE(aNorm1.IsDefined); - ASSERT_TRUE(aNorm2.IsDefined); - const double aDot = aNorm1.Direction.Dot(aNorm2.Direction); - EXPECT_NEAR(std::abs(aDot), 1.0, THE_DIR_TOL) << "Normal varies along v at u=" << aU; - } -} - -TEST(GeomProp_CylinderTest, MeanGaussian_Constant) -{ - const double aRadius = 5.0; - occ::handle aCyl = new Geom_CylindricalSurface(gp_Ax3(), aRadius); - GeomProp_Surface aProp(aCyl); - - const GeomProp::MeanGaussianResult aRef = aProp.MeanGaussian(0.0, 0.0, THE_LIN_TOL); - ASSERT_TRUE(aRef.IsDefined); - - for (int i = 0; i < 6; ++i) - { - for (int j = -3; j <= 3; ++j) - { - const double aU = i * M_PI / 3.0; - const double aV = j * 3.0; - const GeomProp::MeanGaussianResult aMG = aProp.MeanGaussian(aU, aV, THE_LIN_TOL); - ASSERT_TRUE(aMG.IsDefined); - EXPECT_NEAR(aMG.MeanCurvature, aRef.MeanCurvature, THE_CURV_TOL); - EXPECT_NEAR(aMG.GaussianCurvature, aRef.GaussianCurvature, THE_CURV_TOL); - } - } -} - -TEST(GeomProp_CylinderTest, Curvatures_IsNotUmbilic) -{ - const double aRadius = 5.0; - occ::handle aCyl = new Geom_CylindricalSurface(gp_Ax3(), aRadius); - GeomProp_Surface aProp(aCyl); - - const GeomProp::SurfaceCurvatureResult aCurv = aProp.Curvatures(1.0, 1.0, THE_LIN_TOL); - ASSERT_TRUE(aCurv.IsDefined); - // Min and max curvatures differ (0 vs 1/R). - EXPECT_GT(std::abs(aCurv.MaxCurvature - aCurv.MinCurvature), THE_CURV_TOL); -} - -TEST(GeomProp_CylinderTest, VsSLProps_LargeParams) -{ - occ::handle aCyl = new Geom_CylindricalSurface(gp_Ax3(), 5.0); - compareAllSurface(aCyl, 0.0, 2.0 * M_PI, 990.0, 1010.0); -} - -TEST(GeomProp_CylinderTest, VsSLProps_CriticalPoints) -{ - occ::handle aCyl = new Geom_CylindricalSurface(gp_Ax3(), 5.0); - // Critical: seam (u=0, near 2PI), axis extremes, various v - const double aParams[][2] = {{0.0, 0.0}, - {1.0e-10, 0.0}, - {2.0 * M_PI - 1.0e-10, 0.0}, - {M_PI / 2.0, 0.0}, - {M_PI, 0.0}, - {3.0 * M_PI / 2.0, 0.0}, - {0.0, 1.0e-10}, - {0.0, 1.0e6}, - {0.0, -1.0e6}, - {M_PI / 4.0, 100.0}, - {M_PI / 4.0, -100.0}, - {M_PI, 1.0e-6}}; - for (const auto& aUV : aParams) - { - compareNormal(aCyl, aUV[0], aUV[1]); - compareCurvatures(aCyl, aUV[0], aUV[1]); - compareMeanGaussian(aCyl, aUV[0], aUV[1]); - } -} diff --git a/src/ModelingData/TKG3d/GTests/GeomProp_Ellipse_Test.cxx b/src/ModelingData/TKG3d/GTests/GeomProp_Ellipse_Test.cxx deleted file mode 100644 index 7476c54ec9..0000000000 --- a/src/ModelingData/TKG3d/GTests/GeomProp_Ellipse_Test.cxx +++ /dev/null @@ -1,474 +0,0 @@ -// 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. - -// Unit tests for GeomProp_Curve with Ellipse geometry. - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -namespace -{ -constexpr double THE_LIN_TOL = Precision::PConfusion(); -constexpr double THE_CURV_TOL = 1.0e-8; -constexpr double THE_DIR_TOL = 1.0e-6; -constexpr double THE_POINT_TOL = 1.0e-6; - -//! Analytical curvature of an ellipse at parameter t. -//! k(t) = a*b / (a^2*sin^2(t) + b^2*cos^2(t))^(3/2) -double ellipseCurvature(const double theMajor, const double theMinor, const double theParam) -{ - const double aSin = std::sin(theParam); - const double aCos = std::cos(theParam); - const double aDenom = - std::pow(theMajor * theMajor * aSin * aSin + theMinor * theMinor * aCos * aCos, 1.5); - return theMajor * theMinor / aDenom; -} - -//! Compare tangent from new GeomProp_Curve vs old GeomLProp_CLProps. -void compareTangent(const occ::handle& theCurve, const double theParam) -{ - GeomProp_Curve aProp(theCurve); - const GeomProp::TangentResult aNew = aProp.Tangent(theParam, THE_LIN_TOL); - - GeomLProp_CLProps anOld(theCurve, theParam, 2, THE_LIN_TOL); - if (anOld.IsTangentDefined()) - { - ASSERT_TRUE(aNew.IsDefined) << "New tangent undefined but old is defined at param=" << theParam; - gp_Dir anOldDir; - anOld.Tangent(anOldDir); - const double aDot = aNew.Direction.Dot(anOldDir); - EXPECT_NEAR(std::abs(aDot), 1.0, THE_DIR_TOL) - << "Tangent direction mismatch at param=" << theParam; - } -} - -//! Compare curvature from new GeomProp_Curve vs old GeomLProp_CLProps. -void compareCurvature(const occ::handle& theCurve, const double theParam) -{ - GeomProp_Curve aProp(theCurve); - const GeomProp::CurvatureResult aNew = aProp.Curvature(theParam, THE_LIN_TOL); - - GeomLProp_CLProps anOld(theCurve, theParam, 2, THE_LIN_TOL); - if (anOld.IsTangentDefined()) - { - ASSERT_TRUE(aNew.IsDefined) << "New curvature undefined at param=" << theParam; - EXPECT_NEAR(aNew.Value, anOld.Curvature(), THE_CURV_TOL) - << "Curvature mismatch at param=" << theParam; - } -} - -//! Compare normal from new GeomProp_Curve vs old GeomLProp_CLProps. -void compareNormal(const occ::handle& theCurve, const double theParam) -{ - GeomProp_Curve aProp(theCurve); - const GeomProp::NormalResult aNew = aProp.Normal(theParam, THE_LIN_TOL); - - GeomLProp_CLProps anOld(theCurve, theParam, 2, THE_LIN_TOL); - if (anOld.IsTangentDefined() && std::abs(anOld.Curvature()) > THE_LIN_TOL) - { - ASSERT_TRUE(aNew.IsDefined) << "New normal undefined at param=" << theParam; - gp_Dir anOldNorm; - anOld.Normal(anOldNorm); - const double aDot = aNew.Direction.Dot(anOldNorm); - EXPECT_NEAR(std::abs(aDot), 1.0, THE_DIR_TOL) - << "Normal direction mismatch at param=" << theParam; - } -} - -//! Compare centre of curvature from new vs old. -void compareCentre(const occ::handle& theCurve, const double theParam) -{ - GeomProp_Curve aProp(theCurve); - const GeomProp::CentreResult aNew = aProp.CentreOfCurvature(theParam, THE_LIN_TOL); - - GeomLProp_CLProps anOld(theCurve, theParam, 2, THE_LIN_TOL); - if (anOld.IsTangentDefined() && std::abs(anOld.Curvature()) > THE_LIN_TOL) - { - ASSERT_TRUE(aNew.IsDefined) << "New centre undefined at param=" << theParam; - gp_Pnt anOldCentre; - anOld.CentreOfCurvature(anOldCentre); - EXPECT_NEAR(aNew.Centre.Distance(anOldCentre), 0.0, THE_POINT_TOL) - << "Centre mismatch at param=" << theParam; - } -} - -//! Run all comparisons at several parameter values. -void compareAll(const occ::handle& theCurve, - const double theFirst, - const double theLast, - const int theNbSamples = 10) -{ - const double aStep = (theLast - theFirst) / theNbSamples; - for (int i = 0; i <= theNbSamples; ++i) - { - const double aParam = theFirst + i * aStep; - compareTangent(theCurve, aParam); - compareCurvature(theCurve, aParam); - compareNormal(theCurve, aParam); - compareCentre(theCurve, aParam); - } -} -} // namespace - -// ============================================================================ -// Analytical reference tests -// ============================================================================ - -TEST(GeomProp_EllipseTest, Curvature_AtMajorVertex) -{ - // At t=0 (major vertex): k = a*b / b^3 = a / b^2 - const double aMajor = 10.0; - const double aMinor = 5.0; - gp_Elips anElips(gp_Ax2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), aMajor, aMinor); - occ::handle anEllipse = new Geom_Ellipse(anElips); - GeomProp_Curve aProp(anEllipse); - - const double aExpected = aMajor / (aMinor * aMinor); - const GeomProp::CurvatureResult aCurv = aProp.Curvature(0.0, THE_LIN_TOL); - ASSERT_TRUE(aCurv.IsDefined); - EXPECT_NEAR(aCurv.Value, aExpected, THE_CURV_TOL); -} - -TEST(GeomProp_EllipseTest, Curvature_AtMinorVertex) -{ - // At t=PI/2 (minor vertex): k = a*b / a^3 = b / a^2 - const double aMajor = 10.0; - const double aMinor = 5.0; - gp_Elips anElips(gp_Ax2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), aMajor, aMinor); - occ::handle anEllipse = new Geom_Ellipse(anElips); - GeomProp_Curve aProp(anEllipse); - - const double aExpected = aMinor / (aMajor * aMajor); - const GeomProp::CurvatureResult aCurv = aProp.Curvature(M_PI / 2.0, THE_LIN_TOL); - ASSERT_TRUE(aCurv.IsDefined); - EXPECT_NEAR(aCurv.Value, aExpected, THE_CURV_TOL); -} - -TEST(GeomProp_EllipseTest, Curvature_Symmetry) -{ - // k(t) = k(-t) = k(PI - t) for an ellipse centered at origin. - const double aMajor = 10.0; - const double aMinor = 5.0; - gp_Elips anElips(gp_Ax2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), aMajor, aMinor); - occ::handle anEllipse = new Geom_Ellipse(anElips); - GeomProp_Curve aProp(anEllipse); - - const double aTestParams[] = {0.3, 0.7, 1.1, 1.5}; - for (const double aT : aTestParams) - { - const GeomProp::CurvatureResult aCurvT = aProp.Curvature(aT, THE_LIN_TOL); - const GeomProp::CurvatureResult aCurvNegT = aProp.Curvature(-aT, THE_LIN_TOL); - const GeomProp::CurvatureResult aCurvPiT = aProp.Curvature(M_PI - aT, THE_LIN_TOL); - ASSERT_TRUE(aCurvT.IsDefined); - ASSERT_TRUE(aCurvNegT.IsDefined); - ASSERT_TRUE(aCurvPiT.IsDefined); - EXPECT_NEAR(aCurvT.Value, aCurvNegT.Value, THE_CURV_TOL) << "k(t) != k(-t) at t=" << aT; - EXPECT_NEAR(aCurvT.Value, aCurvPiT.Value, THE_CURV_TOL) << "k(t) != k(PI-t) at t=" << aT; - } -} - -TEST(GeomProp_EllipseTest, Tangent_AtMajorVertex) -{ - // At param=0, point is (a,0,0), tangent should be along Y: (0,1,0). - gp_Elips anElips(gp_Ax2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), 10.0, 5.0); - occ::handle anEllipse = new Geom_Ellipse(anElips); - GeomProp_Curve aProp(anEllipse); - - const GeomProp::TangentResult aTan = aProp.Tangent(0.0, THE_LIN_TOL); - ASSERT_TRUE(aTan.IsDefined); - EXPECT_NEAR(aTan.Direction.X(), 0.0, THE_DIR_TOL); - EXPECT_NEAR(std::abs(aTan.Direction.Y()), 1.0, THE_DIR_TOL); - EXPECT_NEAR(aTan.Direction.Z(), 0.0, THE_DIR_TOL); -} - -TEST(GeomProp_EllipseTest, Tangent_AtMinorVertex) -{ - // At param=PI/2, point is (0,b,0), tangent should be along -X: (-1,0,0). - gp_Elips anElips(gp_Ax2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), 10.0, 5.0); - occ::handle anEllipse = new Geom_Ellipse(anElips); - GeomProp_Curve aProp(anEllipse); - - const GeomProp::TangentResult aTan = aProp.Tangent(M_PI / 2.0, THE_LIN_TOL); - ASSERT_TRUE(aTan.IsDefined); - EXPECT_NEAR(std::abs(aTan.Direction.X()), 1.0, THE_DIR_TOL); - EXPECT_NEAR(aTan.Direction.Y(), 0.0, THE_DIR_TOL); - EXPECT_NEAR(aTan.Direction.Z(), 0.0, THE_DIR_TOL); -} - -TEST(GeomProp_EllipseTest, Normal_AtMajorVertex) -{ - // At param=0, normal should point from (a,0,0) toward center (0,0,0): (-1,0,0). - gp_Elips anElips(gp_Ax2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), 10.0, 5.0); - occ::handle anEllipse = new Geom_Ellipse(anElips); - GeomProp_Curve aProp(anEllipse); - - const GeomProp::NormalResult aNorm = aProp.Normal(0.0, THE_LIN_TOL); - ASSERT_TRUE(aNorm.IsDefined); - EXPECT_NEAR(aNorm.Direction.X(), -1.0, THE_DIR_TOL); - EXPECT_NEAR(aNorm.Direction.Y(), 0.0, THE_DIR_TOL); - EXPECT_NEAR(aNorm.Direction.Z(), 0.0, THE_DIR_TOL); -} - -TEST(GeomProp_EllipseTest, Normal_AtMinorVertex) -{ - // At param=PI/2, normal should point from (0,b,0) toward center: (0,-1,0). - gp_Elips anElips(gp_Ax2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), 10.0, 5.0); - occ::handle anEllipse = new Geom_Ellipse(anElips); - GeomProp_Curve aProp(anEllipse); - - const GeomProp::NormalResult aNorm = aProp.Normal(M_PI / 2.0, THE_LIN_TOL); - ASSERT_TRUE(aNorm.IsDefined); - EXPECT_NEAR(aNorm.Direction.X(), 0.0, THE_DIR_TOL); - EXPECT_NEAR(aNorm.Direction.Y(), -1.0, THE_DIR_TOL); - EXPECT_NEAR(aNorm.Direction.Z(), 0.0, THE_DIR_TOL); -} - -TEST(GeomProp_EllipseTest, Centre_AtMajorVertex) -{ - // At t=0, radius of curvature R = b^2/a. Centre = point + R * normal = (a - b^2/a, 0, 0). - const double aMajor = 10.0; - const double aMinor = 5.0; - gp_Elips anElips(gp_Ax2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), aMajor, aMinor); - occ::handle anEllipse = new Geom_Ellipse(anElips); - GeomProp_Curve aProp(anEllipse); - - const double aRoc = aMinor * aMinor / aMajor; // b^2/a - const double aExpX = aMajor - aRoc; // a - b^2/a - const GeomProp::CentreResult aCentre = aProp.CentreOfCurvature(0.0, THE_LIN_TOL); - ASSERT_TRUE(aCentre.IsDefined); - EXPECT_NEAR(aCentre.Centre.X(), aExpX, THE_POINT_TOL); - EXPECT_NEAR(aCentre.Centre.Y(), 0.0, THE_POINT_TOL); - EXPECT_NEAR(aCentre.Centre.Z(), 0.0, THE_POINT_TOL); -} - -TEST(GeomProp_EllipseTest, Centre_AtMinorVertex) -{ - // At t=PI/2, radius of curvature R = a^2/b. Centre = (0, b - a^2/b, 0). - const double aMajor = 10.0; - const double aMinor = 5.0; - gp_Elips anElips(gp_Ax2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), aMajor, aMinor); - occ::handle anEllipse = new Geom_Ellipse(anElips); - GeomProp_Curve aProp(anEllipse); - - const double aRoc = aMajor * aMajor / aMinor; // a^2/b - const double aExpY = aMinor - aRoc; // b - a^2/b - const GeomProp::CentreResult aCentre = aProp.CentreOfCurvature(M_PI / 2.0, THE_LIN_TOL); - ASSERT_TRUE(aCentre.IsDefined); - EXPECT_NEAR(aCentre.Centre.X(), 0.0, THE_POINT_TOL); - EXPECT_NEAR(aCentre.Centre.Y(), aExpY, THE_POINT_TOL); - EXPECT_NEAR(aCentre.Centre.Z(), 0.0, THE_POINT_TOL); -} - -TEST(GeomProp_EllipseTest, FindCurvatureExtrema_FourPoints) -{ - gp_Elips anElips(gp_Ax2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), 10.0, 5.0); - occ::handle anEllipse = new Geom_Ellipse(anElips); - GeomProp_Curve aProp(anEllipse); - - const GeomProp::CurveAnalysis aResult = aProp.FindCurvatureExtrema(); - ASSERT_TRUE(aResult.IsDone); - EXPECT_EQ(aResult.Points.Length(), 4); - - // Verify parameters are at approximately 0, PI/2, PI, 3*PI/2. - const double aExpected[] = {0.0, M_PI / 2.0, M_PI, 3.0 * M_PI / 2.0}; - for (int i = 0; i < 4; ++i) - { - EXPECT_NEAR(aResult.Points[i].Parameter, aExpected[i], 1.0e-6) - << "Extremum parameter mismatch at index " << i; - } -} - -TEST(GeomProp_EllipseTest, FindInflections_Empty) -{ - gp_Elips anElips(gp_Ax2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), 10.0, 5.0); - occ::handle anEllipse = new Geom_Ellipse(anElips); - GeomProp_Curve aProp(anEllipse); - - const GeomProp::CurveAnalysis aResult = aProp.FindInflections(); - ASSERT_TRUE(aResult.IsDone); - EXPECT_EQ(aResult.Points.Length(), 0); -} - -TEST(GeomProp_EllipseTest, GetType_IsEllipse) -{ - gp_Elips anElips(gp_Ax2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), 10.0, 5.0); - occ::handle anEllipse = new Geom_Ellipse(anElips); - GeomProp_Curve aProp(anEllipse); - - EXPECT_EQ(aProp.GetType(), GeomAbs_Ellipse); -} - -TEST(GeomProp_EllipseTest, Curvature_HighEccentricity) -{ - // Very elongated ellipse: a=100, b=1. - const double aMajor = 100.0; - const double aMinor = 1.0; - gp_Elips anElips(gp_Ax2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), aMajor, aMinor); - occ::handle anEllipse = new Geom_Ellipse(anElips); - GeomProp_Curve aProp(anEllipse); - - // At major vertex: k = a/b^2 = 100 - const GeomProp::CurvatureResult aCurvMajor = aProp.Curvature(0.0, THE_LIN_TOL); - ASSERT_TRUE(aCurvMajor.IsDefined); - EXPECT_NEAR(aCurvMajor.Value, aMajor / (aMinor * aMinor), THE_CURV_TOL); - - // At minor vertex: k = b/a^2 = 0.0001 - const GeomProp::CurvatureResult aCurvMinor = aProp.Curvature(M_PI / 2.0, THE_LIN_TOL); - ASSERT_TRUE(aCurvMinor.IsDefined); - EXPECT_NEAR(aCurvMinor.Value, aMinor / (aMajor * aMajor), THE_CURV_TOL); -} - -TEST(GeomProp_EllipseTest, Curvature_NearlyCircular) -{ - // Nearly circular: a=5, b=4.99. - const double aMajor = 5.0; - const double aMinor = 4.99; - gp_Elips anElips(gp_Ax2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), aMajor, aMinor); - occ::handle anEllipse = new Geom_Ellipse(anElips); - GeomProp_Curve aProp(anEllipse); - - const GeomProp::CurvatureResult aCurvMajor = aProp.Curvature(0.0, THE_LIN_TOL); - const GeomProp::CurvatureResult aCurvMinor = aProp.Curvature(M_PI / 2.0, THE_LIN_TOL); - ASSERT_TRUE(aCurvMajor.IsDefined); - ASSERT_TRUE(aCurvMinor.IsDefined); - - // When nearly circular, curvatures at both vertices should be close to 1/R ~ 0.2. - EXPECT_NEAR(aCurvMajor.Value, aMajor / (aMinor * aMinor), THE_CURV_TOL); - EXPECT_NEAR(aCurvMinor.Value, aMinor / (aMajor * aMajor), THE_CURV_TOL); - - // Difference should be small. - EXPECT_LT(std::abs(aCurvMajor.Value - aCurvMinor.Value), 0.01); -} - -TEST(GeomProp_EllipseTest, Curvature_MonotonicBetweenExtrema) -{ - // Curvature should be monotonically decreasing from major vertex (t=0) - // to minor vertex (t=PI/2) since max curvature is at major vertex. - const double aMajor = 10.0; - const double aMinor = 5.0; - gp_Elips anElips(gp_Ax2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), aMajor, aMinor); - occ::handle anEllipse = new Geom_Ellipse(anElips); - GeomProp_Curve aProp(anEllipse); - - double aPrevCurv = 0.0; - for (int i = 0; i <= 20; ++i) - { - const double aParam = i * M_PI / (2.0 * 20); - const GeomProp::CurvatureResult aCurv = aProp.Curvature(aParam, THE_LIN_TOL); - ASSERT_TRUE(aCurv.IsDefined); - if (i > 0) - { - EXPECT_LE(aCurv.Value, aPrevCurv + THE_CURV_TOL) - << "Curvature not monotonically decreasing at param=" << aParam; - } - aPrevCurv = aCurv.Value; - } -} - -// ============================================================================ -// Cross-validation tests vs GeomLProp_CLProps -// ============================================================================ - -TEST(GeomProp_EllipseTest, VsCLProps_Standard) -{ - gp_Elips anElips(gp_Ax2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), 10.0, 5.0); - occ::handle anEllipse = new Geom_Ellipse(anElips); - compareAll(anEllipse, 0.0, 2.0 * M_PI, 20); -} - -TEST(GeomProp_EllipseTest, VsCLProps_HighEccentricity) -{ - gp_Elips anElips(gp_Ax2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), 100.0, 1.0); - occ::handle anEllipse = new Geom_Ellipse(anElips); - compareAll(anEllipse, 0.0, 2.0 * M_PI); -} - -TEST(GeomProp_EllipseTest, VsCLProps_AllProperties) -{ - gp_Elips anElips(gp_Ax2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), 8.0, 3.0); - occ::handle anEllipse = new Geom_Ellipse(anElips); - compareAll(anEllipse, 0.0, 2.0 * M_PI, 40); -} - -TEST(GeomProp_EllipseTest, VsCLProps_OffCenter) -{ - gp_Elips anElips(gp_Ax2(gp_Pnt(5, 10, 15), gp_Dir(0, 0, 1)), 10.0, 5.0); - occ::handle anEllipse = new Geom_Ellipse(anElips); - compareAll(anEllipse, 0.0, 2.0 * M_PI); -} - -TEST(GeomProp_EllipseTest, VsCLProps_TiltedPlane) -{ - // Ellipse in a tilted plane with axis not along Z. - const gp_Dir anAxis(1, 1, 1); - gp_Elips anElips(gp_Ax2(gp_Pnt(0, 0, 0), anAxis), 10.0, 5.0); - occ::handle anEllipse = new Geom_Ellipse(anElips); - compareAll(anEllipse, 0.0, 2.0 * M_PI); -} - -TEST(GeomProp_EllipseTest, Curvature_MatchesAnalytical) -{ - // Verify curvature against the analytical formula at several params. - const double aMajor = 10.0; - const double aMinor = 5.0; - gp_Elips anElips(gp_Ax2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), aMajor, aMinor); - occ::handle anEllipse = new Geom_Ellipse(anElips); - GeomProp_Curve aProp(anEllipse); - - for (int i = 0; i <= 20; ++i) - { - const double aParam = i * 2.0 * M_PI / 20.0; - const double aExpected = ellipseCurvature(aMajor, aMinor, aParam); - const GeomProp::CurvatureResult aCurv = aProp.Curvature(aParam, THE_LIN_TOL); - ASSERT_TRUE(aCurv.IsDefined) << "Curvature undefined at param=" << aParam; - EXPECT_NEAR(aCurv.Value, aExpected, THE_CURV_TOL) - << "Curvature mismatch vs analytical at param=" << aParam; - } -} - -TEST(GeomProp_EllipseTest, VsCLProps_CriticalPoints) -{ - gp_Elips anElips(gp_Ax2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), 10.0, 3.0); - occ::handle anEllipse = new Geom_Ellipse(anElips); - const double aParams[] = {0.0, - 1.0e-10, - -1.0e-10, - M_PI / 2.0, - M_PI / 2.0 + 1.0e-10, - M_PI / 2.0 - 1.0e-10, - M_PI, - M_PI + 1.0e-6, - 3.0 * M_PI / 2.0, - 3.0 * M_PI / 2.0 + 1.0e-6, - M_PI / 4.0, - 3.0 * M_PI / 4.0, - 2.0 * M_PI - 1.0e-10}; - for (const double aParam : aParams) - { - compareTangent(anEllipse, aParam); - compareCurvature(anEllipse, aParam); - compareNormal(anEllipse, aParam); - compareCentre(anEllipse, aParam); - } -} diff --git a/src/ModelingData/TKG3d/GTests/GeomProp_Hyperbola_Test.cxx b/src/ModelingData/TKG3d/GTests/GeomProp_Hyperbola_Test.cxx deleted file mode 100644 index d3f5857e6b..0000000000 --- a/src/ModelingData/TKG3d/GTests/GeomProp_Hyperbola_Test.cxx +++ /dev/null @@ -1,429 +0,0 @@ -// 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. - -// Tests for GeomProp_Curve with Geom_Hyperbola curves. -// Validates curvature, tangent, normal, and centre of curvature properties -// against analytical formulas and cross-validates against GeomLProp_CLProps. - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -namespace -{ -constexpr double THE_LIN_TOL = Precision::PConfusion(); -constexpr double THE_CURV_TOL = 1.0e-8; -constexpr double THE_DIR_TOL = 1.0e-6; -constexpr double THE_POINT_TOL = 1.0e-6; - -//! Compare tangent from new GeomProp_Curve vs old GeomLProp_CLProps. -void compareTangent(const occ::handle& theCurve, const double theParam) -{ - GeomProp_Curve aProp(theCurve); - const GeomProp::TangentResult aNew = aProp.Tangent(theParam, THE_LIN_TOL); - - GeomLProp_CLProps anOld(theCurve, theParam, 2, THE_LIN_TOL); - if (anOld.IsTangentDefined()) - { - ASSERT_TRUE(aNew.IsDefined) << "New tangent undefined but old is defined at param=" << theParam; - gp_Dir anOldDir; - anOld.Tangent(anOldDir); - const double aDot = aNew.Direction.Dot(anOldDir); - EXPECT_NEAR(std::abs(aDot), 1.0, THE_DIR_TOL) - << "Tangent direction mismatch at param=" << theParam; - } -} - -//! Compare curvature from new GeomProp_Curve vs old GeomLProp_CLProps. -void compareCurvature(const occ::handle& theCurve, const double theParam) -{ - GeomProp_Curve aProp(theCurve); - const GeomProp::CurvatureResult aNew = aProp.Curvature(theParam, THE_LIN_TOL); - - GeomLProp_CLProps anOld(theCurve, theParam, 2, THE_LIN_TOL); - if (anOld.IsTangentDefined()) - { - ASSERT_TRUE(aNew.IsDefined) << "New curvature undefined at param=" << theParam; - EXPECT_NEAR(aNew.Value, anOld.Curvature(), THE_CURV_TOL) - << "Curvature mismatch at param=" << theParam; - } -} - -//! Compare normal from new GeomProp_Curve vs old GeomLProp_CLProps. -void compareNormal(const occ::handle& theCurve, const double theParam) -{ - GeomProp_Curve aProp(theCurve); - const GeomProp::NormalResult aNew = aProp.Normal(theParam, THE_LIN_TOL); - - GeomLProp_CLProps anOld(theCurve, theParam, 2, THE_LIN_TOL); - if (anOld.IsTangentDefined() && std::abs(anOld.Curvature()) > THE_LIN_TOL) - { - ASSERT_TRUE(aNew.IsDefined) << "New normal undefined at param=" << theParam; - gp_Dir anOldNorm; - anOld.Normal(anOldNorm); - const double aDot = aNew.Direction.Dot(anOldNorm); - EXPECT_NEAR(std::abs(aDot), 1.0, THE_DIR_TOL) - << "Normal direction mismatch at param=" << theParam; - } -} - -//! Compare centre of curvature from new vs old. -void compareCentre(const occ::handle& theCurve, const double theParam) -{ - GeomProp_Curve aProp(theCurve); - const GeomProp::CentreResult aNew = aProp.CentreOfCurvature(theParam, THE_LIN_TOL); - - GeomLProp_CLProps anOld(theCurve, theParam, 2, THE_LIN_TOL); - if (anOld.IsTangentDefined() && std::abs(anOld.Curvature()) > THE_LIN_TOL) - { - ASSERT_TRUE(aNew.IsDefined) << "New centre undefined at param=" << theParam; - gp_Pnt anOldCentre; - anOld.CentreOfCurvature(anOldCentre); - EXPECT_NEAR(aNew.Centre.Distance(anOldCentre), 0.0, THE_POINT_TOL) - << "Centre mismatch at param=" << theParam; - } -} - -//! Run all comparisons at several parameter values. -void compareAll(const occ::handle& theCurve, - const double theFirst, - const double theLast, - const int theNbSamples = 10) -{ - const double aStep = (theLast - theFirst) / theNbSamples; - for (int i = 0; i <= theNbSamples; ++i) - { - const double aParam = theFirst + i * aStep; - compareTangent(theCurve, aParam); - compareCurvature(theCurve, aParam); - compareNormal(theCurve, aParam); - compareCentre(theCurve, aParam); - } -} -} // namespace - -// Curvature at vertex (t=0): k = a / b^2 -TEST(GeomProp_HyperbolaTest, Curvature_AtVertex) -{ - const double aA = 6.0; - const double aB = 3.0; - gp_Hypr anHypr(gp_Ax2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), aA, aB); - occ::handle aHyperbola = new Geom_Hyperbola(anHypr); - GeomProp_Curve aProp(aHyperbola); - const GeomProp::CurvatureResult aCurv = aProp.Curvature(0.0, THE_LIN_TOL); - ASSERT_TRUE(aCurv.IsDefined); - const double aExpected = aA / (aB * aB); - EXPECT_NEAR(aCurv.Value, aExpected, THE_CURV_TOL); -} - -// Curvature is symmetric: k(t) = k(-t) -TEST(GeomProp_HyperbolaTest, Curvature_Symmetric) -{ - gp_Hypr anHypr(gp_Ax2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), 6.0, 3.0); - occ::handle aHyperbola = new Geom_Hyperbola(anHypr); - GeomProp_Curve aProp(aHyperbola); - - for (double aT = 0.1; aT <= 2.0; aT += 0.3) - { - const GeomProp::CurvatureResult aPos = aProp.Curvature(aT, THE_LIN_TOL); - const GeomProp::CurvatureResult aNeg = aProp.Curvature(-aT, THE_LIN_TOL); - ASSERT_TRUE(aPos.IsDefined); - ASSERT_TRUE(aNeg.IsDefined); - EXPECT_NEAR(aPos.Value, aNeg.Value, THE_CURV_TOL) << "Asymmetry at t=" << aT; - } -} - -// Curvature decreases from vertex as |t| increases -TEST(GeomProp_HyperbolaTest, Curvature_DecreasesFromVertex) -{ - gp_Hypr anHypr(gp_Ax2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), 6.0, 3.0); - occ::handle aHyperbola = new Geom_Hyperbola(anHypr); - GeomProp_Curve aProp(aHyperbola); - - const GeomProp::CurvatureResult aCurvVertex = aProp.Curvature(0.0, THE_LIN_TOL); - ASSERT_TRUE(aCurvVertex.IsDefined); - - double aPrevCurv = aCurvVertex.Value; - for (double aT = 0.5; aT <= 3.0; aT += 0.5) - { - const GeomProp::CurvatureResult aCurv = aProp.Curvature(aT, THE_LIN_TOL); - ASSERT_TRUE(aCurv.IsDefined); - EXPECT_LT(aCurv.Value, aPrevCurv) << "Curvature did not decrease at t=" << aT; - aPrevCurv = aCurv.Value; - } -} - -// Tangent at vertex is perpendicular to real axis -TEST(GeomProp_HyperbolaTest, Tangent_AtVertex) -{ - gp_Ax2 anAx2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)); - gp_Hypr anHypr(anAx2, 6.0, 3.0); - occ::handle aHyperbola = new Geom_Hyperbola(anHypr); - GeomProp_Curve aProp(aHyperbola); - - const GeomProp::TangentResult aTan = aProp.Tangent(0.0, THE_LIN_TOL); - ASSERT_TRUE(aTan.IsDefined); - // Real axis is X direction of the coordinate system - const gp_Dir aRealAxis = anAx2.XDirection(); - EXPECT_NEAR(std::abs(aTan.Direction.Dot(aRealAxis)), 0.0, THE_DIR_TOL); -} - -// Tangent direction is symmetric about vertex -TEST(GeomProp_HyperbolaTest, Tangent_Symmetric) -{ - gp_Hypr anHypr(gp_Ax2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), 6.0, 3.0); - occ::handle aHyperbola = new Geom_Hyperbola(anHypr); - GeomProp_Curve aProp(aHyperbola); - - for (double aT = 0.2; aT <= 2.0; aT += 0.3) - { - const GeomProp::TangentResult aTanPos = aProp.Tangent(aT, THE_LIN_TOL); - const GeomProp::TangentResult aTanNeg = aProp.Tangent(-aT, THE_LIN_TOL); - ASSERT_TRUE(aTanPos.IsDefined); - ASSERT_TRUE(aTanNeg.IsDefined); - // Symmetric tangent: Y-component flips sign, X-component stays the same - // Check that the X-components have the same magnitude - EXPECT_NEAR(std::abs(aTanPos.Direction.X()), std::abs(aTanNeg.Direction.X()), THE_DIR_TOL) - << "Tangent X asymmetry at t=" << aT; - } -} - -// Normal at vertex is along real axis toward center -TEST(GeomProp_HyperbolaTest, Normal_AtVertex) -{ - gp_Ax2 anAx2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)); - gp_Hypr anHypr(anAx2, 6.0, 3.0); - occ::handle aHyperbola = new Geom_Hyperbola(anHypr); - GeomProp_Curve aProp(aHyperbola); - - const GeomProp::NormalResult aNorm = aProp.Normal(0.0, THE_LIN_TOL); - ASSERT_TRUE(aNorm.IsDefined); - // Normal at vertex should be along the real axis (X direction) - const gp_Dir aRealAxis = anAx2.XDirection(); - EXPECT_NEAR(std::abs(aNorm.Direction.Dot(aRealAxis)), 1.0, THE_DIR_TOL); -} - -// Centre at vertex is at distance 1/k from vertex along normal -TEST(GeomProp_HyperbolaTest, Centre_AtVertex) -{ - const double aA = 6.0; - const double aB = 3.0; - gp_Hypr anHypr(gp_Ax2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), aA, aB); - occ::handle aHyperbola = new Geom_Hyperbola(anHypr); - GeomProp_Curve aProp(aHyperbola); - - const GeomProp::CentreResult aCentre = aProp.CentreOfCurvature(0.0, THE_LIN_TOL); - const GeomProp::CurvatureResult aCurv = aProp.Curvature(0.0, THE_LIN_TOL); - ASSERT_TRUE(aCentre.IsDefined); - ASSERT_TRUE(aCurv.IsDefined); - - // Vertex is at (a, 0, 0); centre should be at distance 1/k from vertex - gp_Pnt aVertex; - aHyperbola->D0(0.0, aVertex); - const double aRadius = 1.0 / aCurv.Value; - EXPECT_NEAR(aCentre.Centre.Distance(aVertex), std::abs(aRadius), THE_POINT_TOL); -} - -// FindCurvatureExtrema returns 1 extremum at t=0 -TEST(GeomProp_HyperbolaTest, FindCurvatureExtrema_OnePoint) -{ - gp_Hypr anHypr(gp_Ax2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), 6.0, 3.0); - occ::handle aHyperbola = new Geom_Hyperbola(anHypr); - GeomProp_Curve aProp(aHyperbola); - - const GeomProp::CurveAnalysis aResult = aProp.FindCurvatureExtrema(); - ASSERT_TRUE(aResult.IsDone); - EXPECT_EQ(aResult.Points.Length(), 1); - EXPECT_NEAR(aResult.Points[0].Parameter, 0.0, Precision::Confusion()); -} - -// FindInflections returns no inflections -TEST(GeomProp_HyperbolaTest, FindInflections_Empty) -{ - gp_Hypr anHypr(gp_Ax2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), 6.0, 3.0); - occ::handle aHyperbola = new Geom_Hyperbola(anHypr); - GeomProp_Curve aProp(aHyperbola); - - const GeomProp::CurveAnalysis aResult = aProp.FindInflections(); - ASSERT_TRUE(aResult.IsDone); - EXPECT_EQ(aResult.Points.Length(), 0); -} - -// GetType returns GeomAbs_Hyperbola -TEST(GeomProp_HyperbolaTest, GetType_IsHyperbola) -{ - gp_Hypr anHypr(gp_Ax2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), 6.0, 3.0); - occ::handle aHyperbola = new Geom_Hyperbola(anHypr); - GeomProp_Curve aProp(aHyperbola); - EXPECT_EQ(aProp.GetType(), GeomAbs_Hyperbola); -} - -// Curvature approaches 0 for large |t| -TEST(GeomProp_HyperbolaTest, Curvature_LargeParam) -{ - gp_Hypr anHypr(gp_Ax2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), 6.0, 3.0); - occ::handle aHyperbola = new Geom_Hyperbola(anHypr); - GeomProp_Curve aProp(aHyperbola); - - const GeomProp::CurvatureResult aCurv = aProp.Curvature(10.0, THE_LIN_TOL); - ASSERT_TRUE(aCurv.IsDefined); - EXPECT_LT(aCurv.Value, 0.01); -} - -// Cross-validate vs CLProps: standard axes a=6, b=3 -TEST(GeomProp_HyperbolaTest, VsCLProps_Standard) -{ - gp_Hypr anHypr(gp_Ax2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), 6.0, 3.0); - occ::handle aHyperbola = new Geom_Hyperbola(anHypr); - compareAll(aHyperbola, -2.0, 2.0); -} - -// Dense cross-validation on [-2, 2] -TEST(GeomProp_HyperbolaTest, VsCLProps_AllProperties) -{ - gp_Hypr anHypr(gp_Ax2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), 6.0, 3.0); - occ::handle aHyperbola = new Geom_Hyperbola(anHypr); - compareAll(aHyperbola, -2.0, 2.0, 20); -} - -// Cross-validate with large semi-axes -TEST(GeomProp_HyperbolaTest, VsCLProps_LargeAxes) -{ - gp_Hypr anHypr(gp_Ax2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), 100.0, 50.0); - occ::handle aHyperbola = new Geom_Hyperbola(anHypr); - compareAll(aHyperbola, -1.0, 1.0); -} - -// Cross-validate with small semi-axes -TEST(GeomProp_HyperbolaTest, VsCLProps_SmallAxes) -{ - gp_Hypr anHypr(gp_Ax2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), 0.5, 0.3); - occ::handle aHyperbola = new Geom_Hyperbola(anHypr); - compareAll(aHyperbola, -2.0, 2.0); -} - -// Cross-validate with asymmetric semi-axes (a >> b) -TEST(GeomProp_HyperbolaTest, VsCLProps_AsymmetricAxes) -{ - gp_Hypr anHypr(gp_Ax2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), 10.0, 1.0); - occ::handle aHyperbola = new Geom_Hyperbola(anHypr); - compareAll(aHyperbola, -2.0, 2.0); -} - -// Fine-grained curvature near vertex -TEST(GeomProp_HyperbolaTest, Curvature_NearVertex) -{ - const double aA = 6.0; - const double aB = 3.0; - gp_Hypr anHypr(gp_Ax2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), aA, aB); - occ::handle aHyperbola = new Geom_Hyperbola(anHypr); - GeomProp_Curve aProp(aHyperbola); - - const double aExpectedMax = aA / (aB * aB); - for (double aT = 0.01; aT <= 0.1; aT += 0.01) - { - const GeomProp::CurvatureResult aCurv = aProp.Curvature(aT, THE_LIN_TOL); - ASSERT_TRUE(aCurv.IsDefined); - EXPECT_LT(aCurv.Value, aExpectedMax + THE_CURV_TOL) - << "Curvature exceeds vertex maximum at t=" << aT; - } -} - -// Tangent far from vertex approaches asymptote direction -TEST(GeomProp_HyperbolaTest, Tangent_FarFromVertex) -{ - const double aA = 6.0; - const double aB = 3.0; - gp_Ax2 anAx2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)); - gp_Hypr anHypr(anAx2, aA, aB); - occ::handle aHyperbola = new Geom_Hyperbola(anHypr); - GeomProp_Curve aProp(aHyperbola); - - // For large t, the asymptote direction is (a*sinh(t), b*cosh(t), 0) -> (a, b, 0) normalized - const gp_Dir aAsymptote(aA, aB, 0.0); - - const GeomProp::TangentResult aTan = aProp.Tangent(10.0, THE_LIN_TOL); - ASSERT_TRUE(aTan.IsDefined); - EXPECT_NEAR(std::abs(aTan.Direction.Dot(aAsymptote)), 1.0, 1.0e-4); -} - -// Cross-validate with off-center hyperbola -TEST(GeomProp_HyperbolaTest, VsCLProps_OffCenter) -{ - gp_Hypr anHypr(gp_Ax2(gp_Pnt(5.0, 5.0, 5.0), gp_Dir(0, 0, 1)), 6.0, 3.0); - occ::handle aHyperbola = new Geom_Hyperbola(anHypr); - compareAll(aHyperbola, -2.0, 2.0); -} - -// Centre of curvature moves away from vertex as |t| increases -TEST(GeomProp_HyperbolaTest, Centre_MovesAwayFromVertex) -{ - gp_Hypr anHypr(gp_Ax2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), 6.0, 3.0); - occ::handle aHyperbola = new Geom_Hyperbola(anHypr); - GeomProp_Curve aProp(aHyperbola); - - gp_Pnt aVertex; - aHyperbola->D0(0.0, aVertex); - - const GeomProp::CentreResult aCentreAtVertex = aProp.CentreOfCurvature(0.0, THE_LIN_TOL); - ASSERT_TRUE(aCentreAtVertex.IsDefined); - - double aPrevDist = aCentreAtVertex.Centre.Distance(aVertex); - for (double aT = 0.5; aT <= 2.5; aT += 0.5) - { - const GeomProp::CentreResult aCentre = aProp.CentreOfCurvature(aT, THE_LIN_TOL); - ASSERT_TRUE(aCentre.IsDefined); - const double aDist = aCentre.Centre.Distance(aVertex); - EXPECT_GT(aDist, aPrevDist - THE_POINT_TOL) - << "Centre did not move away from vertex at t=" << aT; - aPrevDist = aDist; - } -} - -TEST(GeomProp_HyperbolaTest, VsCLProps_CriticalPoints) -{ - gp_Hypr aHypr(gp_Ax2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), 5.0, 3.0); - occ::handle aHyperbola = new Geom_Hyperbola(aHypr); - const double aParams[] = {0.0, - 1.0e-10, - -1.0e-10, - 1.0e-6, - -1.0e-6, - 0.1, - -0.1, - 0.5, - -0.5, - 1.0, - -1.0, - 3.0, - -3.0, - 5.0, - -5.0}; - for (const double aParam : aParams) - { - compareTangent(aHyperbola, aParam); - compareCurvature(aHyperbola, aParam); - compareNormal(aHyperbola, aParam); - compareCentre(aHyperbola, aParam); - } -} diff --git a/src/ModelingData/TKG3d/GTests/GeomProp_Line_Test.cxx b/src/ModelingData/TKG3d/GTests/GeomProp_Line_Test.cxx deleted file mode 100644 index 5da8d1f576..0000000000 --- a/src/ModelingData/TKG3d/GTests/GeomProp_Line_Test.cxx +++ /dev/null @@ -1,398 +0,0 @@ -// 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. - -// Unit tests for GeomProp_Curve with Line geometry. - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -namespace -{ -constexpr double THE_LIN_TOL = Precision::PConfusion(); -constexpr double THE_CURV_TOL = 1.0e-8; -constexpr double THE_DIR_TOL = 1.0e-6; -constexpr double THE_POINT_TOL = 1.0e-6; - -//! Compare tangent from new GeomProp_Curve vs old GeomLProp_CLProps. -void compareTangent(const occ::handle& theCurve, const double theParam) -{ - GeomProp_Curve aProp(theCurve); - const GeomProp::TangentResult aNew = aProp.Tangent(theParam, THE_LIN_TOL); - - GeomLProp_CLProps anOld(theCurve, theParam, 2, THE_LIN_TOL); - if (anOld.IsTangentDefined()) - { - ASSERT_TRUE(aNew.IsDefined) << "New tangent undefined but old is defined at param=" << theParam; - gp_Dir anOldDir; - anOld.Tangent(anOldDir); - const double aDot = aNew.Direction.Dot(anOldDir); - EXPECT_NEAR(std::abs(aDot), 1.0, THE_DIR_TOL) - << "Tangent direction mismatch at param=" << theParam; - } -} - -//! Compare curvature from new GeomProp_Curve vs old GeomLProp_CLProps. -void compareCurvature(const occ::handle& theCurve, const double theParam) -{ - GeomProp_Curve aProp(theCurve); - const GeomProp::CurvatureResult aNew = aProp.Curvature(theParam, THE_LIN_TOL); - - GeomLProp_CLProps anOld(theCurve, theParam, 2, THE_LIN_TOL); - if (anOld.IsTangentDefined()) - { - ASSERT_TRUE(aNew.IsDefined) << "New curvature undefined at param=" << theParam; - EXPECT_NEAR(aNew.Value, anOld.Curvature(), THE_CURV_TOL) - << "Curvature mismatch at param=" << theParam; - } -} - -//! Compare normal from new GeomProp_Curve vs old GeomLProp_CLProps. -void compareNormal(const occ::handle& theCurve, const double theParam) -{ - GeomProp_Curve aProp(theCurve); - const GeomProp::NormalResult aNew = aProp.Normal(theParam, THE_LIN_TOL); - - GeomLProp_CLProps anOld(theCurve, theParam, 2, THE_LIN_TOL); - if (anOld.IsTangentDefined() && std::abs(anOld.Curvature()) > THE_LIN_TOL) - { - ASSERT_TRUE(aNew.IsDefined) << "New normal undefined at param=" << theParam; - gp_Dir anOldNorm; - anOld.Normal(anOldNorm); - const double aDot = aNew.Direction.Dot(anOldNorm); - EXPECT_NEAR(std::abs(aDot), 1.0, THE_DIR_TOL) - << "Normal direction mismatch at param=" << theParam; - } -} - -//! Compare centre of curvature from new vs old. -void compareCentre(const occ::handle& theCurve, const double theParam) -{ - GeomProp_Curve aProp(theCurve); - const GeomProp::CentreResult aNew = aProp.CentreOfCurvature(theParam, THE_LIN_TOL); - - GeomLProp_CLProps anOld(theCurve, theParam, 2, THE_LIN_TOL); - if (anOld.IsTangentDefined() && std::abs(anOld.Curvature()) > THE_LIN_TOL) - { - ASSERT_TRUE(aNew.IsDefined) << "New centre undefined at param=" << theParam; - gp_Pnt anOldCentre; - anOld.CentreOfCurvature(anOldCentre); - EXPECT_NEAR(aNew.Centre.Distance(anOldCentre), 0.0, THE_POINT_TOL) - << "Centre mismatch at param=" << theParam; - } -} - -//! Run all comparisons at several parameter values. -void compareAll(const occ::handle& theCurve, - const double theFirst, - const double theLast, - const int theNbSamples = 10) -{ - const double aStep = (theLast - theFirst) / theNbSamples; - for (int i = 0; i <= theNbSamples; ++i) - { - const double aParam = theFirst + i * aStep; - compareTangent(theCurve, aParam); - compareCurvature(theCurve, aParam); - compareNormal(theCurve, aParam); - compareCentre(theCurve, aParam); - } -} -} // namespace - -// ============================================================================ -// Analytical reference tests -// ============================================================================ - -TEST(GeomProp_LineTest, Tangent_AlongX) -{ - occ::handle aLine = new Geom_Line(gp_Pnt(0, 0, 0), gp_Dir(1, 0, 0)); - GeomProp_Curve aProp(aLine); - - const GeomProp::TangentResult aTan = aProp.Tangent(0.0, THE_LIN_TOL); - ASSERT_TRUE(aTan.IsDefined); - EXPECT_NEAR(aTan.Direction.X(), 1.0, THE_DIR_TOL); - EXPECT_NEAR(aTan.Direction.Y(), 0.0, THE_DIR_TOL); - EXPECT_NEAR(aTan.Direction.Z(), 0.0, THE_DIR_TOL); -} - -TEST(GeomProp_LineTest, Tangent_AlongDiagonal) -{ - const double aInvSqrt3 = 1.0 / std::sqrt(3.0); - occ::handle aLine = new Geom_Line(gp_Pnt(0, 0, 0), gp_Dir(1, 1, 1)); - GeomProp_Curve aProp(aLine); - - const GeomProp::TangentResult aTan = aProp.Tangent(5.0, THE_LIN_TOL); - ASSERT_TRUE(aTan.IsDefined); - EXPECT_NEAR(aTan.Direction.X(), aInvSqrt3, THE_DIR_TOL); - EXPECT_NEAR(aTan.Direction.Y(), aInvSqrt3, THE_DIR_TOL); - EXPECT_NEAR(aTan.Direction.Z(), aInvSqrt3, THE_DIR_TOL); -} - -TEST(GeomProp_LineTest, Tangent_NegativeParam) -{ - occ::handle aLine = new Geom_Line(gp_Pnt(0, 0, 0), gp_Dir(0, 1, 0)); - GeomProp_Curve aProp(aLine); - - const GeomProp::TangentResult aTanPos = aProp.Tangent(3.0, THE_LIN_TOL); - const GeomProp::TangentResult aTanNeg = aProp.Tangent(-3.0, THE_LIN_TOL); - ASSERT_TRUE(aTanPos.IsDefined); - ASSERT_TRUE(aTanNeg.IsDefined); - const double aDot = aTanPos.Direction.Dot(aTanNeg.Direction); - EXPECT_NEAR(aDot, 1.0, THE_DIR_TOL); -} - -TEST(GeomProp_LineTest, Tangent_AtOrigin) -{ - occ::handle aLine = new Geom_Line(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)); - GeomProp_Curve aProp(aLine); - - const GeomProp::TangentResult aTan = aProp.Tangent(0.0, THE_LIN_TOL); - ASSERT_TRUE(aTan.IsDefined); - EXPECT_NEAR(aTan.Direction.Z(), 1.0, THE_DIR_TOL); -} - -TEST(GeomProp_LineTest, Curvature_IsZero) -{ - occ::handle aLine = new Geom_Line(gp_Pnt(0, 0, 0), gp_Dir(1, 0, 0)); - GeomProp_Curve aProp(aLine); - - const GeomProp::CurvatureResult aCurv = aProp.Curvature(1.0, THE_LIN_TOL); - ASSERT_TRUE(aCurv.IsDefined); - EXPECT_FALSE(aCurv.IsInfinite); - EXPECT_NEAR(aCurv.Value, 0.0, THE_CURV_TOL); -} - -TEST(GeomProp_LineTest, Curvature_MultipleParams) -{ - occ::handle aLine = new Geom_Line(gp_Pnt(0, 0, 0), gp_Dir(1, 0, 0)); - GeomProp_Curve aProp(aLine); - - const double aParams[] = {-10.0, -1.0, 0.0, 0.5, 1.0, 10.0, 100.0}; - for (const double aParam : aParams) - { - const GeomProp::CurvatureResult aCurv = aProp.Curvature(aParam, THE_LIN_TOL); - ASSERT_TRUE(aCurv.IsDefined) << "Curvature undefined at param=" << aParam; - EXPECT_NEAR(aCurv.Value, 0.0, THE_CURV_TOL) << "Non-zero curvature at param=" << aParam; - } -} - -TEST(GeomProp_LineTest, Normal_Undefined) -{ - occ::handle aLine = new Geom_Line(gp_Pnt(0, 0, 0), gp_Dir(1, 0, 0)); - GeomProp_Curve aProp(aLine); - - const GeomProp::NormalResult aNorm = aProp.Normal(0.5, THE_LIN_TOL); - EXPECT_FALSE(aNorm.IsDefined); -} - -TEST(GeomProp_LineTest, Centre_Undefined) -{ - occ::handle aLine = new Geom_Line(gp_Pnt(0, 0, 0), gp_Dir(1, 0, 0)); - GeomProp_Curve aProp(aLine); - - const GeomProp::CentreResult aCentre = aProp.CentreOfCurvature(0.5, THE_LIN_TOL); - EXPECT_FALSE(aCentre.IsDefined); -} - -TEST(GeomProp_LineTest, FindCurvatureExtrema_Empty) -{ - occ::handle aLine = new Geom_Line(gp_Pnt(0, 0, 0), gp_Dir(1, 0, 0)); - GeomProp_Curve aProp(aLine); - - const GeomProp::CurveAnalysis aResult = aProp.FindCurvatureExtrema(); - ASSERT_TRUE(aResult.IsDone); - EXPECT_EQ(aResult.Points.Length(), 0); -} - -TEST(GeomProp_LineTest, FindInflections_Empty) -{ - occ::handle aLine = new Geom_Line(gp_Pnt(0, 0, 0), gp_Dir(1, 0, 0)); - GeomProp_Curve aProp(aLine); - - const GeomProp::CurveAnalysis aResult = aProp.FindInflections(); - ASSERT_TRUE(aResult.IsDone); - EXPECT_EQ(aResult.Points.Length(), 0); -} - -TEST(GeomProp_LineTest, GetType_IsLine) -{ - occ::handle aLine = new Geom_Line(gp_Pnt(0, 0, 0), gp_Dir(1, 0, 0)); - GeomProp_Curve aProp(aLine); - - EXPECT_EQ(aProp.GetType(), GeomAbs_Line); -} - -TEST(GeomProp_LineTest, Line_OffCenter) -{ - occ::handle aLine = new Geom_Line(gp_Pnt(10, 20, 30), gp_Dir(1, 0, 0)); - GeomProp_Curve aProp(aLine); - - const GeomProp::TangentResult aTan = aProp.Tangent(5.0, THE_LIN_TOL); - ASSERT_TRUE(aTan.IsDefined); - EXPECT_NEAR(aTan.Direction.X(), 1.0, THE_DIR_TOL); - - const GeomProp::CurvatureResult aCurv = aProp.Curvature(5.0, THE_LIN_TOL); - ASSERT_TRUE(aCurv.IsDefined); - EXPECT_NEAR(aCurv.Value, 0.0, THE_CURV_TOL); - - const GeomProp::NormalResult aNorm = aProp.Normal(5.0, THE_LIN_TOL); - EXPECT_FALSE(aNorm.IsDefined); - - const GeomProp::CentreResult aCentre = aProp.CentreOfCurvature(5.0, THE_LIN_TOL); - EXPECT_FALSE(aCentre.IsDefined); -} - -TEST(GeomProp_LineTest, Line_ArbitraryDirection) -{ - const gp_Dir aDir(3, 4, 5); - occ::handle aLine = new Geom_Line(gp_Pnt(0, 0, 0), aDir); - GeomProp_Curve aProp(aLine); - - const GeomProp::TangentResult aTan = aProp.Tangent(2.5, THE_LIN_TOL); - ASSERT_TRUE(aTan.IsDefined); - const double aDot = aTan.Direction.Dot(aDir); - EXPECT_NEAR(std::abs(aDot), 1.0, THE_DIR_TOL); -} - -TEST(GeomProp_LineTest, Line_LargeParams) -{ - occ::handle aLine = new Geom_Line(gp_Pnt(0, 0, 0), gp_Dir(1, 0, 0)); - GeomProp_Curve aProp(aLine); - - for (const double aParam : {1000.0, -1000.0}) - { - const GeomProp::TangentResult aTan = aProp.Tangent(aParam, THE_LIN_TOL); - ASSERT_TRUE(aTan.IsDefined) << "Tangent undefined at param=" << aParam; - EXPECT_NEAR(aTan.Direction.X(), 1.0, THE_DIR_TOL); - - const GeomProp::CurvatureResult aCurv = aProp.Curvature(aParam, THE_LIN_TOL); - ASSERT_TRUE(aCurv.IsDefined) << "Curvature undefined at param=" << aParam; - EXPECT_NEAR(aCurv.Value, 0.0, THE_CURV_TOL); - } -} - -TEST(GeomProp_LineTest, Tangent_ConsistentSign) -{ - const gp_Dir aDir(0, 1, 0); - occ::handle aLine = new Geom_Line(gp_Pnt(0, 0, 0), aDir); - GeomProp_Curve aProp(aLine); - - // Tangent direction should be consistent with the line direction at all params. - for (const double aParam : {-5.0, 0.0, 5.0}) - { - const GeomProp::TangentResult aTan = aProp.Tangent(aParam, THE_LIN_TOL); - ASSERT_TRUE(aTan.IsDefined); - const double aDot = aTan.Direction.Dot(aDir); - EXPECT_NEAR(aDot, 1.0, THE_DIR_TOL) - << "Tangent sign inconsistent with line direction at param=" << aParam; - } -} - -TEST(GeomProp_LineTest, Curvature_ExactlyZero) -{ - occ::handle aLine = new Geom_Line(gp_Pnt(0, 0, 0), gp_Dir(1, 0, 0)); - GeomProp_Curve aProp(aLine); - - const GeomProp::CurvatureResult aCurv = aProp.Curvature(0.0, THE_LIN_TOL); - ASSERT_TRUE(aCurv.IsDefined); - EXPECT_EQ(aCurv.Value, 0.0); -} - -// ============================================================================ -// Cross-validation tests vs GeomLProp_CLProps -// ============================================================================ - -TEST(GeomProp_LineTest, VsCLProps_Tangent) -{ - occ::handle aLine = new Geom_Line(gp_Pnt(0, 0, 0), gp_Dir(1, 1, 0)); - - const double aStep = 1.0; - for (int i = 0; i <= 10; ++i) - { - const double aParam = -5.0 + i * aStep; - compareTangent(aLine, aParam); - } -} - -TEST(GeomProp_LineTest, VsCLProps_Curvature) -{ - occ::handle aLine = new Geom_Line(gp_Pnt(0, 0, 0), gp_Dir(1, 0, 0)); - - const double aStep = 1.0; - for (int i = 0; i <= 10; ++i) - { - const double aParam = -5.0 + i * aStep; - compareCurvature(aLine, aParam); - } -} - -TEST(GeomProp_LineTest, VsCLProps_AllProperties) -{ - occ::handle aLine = new Geom_Line(gp_Pnt(0, 0, 0), gp_Dir(1, 1, 1)); - compareAll(aLine, -5.0, 5.0, 20); -} - -TEST(GeomProp_LineTest, VsCLProps_OffCenter) -{ - occ::handle aLine = new Geom_Line(gp_Pnt(10, 20, 30), gp_Dir(3, 4, 5)); - compareAll(aLine, -10.0, 10.0); -} - -TEST(GeomProp_LineTest, Normal_Undefined_MultipleParams) -{ - occ::handle aLine = new Geom_Line(gp_Pnt(0, 0, 0), gp_Dir(1, 0, 0)); - GeomProp_Curve aProp(aLine); - - const double aParams[] = {-100.0, -1.0, 0.0, 1.0, 100.0}; - for (const double aParam : aParams) - { - const GeomProp::NormalResult aNorm = aProp.Normal(aParam, THE_LIN_TOL); - EXPECT_FALSE(aNorm.IsDefined) << "Normal should be undefined at param=" << aParam; - } -} - -TEST(GeomProp_LineTest, Centre_Undefined_MultipleParams) -{ - occ::handle aLine = new Geom_Line(gp_Pnt(0, 0, 0), gp_Dir(1, 0, 0)); - GeomProp_Curve aProp(aLine); - - const double aParams[] = {-100.0, -1.0, 0.0, 1.0, 100.0}; - for (const double aParam : aParams) - { - const GeomProp::CentreResult aCentre = aProp.CentreOfCurvature(aParam, THE_LIN_TOL); - EXPECT_FALSE(aCentre.IsDefined) << "Centre should be undefined at param=" << aParam; - } -} - -TEST(GeomProp_LineTest, VsCLProps_CriticalPoints) -{ - occ::handle aLine = new Geom_Line(gp_Pnt(0, 0, 0), gp_Dir(1, 1, 1)); - const double aParams[] = {0.0, 1.0e-10, -1.0e-10, 1.0e-6, -1.0e-6, 1.0e6, -1.0e6, 0.5, -0.5}; - for (const double aParam : aParams) - { - compareTangent(aLine, aParam); - compareCurvature(aLine, aParam); - compareNormal(aLine, aParam); - compareCentre(aLine, aParam); - } -} diff --git a/src/ModelingData/TKG3d/GTests/GeomProp_OffsetCurve_Test.cxx b/src/ModelingData/TKG3d/GTests/GeomProp_OffsetCurve_Test.cxx deleted file mode 100644 index f166e14fab..0000000000 --- a/src/ModelingData/TKG3d/GTests/GeomProp_OffsetCurve_Test.cxx +++ /dev/null @@ -1,441 +0,0 @@ -// 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. - -// Tests for GeomProp_Curve with offset curves: curves at constant distance -// from a base curve in a given direction. Properties computed numerically. - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -namespace -{ -constexpr double THE_LIN_TOL = Precision::PConfusion(); -constexpr double THE_CURV_TOL = 1.0e-8; -constexpr double THE_DIR_TOL = 1.0e-6; -constexpr double THE_POINT_TOL = 1.0e-6; - -void compareTangent(const occ::handle& theCurve, const double theParam) -{ - GeomProp_Curve aProp(theCurve); - const GeomProp::TangentResult aNew = aProp.Tangent(theParam, THE_LIN_TOL); - GeomLProp_CLProps anOld(theCurve, theParam, 2, THE_LIN_TOL); - if (anOld.IsTangentDefined()) - { - ASSERT_TRUE(aNew.IsDefined); - gp_Dir anOldDir; - anOld.Tangent(anOldDir); - EXPECT_NEAR(std::abs(aNew.Direction.Dot(anOldDir)), 1.0, THE_DIR_TOL); - } -} - -void compareCurvature(const occ::handle& theCurve, const double theParam) -{ - GeomProp_Curve aProp(theCurve); - const GeomProp::CurvatureResult aNew = aProp.Curvature(theParam, THE_LIN_TOL); - GeomLProp_CLProps anOld(theCurve, theParam, 2, THE_LIN_TOL); - if (anOld.IsTangentDefined()) - { - ASSERT_TRUE(aNew.IsDefined); - EXPECT_NEAR(aNew.Value, anOld.Curvature(), THE_CURV_TOL); - } -} - -void compareNormal(const occ::handle& theCurve, const double theParam) -{ - GeomProp_Curve aProp(theCurve); - const GeomProp::NormalResult aNew = aProp.Normal(theParam, THE_LIN_TOL); - GeomLProp_CLProps anOld(theCurve, theParam, 2, THE_LIN_TOL); - if (anOld.IsTangentDefined() && std::abs(anOld.Curvature()) > THE_LIN_TOL) - { - ASSERT_TRUE(aNew.IsDefined); - gp_Dir anOldNorm; - anOld.Normal(anOldNorm); - EXPECT_NEAR(std::abs(aNew.Direction.Dot(anOldNorm)), 1.0, THE_DIR_TOL); - } -} - -void compareCentre(const occ::handle& theCurve, const double theParam) -{ - GeomProp_Curve aProp(theCurve); - const GeomProp::CentreResult aNew = aProp.CentreOfCurvature(theParam, THE_LIN_TOL); - GeomLProp_CLProps anOld(theCurve, theParam, 2, THE_LIN_TOL); - if (anOld.IsTangentDefined() && std::abs(anOld.Curvature()) > THE_LIN_TOL) - { - ASSERT_TRUE(aNew.IsDefined); - gp_Pnt anOldCentre; - anOld.CentreOfCurvature(anOldCentre); - EXPECT_NEAR(aNew.Centre.Distance(anOldCentre), 0.0, THE_POINT_TOL); - } -} - -void compareAll(const occ::handle& theCurve, - const double theFirst, - const double theLast, - const int theNbSamples = 10) -{ - const double aStep = (theLast - theFirst) / theNbSamples; - for (int i = 0; i <= theNbSamples; ++i) - { - const double aParam = theFirst + i * aStep; - compareTangent(theCurve, aParam); - compareCurvature(theCurve, aParam); - compareNormal(theCurve, aParam); - compareCentre(theCurve, aParam); - } -} - -//! Create a circle in the XY plane with given radius and center. -occ::handle makeCircle(const double theRadius, - const double theCX = 0.0, - const double theCY = 0.0, - const double theCZ = 0.0) -{ - gp_Circ aCirc(gp_Ax2(gp_Pnt(theCX, theCY, theCZ), gp_Dir(0, 0, 1)), theRadius); - return new Geom_Circle(aCirc); -} - -//! Create an ellipse in the XY plane with given semi-axes. -occ::handle makeEllipse(const double theMajor, const double theMinor) -{ - gp_Elips anElips(gp_Ax2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), theMajor, theMinor); - return new Geom_Ellipse(anElips); -} - -//! Create an offset curve from a base curve in the Z direction. -occ::handle makeOffset(const occ::handle& theBase, - const double theOffset) -{ - return new Geom_OffsetCurve(theBase, theOffset, gp_Dir(0, 0, 1)); -} - -} // namespace - -// ============================================================================ -// Curvature tests - offset circle -// ============================================================================ - -TEST(GeomProp_OffsetCurveTest, Curvature_OffsetCircle_Constant) -{ - const double aRadius = 5.0; - const double aDist = 2.0; - occ::handle aCircle = makeCircle(aRadius); - occ::handle anOffset = makeOffset(aCircle, aDist); - - GeomProp_Curve aProp(anOffset); - - // Offset of circle with radius R by distance d gives circle with radius R+d - const double aExpectedCurvature = 1.0 / (aRadius + aDist); - for (double aParam = 0.0; aParam < 2.0 * M_PI; aParam += M_PI / 4.0) - { - const GeomProp::CurvatureResult aCurv = aProp.Curvature(aParam, THE_LIN_TOL); - ASSERT_TRUE(aCurv.IsDefined) << "Curvature undefined at param=" << aParam; - EXPECT_NEAR(aCurv.Value, aExpectedCurvature, THE_CURV_TOL) - << "Curvature mismatch at param=" << aParam; - } -} - -TEST(GeomProp_OffsetCurveTest, Curvature_OffsetCircle_Positive) -{ - const double aRadius = 3.0; - const double aDist = 4.0; - occ::handle aCircle = makeCircle(aRadius); - occ::handle anOffset = makeOffset(aCircle, aDist); - - GeomProp_Curve aProp(anOffset); - const GeomProp::CurvatureResult aCurv = aProp.Curvature(0.0, THE_LIN_TOL); - ASSERT_TRUE(aCurv.IsDefined); - EXPECT_NEAR(aCurv.Value, 1.0 / (aRadius + aDist), THE_CURV_TOL); -} - -TEST(GeomProp_OffsetCurveTest, Curvature_OffsetCircle_Negative) -{ - const double aRadius = 5.0; - const double aDist = -2.0; - occ::handle aCircle = makeCircle(aRadius); - occ::handle anOffset = makeOffset(aCircle, aDist); - - GeomProp_Curve aProp(anOffset); - const GeomProp::CurvatureResult aCurv = aProp.Curvature(0.0, THE_LIN_TOL); - ASSERT_TRUE(aCurv.IsDefined); - // Negative offset gives smaller circle with radius R-|d|=3 - EXPECT_NEAR(aCurv.Value, 1.0 / (aRadius + aDist), THE_CURV_TOL); -} - -// ============================================================================ -// Tangent tests - offset circle -// ============================================================================ - -TEST(GeomProp_OffsetCurveTest, Tangent_OffsetCircle) -{ - occ::handle aCircle = makeCircle(5.0); - occ::handle anOffset = makeOffset(aCircle, 2.0); - - GeomProp_Curve aPropBase(aCircle); - GeomProp_Curve aPropOffset(anOffset); - - // Tangent of offset circle should be parallel to base circle tangent - for (double aParam = 0.0; aParam < 2.0 * M_PI; aParam += M_PI / 3.0) - { - const GeomProp::TangentResult aTanBase = aPropBase.Tangent(aParam, THE_LIN_TOL); - const GeomProp::TangentResult aTanOffset = aPropOffset.Tangent(aParam, THE_LIN_TOL); - ASSERT_TRUE(aTanBase.IsDefined); - ASSERT_TRUE(aTanOffset.IsDefined); - EXPECT_NEAR(std::abs(aTanBase.Direction.Dot(aTanOffset.Direction)), 1.0, THE_DIR_TOL); - } -} - -// ============================================================================ -// Normal tests - offset circle -// ============================================================================ - -TEST(GeomProp_OffsetCurveTest, Normal_OffsetCircle) -{ - occ::handle aCircle = makeCircle(5.0); - occ::handle anOffset = makeOffset(aCircle, 2.0); - - GeomProp_Curve aPropBase(aCircle); - GeomProp_Curve aPropOffset(anOffset); - - for (double aParam = 0.0; aParam < 2.0 * M_PI; aParam += M_PI / 3.0) - { - const GeomProp::NormalResult aNormBase = aPropBase.Normal(aParam, THE_LIN_TOL); - const GeomProp::NormalResult aNormOffset = aPropOffset.Normal(aParam, THE_LIN_TOL); - ASSERT_TRUE(aNormBase.IsDefined); - ASSERT_TRUE(aNormOffset.IsDefined); - EXPECT_NEAR(std::abs(aNormBase.Direction.Dot(aNormOffset.Direction)), 1.0, THE_DIR_TOL); - } -} - -// ============================================================================ -// Centre of curvature - offset circle -// ============================================================================ - -TEST(GeomProp_OffsetCurveTest, Centre_OffsetCircle) -{ - const gp_Pnt aCenter(1.0, 2.0, 0.0); - occ::handle aCircle = makeCircle(5.0, 1.0, 2.0, 0.0); - occ::handle anOffset = makeOffset(aCircle, 2.0); - - GeomProp_Curve aProp(anOffset); - - // Centre of curvature of offset circle = center of the circle - const GeomProp::CentreResult aCentre = aProp.CentreOfCurvature(0.0, THE_LIN_TOL); - ASSERT_TRUE(aCentre.IsDefined); - EXPECT_NEAR(aCentre.Centre.Distance(aCenter), 0.0, THE_POINT_TOL); -} - -// ============================================================================ -// FindCurvatureExtrema / FindInflections - offset circle -// ============================================================================ - -TEST(GeomProp_OffsetCurveTest, FindCurvatureExtrema_OffsetCircle) -{ - occ::handle aCircle = makeCircle(5.0); - occ::handle anOffset = makeOffset(aCircle, 2.0); - - GeomProp_Curve aProp(anOffset); - const GeomProp::CurveAnalysis aResult = aProp.FindCurvatureExtrema(); - ASSERT_TRUE(aResult.IsDone); - // Constant curvature => no extrema - EXPECT_EQ(aResult.Points.Length(), 0); -} - -TEST(GeomProp_OffsetCurveTest, FindInflections_OffsetCircle) -{ - occ::handle aCircle = makeCircle(5.0); - occ::handle anOffset = makeOffset(aCircle, 2.0); - - GeomProp_Curve aProp(anOffset); - const GeomProp::CurveAnalysis aResult = aProp.FindInflections(); - ASSERT_TRUE(aResult.IsDone); - EXPECT_EQ(aResult.Points.Length(), 0); -} - -// ============================================================================ -// GetType test -// ============================================================================ - -TEST(GeomProp_OffsetCurveTest, GetType_IsOffsetCurve) -{ - occ::handle aCircle = makeCircle(5.0); - occ::handle anOffset = makeOffset(aCircle, 2.0); - - GeomProp_Curve aProp(anOffset); - EXPECT_EQ(aProp.GetType(), GeomAbs_OffsetCurve); -} - -// ============================================================================ -// VsCLProps comparison tests - offset circle -// ============================================================================ - -TEST(GeomProp_OffsetCurveTest, VsCLProps_OffsetCircle) -{ - occ::handle aCircle = makeCircle(5.0); - occ::handle anOffset = makeOffset(aCircle, 2.0); - compareAll(anOffset, 0.0, 2.0 * M_PI); -} - -TEST(GeomProp_OffsetCurveTest, VsCLProps_AllProperties_OffsetCircle) -{ - occ::handle aCircle = makeCircle(5.0); - occ::handle anOffset = makeOffset(aCircle, 2.0); - compareAll(anOffset, 0.0, 2.0 * M_PI, 20); -} - -// ============================================================================ -// Offset ellipse tests -// ============================================================================ - -TEST(GeomProp_OffsetCurveTest, Curvature_OffsetEllipse) -{ - occ::handle anEllipse = makeEllipse(10.0, 5.0); - occ::handle anOffset = makeOffset(anEllipse, 1.0); - - GeomProp_Curve aProp(anOffset); - - // Curvature should vary along the offset ellipse - const GeomProp::CurvatureResult aCurv0 = aProp.Curvature(0.0, THE_LIN_TOL); - const GeomProp::CurvatureResult aCurvPi2 = aProp.Curvature(M_PI / 2.0, THE_LIN_TOL); - ASSERT_TRUE(aCurv0.IsDefined); - ASSERT_TRUE(aCurvPi2.IsDefined); - EXPECT_NE(aCurv0.Value, aCurvPi2.Value); -} - -TEST(GeomProp_OffsetCurveTest, FindCurvatureExtrema_OffsetEllipse) -{ - occ::handle anEllipse = makeEllipse(10.0, 5.0); - occ::handle anOffset = makeOffset(anEllipse, 1.0); - - GeomProp_Curve aProp(anOffset); - const GeomProp::CurveAnalysis aResult = aProp.FindCurvatureExtrema(); - ASSERT_TRUE(aResult.IsDone); - // Offset ellipse should have curvature extrema (inherited from ellipse shape) - EXPECT_GE(aResult.Points.Length(), 2); -} - -TEST(GeomProp_OffsetCurveTest, FindInflections_OffsetEllipse) -{ - occ::handle anEllipse = makeEllipse(10.0, 5.0); - occ::handle anOffset = makeOffset(anEllipse, 1.0); - - GeomProp_Curve aProp(anOffset); - const GeomProp::CurveAnalysis aResult = aProp.FindInflections(); - ASSERT_TRUE(aResult.IsDone); - // Offset of convex ellipse with small offset should have no inflections - for (int i = 0; i < aResult.Points.Length(); ++i) - { - EXPECT_EQ(aResult.Points[i].Type, GeomProp::CIType::Inflection); - } -} - -TEST(GeomProp_OffsetCurveTest, Tangent_OffsetEllipse) -{ - occ::handle anEllipse = makeEllipse(10.0, 5.0); - occ::handle anOffset = makeOffset(anEllipse, 1.0); - - GeomProp_Curve aProp(anOffset); - - for (double aParam = 0.0; aParam < 2.0 * M_PI; aParam += M_PI / 4.0) - { - const GeomProp::TangentResult aTan = aProp.Tangent(aParam, THE_LIN_TOL); - ASSERT_TRUE(aTan.IsDefined) << "Tangent undefined at param=" << aParam; - (void)aTan.Direction; - } -} - -TEST(GeomProp_OffsetCurveTest, Normal_OffsetEllipse) -{ - occ::handle anEllipse = makeEllipse(10.0, 5.0); - occ::handle anOffset = makeOffset(anEllipse, 1.0); - - GeomProp_Curve aProp(anOffset); - - for (double aParam = 0.0; aParam < 2.0 * M_PI; aParam += M_PI / 4.0) - { - const GeomProp::NormalResult aNorm = aProp.Normal(aParam, THE_LIN_TOL); - if (aNorm.IsDefined) - { - (void)aNorm.Direction; - } - } -} - -// ============================================================================ -// VsCLProps comparison tests - offset ellipse -// ============================================================================ - -TEST(GeomProp_OffsetCurveTest, VsCLProps_OffsetEllipse) -{ - occ::handle anEllipse = makeEllipse(10.0, 5.0); - occ::handle anOffset = makeOffset(anEllipse, 1.0); - compareAll(anOffset, 0.0, 2.0 * M_PI); -} - -TEST(GeomProp_OffsetCurveTest, VsCLProps_AllProperties_OffsetEllipse) -{ - occ::handle anEllipse = makeEllipse(10.0, 5.0); - occ::handle anOffset = makeOffset(anEllipse, 1.0); - compareAll(anOffset, 0.0, 2.0 * M_PI, 20); -} - -TEST(GeomProp_OffsetCurveTest, VsCLProps_LargeOffset) -{ - occ::handle aCircle = makeCircle(5.0); - occ::handle anOffset = makeOffset(aCircle, 50.0); - compareAll(anOffset, 0.0, 2.0 * M_PI); -} - -TEST(GeomProp_OffsetCurveTest, VsCLProps_SmallOffset) -{ - occ::handle aCircle = makeCircle(5.0); - occ::handle anOffset = makeOffset(aCircle, 0.001); - compareAll(anOffset, 0.0, 2.0 * M_PI); -} - -TEST(GeomProp_OffsetCurveTest, VsCLProps_CriticalPoints) -{ - // Offset of a circle - occ::handle aCircle = new Geom_Circle(gp_Ax2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), 5.0); - occ::handle anOffset = new Geom_OffsetCurve(aCircle, 2.0, gp_Dir(0, 0, 1)); - const double aParams[] = {0.0, - 1.0e-10, - M_PI / 4.0, - M_PI / 2.0, - M_PI / 2.0 + 1.0e-6, - M_PI, - 3.0 * M_PI / 2.0, - 2.0 * M_PI - 1.0e-10, - M_PI / 6.0, - 5.0 * M_PI / 6.0}; - for (const double aParam : aParams) - { - compareTangent(anOffset, aParam); - compareCurvature(anOffset, aParam); - compareNormal(anOffset, aParam); - compareCentre(anOffset, aParam); - } -} diff --git a/src/ModelingData/TKG3d/GTests/GeomProp_OffsetSurface_Test.cxx b/src/ModelingData/TKG3d/GTests/GeomProp_OffsetSurface_Test.cxx deleted file mode 100644 index 6bce76199b..0000000000 --- a/src/ModelingData/TKG3d/GTests/GeomProp_OffsetSurface_Test.cxx +++ /dev/null @@ -1,418 +0,0 @@ -// 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. - -// Tests for GeomProp_Surface with Geom_OffsetSurface. -// Validates normal, curvatures, mean/Gaussian curvature for offset surfaces -// created from spheres, planes, and cylinders with various offset distances. -// Cross-validates against GeomLProp_SLProps. - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -namespace -{ -constexpr double THE_LIN_TOL = Precision::PConfusion(); -constexpr double THE_CURV_TOL = 1.0e-6; -constexpr double THE_DIR_TOL = 1.0e-4; - -//! Compare surface normal from new GeomProp_Surface vs old GeomLProp_SLProps. -void compareNormal(const occ::handle& theSurf, const double theU, const double theV) -{ - GeomProp_Surface aProp(theSurf); - const GeomProp::SurfaceNormalResult aNew = aProp.Normal(theU, theV, THE_LIN_TOL); - - GeomLProp_SLProps anOld(theSurf, theU, theV, 2, THE_LIN_TOL); - if (anOld.IsNormalDefined()) - { - ASSERT_TRUE(aNew.IsDefined) << "New normal undefined at (" << theU << "," << theV << ")"; - const double aDot = aNew.Direction.Dot(anOld.Normal()); - EXPECT_NEAR(std::abs(aDot), 1.0, THE_DIR_TOL) - << "Normal mismatch at (" << theU << "," << theV << ")"; - } -} - -//! Compare curvatures from new GeomProp_Surface vs old GeomLProp_SLProps. -void compareCurvatures(const occ::handle& theSurf, - const double theU, - const double theV) -{ - GeomProp_Surface aProp(theSurf); - const GeomProp::SurfaceCurvatureResult aNew = aProp.Curvatures(theU, theV, THE_LIN_TOL); - - GeomLProp_SLProps anOld(theSurf, theU, theV, 2, THE_LIN_TOL); - if (anOld.IsCurvatureDefined()) - { - ASSERT_TRUE(aNew.IsDefined) << "New curvatures undefined at (" << theU << "," << theV << ")"; - EXPECT_NEAR(aNew.MinCurvature, anOld.MinCurvature(), THE_CURV_TOL) - << "MinCurvature mismatch at (" << theU << "," << theV << ")"; - EXPECT_NEAR(aNew.MaxCurvature, anOld.MaxCurvature(), THE_CURV_TOL) - << "MaxCurvature mismatch at (" << theU << "," << theV << ")"; - } -} - -//! Compare mean and Gaussian curvatures. -void compareMeanGaussian(const occ::handle& theSurf, - const double theU, - const double theV) -{ - GeomProp_Surface aProp(theSurf); - const GeomProp::MeanGaussianResult aNew = aProp.MeanGaussian(theU, theV, THE_LIN_TOL); - - GeomLProp_SLProps anOld(theSurf, theU, theV, 2, THE_LIN_TOL); - if (anOld.IsCurvatureDefined()) - { - ASSERT_TRUE(aNew.IsDefined) << "New MeanGaussian undefined at (" << theU << "," << theV << ")"; - EXPECT_NEAR(aNew.MeanCurvature, anOld.MeanCurvature(), THE_CURV_TOL) - << "Mean curvature mismatch at (" << theU << "," << theV << ")"; - EXPECT_NEAR(aNew.GaussianCurvature, anOld.GaussianCurvature(), THE_CURV_TOL) - << "Gaussian curvature mismatch at (" << theU << "," << theV << ")"; - } -} - -//! Run all surface comparisons at a grid of parameter values. -void compareAllSurface(const occ::handle& theSurf, - const double theUMin, - const double theUMax, - const double theVMin, - const double theVMax, - const int theNbU = 5, - const int theNbV = 5) -{ - const double aUStep = (theUMax - theUMin) / theNbU; - const double aVStep = (theVMax - theVMin) / theNbV; - for (int i = 0; i <= theNbU; ++i) - { - for (int j = 0; j <= theNbV; ++j) - { - const double aU = theUMin + i * aUStep; - const double aV = theVMin + j * aVStep; - compareNormal(theSurf, aU, aV); - compareCurvatures(theSurf, aU, aV); - compareMeanGaussian(theSurf, aU, aV); - } - } -} - -//! Create offset sphere: sphere R=10, offset d=2. -occ::handle makeOffsetSphere(const double theOffset = 2.0) -{ - occ::handle aSphere = new Geom_SphericalSurface(gp_Ax3(), 10.0); - return new Geom_OffsetSurface(aSphere, theOffset); -} - -//! Create offset plane: XY plane with offset d=5. -occ::handle makeOffsetPlane() -{ - occ::handle aPlane = new Geom_Plane(gp_Ax3()); - return new Geom_OffsetSurface(aPlane, 5.0); -} - -//! Create offset cylinder: radius 4, offset d=1. -occ::handle makeOffsetCylinder() -{ - occ::handle aCyl = new Geom_CylindricalSurface(gp_Ax3(), 4.0); - return new Geom_OffsetSurface(aCyl, 1.0); -} -} // namespace - -// Normal of offset sphere: same direction as base sphere -TEST(GeomProp_OffsetSurfaceTest, Normal_OffsetSphere) -{ - occ::handle aOffSurf = makeOffsetSphere(); - occ::handle aBaseSurf = new Geom_SphericalSurface(gp_Ax3(), 10.0); - GeomProp_Surface aOffProp(aOffSurf); - GeomProp_Surface aBaseProp(aBaseSurf); - - // Avoid poles - for (double aU = 0.5; aU < 2.0 * M_PI; aU += M_PI / 3.0) - { - for (double aV = -M_PI / 3.0; aV <= M_PI / 3.0; aV += M_PI / 3.0) - { - const GeomProp::SurfaceNormalResult aOffNorm = aOffProp.Normal(aU, aV, THE_LIN_TOL); - const GeomProp::SurfaceNormalResult aBaseNorm = aBaseProp.Normal(aU, aV, THE_LIN_TOL); - ASSERT_TRUE(aOffNorm.IsDefined); - ASSERT_TRUE(aBaseNorm.IsDefined); - const double aDot = aOffNorm.Direction.Dot(aBaseNorm.Direction); - EXPECT_NEAR(std::abs(aDot), 1.0, THE_DIR_TOL) - << "Normal differs from base at (" << aU << "," << aV << ")"; - } - } -} - -// Curvatures of offset sphere: k = 1/(R+d) for both principal curvatures -TEST(GeomProp_OffsetSurfaceTest, Curvatures_OffsetSphere) -{ - const double aR = 10.0; - const double aD = 2.0; - occ::handle aSurf = makeOffsetSphere(aD); - GeomProp_Surface aProp(aSurf); - - // Avoid poles - const GeomProp::SurfaceCurvatureResult aResult = aProp.Curvatures(1.0, 0.0, THE_LIN_TOL); - ASSERT_TRUE(aResult.IsDefined); - const double aExpectedK = 1.0 / (aR + aD); - EXPECT_NEAR(std::abs(aResult.MinCurvature), aExpectedK, THE_CURV_TOL); - EXPECT_NEAR(std::abs(aResult.MaxCurvature), aExpectedK, THE_CURV_TOL); -} - -// Mean and Gaussian curvature of offset sphere -TEST(GeomProp_OffsetSurfaceTest, MeanGaussian_OffsetSphere) -{ - const double aR = 10.0; - const double aD = 2.0; - occ::handle aSurf = makeOffsetSphere(aD); - GeomProp_Surface aProp(aSurf); - - const GeomProp::MeanGaussianResult aResult = aProp.MeanGaussian(1.0, 0.0, THE_LIN_TOL); - ASSERT_TRUE(aResult.IsDefined); - const double aExpectedK = 1.0 / (aR + aD); - const double aExpectedGK = aExpectedK * aExpectedK; - EXPECT_NEAR(std::abs(aResult.MeanCurvature), aExpectedK, THE_CURV_TOL); - EXPECT_NEAR(aResult.GaussianCurvature, aExpectedGK, THE_CURV_TOL); -} - -// Normal of offset plane: same as base plane -TEST(GeomProp_OffsetSurfaceTest, Normal_OffsetPlane) -{ - occ::handle aSurf = makeOffsetPlane(); - GeomProp_Surface aProp(aSurf); - - const gp_Dir aExpected(0.0, 0.0, 1.0); - for (double aU = -5.0; aU <= 5.0; aU += 2.5) - { - for (double aV = -5.0; aV <= 5.0; aV += 2.5) - { - const GeomProp::SurfaceNormalResult aResult = aProp.Normal(aU, aV, THE_LIN_TOL); - ASSERT_TRUE(aResult.IsDefined); - const double aDot = aResult.Direction.Dot(aExpected); - EXPECT_NEAR(std::abs(aDot), 1.0, THE_DIR_TOL); - } - } -} - -// Curvatures of offset plane: still zero -TEST(GeomProp_OffsetSurfaceTest, Curvatures_OffsetPlane) -{ - occ::handle aSurf = makeOffsetPlane(); - GeomProp_Surface aProp(aSurf); - - const GeomProp::SurfaceCurvatureResult aResult = aProp.Curvatures(0.0, 0.0, THE_LIN_TOL); - ASSERT_TRUE(aResult.IsDefined); - EXPECT_NEAR(aResult.MinCurvature, 0.0, THE_CURV_TOL); - EXPECT_NEAR(aResult.MaxCurvature, 0.0, THE_CURV_TOL); -} - -// Mean and Gaussian curvature of offset plane: H=K=0 -TEST(GeomProp_OffsetSurfaceTest, MeanGaussian_OffsetPlane) -{ - occ::handle aSurf = makeOffsetPlane(); - GeomProp_Surface aProp(aSurf); - - const GeomProp::MeanGaussianResult aResult = aProp.MeanGaussian(0.0, 0.0, THE_LIN_TOL); - ASSERT_TRUE(aResult.IsDefined); - EXPECT_NEAR(aResult.MeanCurvature, 0.0, THE_CURV_TOL); - EXPECT_NEAR(aResult.GaussianCurvature, 0.0, THE_CURV_TOL); -} - -// GetType returns GeomAbs_OffsetSurface -TEST(GeomProp_OffsetSurfaceTest, GetType_IsOffsetSurface) -{ - occ::handle aSurf = makeOffsetSphere(); - GeomProp_Surface aProp(aSurf); - EXPECT_EQ(aProp.GetType(), GeomAbs_OffsetSurface); -} - -// Cross-validate offset sphere vs SLProps -TEST(GeomProp_OffsetSurfaceTest, VsSLProps_OffsetSphere) -{ - occ::handle aSurf = makeOffsetSphere(); - compareAllSurface(aSurf, 0.1, 2.0 * M_PI - 0.1, -M_PI / 3.0, M_PI / 3.0); -} - -// Cross-validate offset plane vs SLProps -TEST(GeomProp_OffsetSurfaceTest, VsSLProps_OffsetPlane) -{ - occ::handle aSurf = makeOffsetPlane(); - compareAllSurface(aSurf, -5.0, 5.0, -5.0, 5.0); -} - -// Dense cross-validation for offset sphere -TEST(GeomProp_OffsetSurfaceTest, VsSLProps_AllProperties_Sphere) -{ - occ::handle aSurf = makeOffsetSphere(); - compareAllSurface(aSurf, 0.1, 2.0 * M_PI - 0.1, -M_PI / 3.0, M_PI / 3.0, 6, 6); -} - -// Dense cross-validation for offset plane -TEST(GeomProp_OffsetSurfaceTest, VsSLProps_AllProperties_Plane) -{ - occ::handle aSurf = makeOffsetPlane(); - compareAllSurface(aSurf, -5.0, 5.0, -5.0, 5.0, 6, 6); -} - -// Normal of offset cylinder: same as base cylinder -TEST(GeomProp_OffsetSurfaceTest, Normal_OffsetCylinder) -{ - occ::handle aOffSurf = makeOffsetCylinder(); - occ::handle aBaseSurf = new Geom_CylindricalSurface(gp_Ax3(), 4.0); - GeomProp_Surface aOffProp(aOffSurf); - GeomProp_Surface aBaseProp(aBaseSurf); - - for (double aU = 0.5; aU < 2.0 * M_PI; aU += M_PI / 3.0) - { - const GeomProp::SurfaceNormalResult aOffNorm = aOffProp.Normal(aU, 0.0, THE_LIN_TOL); - const GeomProp::SurfaceNormalResult aBaseNorm = aBaseProp.Normal(aU, 0.0, THE_LIN_TOL); - ASSERT_TRUE(aOffNorm.IsDefined); - ASSERT_TRUE(aBaseNorm.IsDefined); - const double aDot = aOffNorm.Direction.Dot(aBaseNorm.Direction); - EXPECT_NEAR(std::abs(aDot), 1.0, THE_DIR_TOL); - } -} - -// Curvatures of offset cylinder: modified radius R+d -TEST(GeomProp_OffsetSurfaceTest, Curvatures_OffsetCylinder) -{ - occ::handle aSurf = makeOffsetCylinder(); - GeomProp_Surface aProp(aSurf); - - const double aExpectedK = 1.0 / (4.0 + 1.0); // 1/(R+d) - const GeomProp::SurfaceCurvatureResult aResult = aProp.Curvatures(1.0, 0.0, THE_LIN_TOL); - ASSERT_TRUE(aResult.IsDefined); - // MinCurvature = -1/(R+d) (concave, signed), MaxCurvature = 0 (along axis). - EXPECT_NEAR(aResult.MinCurvature, -aExpectedK, THE_CURV_TOL); - EXPECT_NEAR(aResult.MaxCurvature, 0.0, THE_CURV_TOL); -} - -// Mean and Gaussian curvature of offset cylinder -TEST(GeomProp_OffsetSurfaceTest, MeanGaussian_OffsetCylinder) -{ - occ::handle aSurf = makeOffsetCylinder(); - GeomProp_Surface aProp(aSurf); - - const GeomProp::MeanGaussianResult aResult = aProp.MeanGaussian(1.0, 0.0, THE_LIN_TOL); - ASSERT_TRUE(aResult.IsDefined); - // Gaussian curvature of cylinder-like surface should be zero - EXPECT_NEAR(aResult.GaussianCurvature, 0.0, THE_CURV_TOL); -} - -// Cross-validate offset cylinder vs SLProps -TEST(GeomProp_OffsetSurfaceTest, VsSLProps_OffsetCylinder) -{ - occ::handle aSurf = makeOffsetCylinder(); - compareAllSurface(aSurf, 0.1, 2.0 * M_PI - 0.1, -5.0, 5.0); -} - -// Large offset on sphere (d=100) -TEST(GeomProp_OffsetSurfaceTest, Curvatures_OffsetSphere_LargeOffset) -{ - const double aD = 100.0; - occ::handle aSurf = makeOffsetSphere(aD); - GeomProp_Surface aProp(aSurf); - - const GeomProp::SurfaceCurvatureResult aResult = aProp.Curvatures(1.0, 0.0, THE_LIN_TOL); - ASSERT_TRUE(aResult.IsDefined); - const double aExpectedK = 1.0 / (10.0 + aD); - EXPECT_NEAR(std::abs(aResult.MinCurvature), aExpectedK, THE_CURV_TOL); - EXPECT_NEAR(std::abs(aResult.MaxCurvature), aExpectedK, THE_CURV_TOL); -} - -// Small offset on sphere (d=0.01) -TEST(GeomProp_OffsetSurfaceTest, Curvatures_OffsetSphere_SmallOffset) -{ - const double aD = 0.01; - occ::handle aSurf = makeOffsetSphere(aD); - GeomProp_Surface aProp(aSurf); - - const GeomProp::SurfaceCurvatureResult aResult = aProp.Curvatures(1.0, 0.0, THE_LIN_TOL); - ASSERT_TRUE(aResult.IsDefined); - const double aExpectedK = 1.0 / (10.0 + aD); - EXPECT_NEAR(std::abs(aResult.MinCurvature), aExpectedK, THE_CURV_TOL); - EXPECT_NEAR(std::abs(aResult.MaxCurvature), aExpectedK, THE_CURV_TOL); -} - -// Cross-validate large offset sphere -TEST(GeomProp_OffsetSurfaceTest, VsSLProps_LargeOffset) -{ - occ::handle aSurf = makeOffsetSphere(100.0); - compareAllSurface(aSurf, 0.1, 2.0 * M_PI - 0.1, -M_PI / 3.0, M_PI / 3.0); -} - -// Cross-validate small offset sphere -TEST(GeomProp_OffsetSurfaceTest, VsSLProps_SmallOffset) -{ - occ::handle aSurf = makeOffsetSphere(0.01); - compareAllSurface(aSurf, 0.1, 2.0 * M_PI - 0.1, -M_PI / 3.0, M_PI / 3.0); -} - -// Consistency check: H = (k1+k2)/2 and K = k1*k2 -TEST(GeomProp_OffsetSurfaceTest, MeanGaussian_Consistent) -{ - occ::handle aSurf = makeOffsetSphere(); - GeomProp_Surface aProp(aSurf); - - for (double aU = 0.5; aU < 2.0 * M_PI; aU += M_PI / 3.0) - { - for (double aV = -M_PI / 4.0; aV <= M_PI / 4.0; aV += M_PI / 4.0) - { - const GeomProp::SurfaceCurvatureResult aCurv = aProp.Curvatures(aU, aV, THE_LIN_TOL); - const GeomProp::MeanGaussianResult aMG = aProp.MeanGaussian(aU, aV, THE_LIN_TOL); - if (aCurv.IsDefined && aMG.IsDefined) - { - const double aExpectedH = (aCurv.MinCurvature + aCurv.MaxCurvature) / 2.0; - const double aExpectedK = aCurv.MinCurvature * aCurv.MaxCurvature; - EXPECT_NEAR(aMG.MeanCurvature, aExpectedH, THE_CURV_TOL) - << "H != (k1+k2)/2 at (" << aU << "," << aV << ")"; - EXPECT_NEAR(aMG.GaussianCurvature, aExpectedK, THE_CURV_TOL) - << "K != k1*k2 at (" << aU << "," << aV << ")"; - } - } - } -} - -TEST(GeomProp_OffsetSurfaceTest, VsSLProps_CriticalPoints) -{ - // Offset of a sphere - occ::handle aSphere = new Geom_SphericalSurface(gp_Ax3(), 5.0); - occ::handle aSurf = new Geom_OffsetSurface(aSphere, 2.0); - // Critical: near poles, equator, seam - const double aParams[][2] = {{0.0, 0.0}, - {1.0e-10, 0.0}, - {0.0, 1.0e-10}, - {M_PI / 2.0, 0.0}, - {M_PI, 0.0}, - {0.0, M_PI / 4.0}, - {0.0, -M_PI / 4.0}, - {0.0, M_PI / 2.0 - 1.0e-6}, - {0.0, -(M_PI / 2.0 - 1.0e-6)}, - {2.0 * M_PI - 1.0e-10, 0.0}, - {M_PI / 4.0, M_PI / 3.0}}; - for (const auto& aUV : aParams) - { - compareNormal(aSurf, aUV[0], aUV[1]); - compareCurvatures(aSurf, aUV[0], aUV[1]); - compareMeanGaussian(aSurf, aUV[0], aUV[1]); - } -} diff --git a/src/ModelingData/TKG3d/GTests/GeomProp_OtherCurve_Test.cxx b/src/ModelingData/TKG3d/GTests/GeomProp_OtherCurve_Test.cxx deleted file mode 100644 index 0fc61e475d..0000000000 --- a/src/ModelingData/TKG3d/GTests/GeomProp_OtherCurve_Test.cxx +++ /dev/null @@ -1,433 +0,0 @@ -// 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. - -// Tests for GeomProp_Curve with TrimmedCurve and other non-standard curve types -// that fall into the "Other" variant of the evaluator. Testing mainly with -// Geom_TrimmedCurve wrapping various base curves. - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -namespace -{ -constexpr double THE_LIN_TOL = Precision::PConfusion(); -constexpr double THE_CURV_TOL = 1.0e-8; -constexpr double THE_DIR_TOL = 1.0e-6; -constexpr double THE_POINT_TOL = 1.0e-6; - -void compareTangent(const occ::handle& theCurve, const double theParam) -{ - GeomProp_Curve aProp(theCurve); - const GeomProp::TangentResult aNew = aProp.Tangent(theParam, THE_LIN_TOL); - GeomLProp_CLProps anOld(theCurve, theParam, 2, THE_LIN_TOL); - if (anOld.IsTangentDefined()) - { - ASSERT_TRUE(aNew.IsDefined); - gp_Dir anOldDir; - anOld.Tangent(anOldDir); - EXPECT_NEAR(std::abs(aNew.Direction.Dot(anOldDir)), 1.0, THE_DIR_TOL); - } -} - -void compareCurvature(const occ::handle& theCurve, const double theParam) -{ - GeomProp_Curve aProp(theCurve); - const GeomProp::CurvatureResult aNew = aProp.Curvature(theParam, THE_LIN_TOL); - GeomLProp_CLProps anOld(theCurve, theParam, 2, THE_LIN_TOL); - if (anOld.IsTangentDefined()) - { - ASSERT_TRUE(aNew.IsDefined); - EXPECT_NEAR(aNew.Value, anOld.Curvature(), THE_CURV_TOL); - } -} - -void compareNormal(const occ::handle& theCurve, const double theParam) -{ - GeomProp_Curve aProp(theCurve); - const GeomProp::NormalResult aNew = aProp.Normal(theParam, THE_LIN_TOL); - GeomLProp_CLProps anOld(theCurve, theParam, 2, THE_LIN_TOL); - if (anOld.IsTangentDefined() && std::abs(anOld.Curvature()) > THE_LIN_TOL) - { - ASSERT_TRUE(aNew.IsDefined); - gp_Dir anOldNorm; - anOld.Normal(anOldNorm); - EXPECT_NEAR(std::abs(aNew.Direction.Dot(anOldNorm)), 1.0, THE_DIR_TOL); - } -} - -void compareCentre(const occ::handle& theCurve, const double theParam) -{ - GeomProp_Curve aProp(theCurve); - const GeomProp::CentreResult aNew = aProp.CentreOfCurvature(theParam, THE_LIN_TOL); - GeomLProp_CLProps anOld(theCurve, theParam, 2, THE_LIN_TOL); - if (anOld.IsTangentDefined() && std::abs(anOld.Curvature()) > THE_LIN_TOL) - { - ASSERT_TRUE(aNew.IsDefined); - gp_Pnt anOldCentre; - anOld.CentreOfCurvature(anOldCentre); - EXPECT_NEAR(aNew.Centre.Distance(anOldCentre), 0.0, THE_POINT_TOL); - } -} - -void compareAll(const occ::handle& theCurve, - const double theFirst, - const double theLast, - const int theNbSamples = 10) -{ - const double aStep = (theLast - theFirst) / theNbSamples; - for (int i = 0; i <= theNbSamples; ++i) - { - const double aParam = theFirst + i * aStep; - compareTangent(theCurve, aParam); - compareCurvature(theCurve, aParam); - compareNormal(theCurve, aParam); - compareCentre(theCurve, aParam); - } -} - -//! Create a trimmed circle (quarter arc from 0 to PI/2). -occ::handle makeTrimmedCircle(const double theRadius = 5.0) -{ - gp_Circ aCirc(gp_Ax2(gp_Pnt(1, 2, 0), gp_Dir(0, 0, 1)), theRadius); - occ::handle aCircle = new Geom_Circle(aCirc); - return new Geom_TrimmedCurve(aCircle, 0.0, M_PI / 2.0); -} - -//! Create a trimmed ellipse (from PI/4 to 3*PI/4). -occ::handle makeTrimmedEllipse(const double theMajor = 10.0, - const double theMinor = 5.0) -{ - gp_Elips anElips(gp_Ax2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), theMajor, theMinor); - occ::handle anEllipse = new Geom_Ellipse(anElips); - return new Geom_TrimmedCurve(anEllipse, M_PI / 4.0, 3.0 * M_PI / 4.0); -} - -//! Create an S-shaped Bezier curve with inflection point. -occ::handle makeSBezier() -{ - NCollection_Array1 aPoles(1, 4); - aPoles(1) = gp_Pnt(0, 0, 0); - aPoles(2) = gp_Pnt(1, 3, 0); - aPoles(3) = gp_Pnt(3, -2, 0); - aPoles(4) = gp_Pnt(4, 1, 0); - return new Geom_BezierCurve(aPoles); -} - -//! Create a trimmed Bezier curve (from 0.1 to 0.9). -occ::handle makeTrimmedBezier() -{ - occ::handle aBezier = makeSBezier(); - return new Geom_TrimmedCurve(aBezier, 0.1, 0.9); -} - -//! Create a trimmed hyperbola (from -1.0 to 1.0). -occ::handle makeTrimmedHyperbola() -{ - gp_Hypr anHypr(gp_Ax2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), 6.0, 3.0); - occ::handle aHyperbola = new Geom_Hyperbola(anHypr); - return new Geom_TrimmedCurve(aHyperbola, -1.0, 1.0); -} - -} // namespace - -// ============================================================================ -// Trimmed circle tests -// ============================================================================ - -TEST(GeomProp_OtherCurveTest, Tangent_TrimmedCircle) -{ - occ::handle aTrimmed = makeTrimmedCircle(); - GeomProp_Curve aProp(aTrimmed); - - for (double aParam = 0.0; aParam <= M_PI / 2.0; aParam += M_PI / 8.0) - { - const GeomProp::TangentResult aTan = aProp.Tangent(aParam, THE_LIN_TOL); - ASSERT_TRUE(aTan.IsDefined) << "Tangent undefined at param=" << aParam; - (void)aTan.Direction; - } -} - -TEST(GeomProp_OtherCurveTest, Curvature_TrimmedCircle) -{ - const double aRadius = 5.0; - occ::handle aTrimmed = makeTrimmedCircle(aRadius); - GeomProp_Curve aProp(aTrimmed); - - // Curvature should be constant 1/R within the trimmed range - for (double aParam = 0.0; aParam <= M_PI / 2.0; aParam += M_PI / 8.0) - { - const GeomProp::CurvatureResult aCurv = aProp.Curvature(aParam, THE_LIN_TOL); - ASSERT_TRUE(aCurv.IsDefined); - EXPECT_NEAR(aCurv.Value, 1.0 / aRadius, THE_CURV_TOL); - } -} - -TEST(GeomProp_OtherCurveTest, Normal_TrimmedCircle) -{ - occ::handle aTrimmed = makeTrimmedCircle(); - GeomProp_Curve aProp(aTrimmed); - - // At param=0, point is (6,2,0) on circle centered at (1,2,0), normal points to (-1,0,0) - const GeomProp::NormalResult aNorm = aProp.Normal(0.0, THE_LIN_TOL); - ASSERT_TRUE(aNorm.IsDefined); - EXPECT_NEAR(aNorm.Direction.X(), -1.0, THE_DIR_TOL); - EXPECT_NEAR(aNorm.Direction.Y(), 0.0, THE_DIR_TOL); -} - -TEST(GeomProp_OtherCurveTest, Centre_TrimmedCircle) -{ - occ::handle aTrimmed = makeTrimmedCircle(); - GeomProp_Curve aProp(aTrimmed); - - // Centre of curvature should be circle center (1,2,0) at all params - for (double aParam = 0.0; aParam <= M_PI / 2.0; aParam += M_PI / 8.0) - { - const GeomProp::CentreResult aCentre = aProp.CentreOfCurvature(aParam, THE_LIN_TOL); - ASSERT_TRUE(aCentre.IsDefined); - EXPECT_NEAR(aCentre.Centre.X(), 1.0, THE_POINT_TOL); - EXPECT_NEAR(aCentre.Centre.Y(), 2.0, THE_POINT_TOL); - } -} - -TEST(GeomProp_OtherCurveTest, FindCurvatureExtrema_TrimmedCircle) -{ - occ::handle aTrimmed = makeTrimmedCircle(); - GeomProp_Curve aProp(aTrimmed); - - const GeomProp::CurveAnalysis aResult = aProp.FindCurvatureExtrema(); - ASSERT_TRUE(aResult.IsDone); - // Constant curvature => no extrema - EXPECT_EQ(aResult.Points.Length(), 0); -} - -TEST(GeomProp_OtherCurveTest, FindInflections_TrimmedCircle) -{ - occ::handle aTrimmed = makeTrimmedCircle(); - GeomProp_Curve aProp(aTrimmed); - - const GeomProp::CurveAnalysis aResult = aProp.FindInflections(); - ASSERT_TRUE(aResult.IsDone); - EXPECT_EQ(aResult.Points.Length(), 0); -} - -// ============================================================================ -// Trimmed ellipse tests -// ============================================================================ - -TEST(GeomProp_OtherCurveTest, Tangent_TrimmedEllipse) -{ - occ::handle aTrimmed = makeTrimmedEllipse(); - GeomProp_Curve aProp(aTrimmed); - - const double aFirst = M_PI / 4.0; - const double aLast = 3.0 * M_PI / 4.0; - for (double aParam = aFirst; aParam <= aLast; aParam += (aLast - aFirst) / 5.0) - { - const GeomProp::TangentResult aTan = aProp.Tangent(aParam, THE_LIN_TOL); - ASSERT_TRUE(aTan.IsDefined) << "Tangent undefined at param=" << aParam; - } -} - -TEST(GeomProp_OtherCurveTest, Curvature_TrimmedEllipse) -{ - occ::handle aTrimmed = makeTrimmedEllipse(); - GeomProp_Curve aProp(aTrimmed); - - const double aFirst = M_PI / 4.0; - const double aLast = 3.0 * M_PI / 4.0; - - // Curvature should vary within the trimmed range - const GeomProp::CurvatureResult aCurvFirst = aProp.Curvature(aFirst, THE_LIN_TOL); - const GeomProp::CurvatureResult aCurvMid = aProp.Curvature((aFirst + aLast) / 2.0, THE_LIN_TOL); - ASSERT_TRUE(aCurvFirst.IsDefined); - ASSERT_TRUE(aCurvMid.IsDefined); - EXPECT_GT(aCurvFirst.Value, 0.0); - EXPECT_GT(aCurvMid.Value, 0.0); -} - -TEST(GeomProp_OtherCurveTest, FindCurvatureExtrema_TrimmedEllipse) -{ - occ::handle aTrimmed = makeTrimmedEllipse(); - GeomProp_Curve aProp(aTrimmed); - - const GeomProp::CurveAnalysis aResult = aProp.FindCurvatureExtrema(); - ASSERT_TRUE(aResult.IsDone); - // Trimmed range [PI/4, 3*PI/4] includes minor vertex at PI/2 => extremum - for (int i = 0; i < aResult.Points.Length(); ++i) - { - EXPECT_GE(aResult.Points[i].Parameter, M_PI / 4.0 - Precision::Confusion()); - EXPECT_LE(aResult.Points[i].Parameter, 3.0 * M_PI / 4.0 + Precision::Confusion()); - } -} - -TEST(GeomProp_OtherCurveTest, FindInflections_TrimmedEllipse) -{ - occ::handle aTrimmed = makeTrimmedEllipse(); - GeomProp_Curve aProp(aTrimmed); - - const GeomProp::CurveAnalysis aResult = aProp.FindInflections(); - ASSERT_TRUE(aResult.IsDone); - // Ellipse is convex => no inflections in any trimmed range - EXPECT_EQ(aResult.Points.Length(), 0); -} - -// ============================================================================ -// GetType test -// ============================================================================ - -TEST(GeomProp_OtherCurveTest, GetType_IsOtherCurve) -{ - occ::handle aTrimmed = makeTrimmedCircle(); - GeomProp_Curve aProp(aTrimmed); - // Note: GeomAdaptor unwraps TrimmedCurve to the base curve type, - // so a trimmed circle is identified as GeomAbs_Circle, not OtherCurve. - EXPECT_EQ(aProp.GetType(), GeomAbs_Circle); -} - -// ============================================================================ -// VsCLProps comparison tests -// ============================================================================ - -TEST(GeomProp_OtherCurveTest, VsCLProps_TrimmedCircle) -{ - occ::handle aTrimmed = makeTrimmedCircle(); - compareAll(aTrimmed, 0.0, M_PI / 2.0); -} - -TEST(GeomProp_OtherCurveTest, VsCLProps_TrimmedEllipse) -{ - occ::handle aTrimmed = makeTrimmedEllipse(); - compareAll(aTrimmed, M_PI / 4.0, 3.0 * M_PI / 4.0); -} - -TEST(GeomProp_OtherCurveTest, VsCLProps_TrimmedBezier) -{ - occ::handle aTrimmed = makeTrimmedBezier(); - compareAll(aTrimmed, 0.1, 0.9); -} - -TEST(GeomProp_OtherCurveTest, VsCLProps_AllProperties_TrimmedCircle) -{ - occ::handle aTrimmed = makeTrimmedCircle(); - compareAll(aTrimmed, 0.0, M_PI / 2.0, 20); -} - -TEST(GeomProp_OtherCurveTest, VsCLProps_AllProperties_TrimmedEllipse) -{ - occ::handle aTrimmed = makeTrimmedEllipse(); - compareAll(aTrimmed, M_PI / 4.0, 3.0 * M_PI / 4.0, 20); -} - -TEST(GeomProp_OtherCurveTest, VsCLProps_AllProperties_TrimmedBezier) -{ - occ::handle aTrimmed = makeTrimmedBezier(); - compareAll(aTrimmed, 0.1, 0.9, 20); -} - -// ============================================================================ -// Trimmed hyperbola tests -// ============================================================================ - -TEST(GeomProp_OtherCurveTest, Curvature_TrimmedHyperbola) -{ - occ::handle aTrimmed = makeTrimmedHyperbola(); - GeomProp_Curve aProp(aTrimmed); - - for (double aParam = -1.0; aParam <= 1.0; aParam += 0.5) - { - const GeomProp::CurvatureResult aCurv = aProp.Curvature(aParam, THE_LIN_TOL); - ASSERT_TRUE(aCurv.IsDefined) << "Curvature undefined at param=" << aParam; - EXPECT_GT(aCurv.Value, 0.0) << "Curvature should be positive at param=" << aParam; - } -} - -// ============================================================================ -// Trimmed Bezier extrema / inflections tests -// ============================================================================ - -TEST(GeomProp_OtherCurveTest, FindCurvatureExtrema_TrimmedBezier) -{ - occ::handle aTrimmed = makeTrimmedBezier(); - GeomProp_Curve aProp(aTrimmed); - - const GeomProp::CurveAnalysis aResult = aProp.FindCurvatureExtrema(); - ASSERT_TRUE(aResult.IsDone); - for (int i = 0; i < aResult.Points.Length(); ++i) - { - EXPECT_GE(aResult.Points[i].Parameter, 0.1 - Precision::Confusion()); - EXPECT_LE(aResult.Points[i].Parameter, 0.9 + Precision::Confusion()); - EXPECT_TRUE(aResult.Points[i].Type == GeomProp::CIType::MinCurvature - || aResult.Points[i].Type == GeomProp::CIType::MaxCurvature); - } -} - -TEST(GeomProp_OtherCurveTest, FindInflections_TrimmedBezier) -{ - occ::handle aTrimmed = makeTrimmedBezier(); - GeomProp_Curve aProp(aTrimmed); - - const GeomProp::CurveAnalysis aResult = aProp.FindInflections(); - ASSERT_TRUE(aResult.IsDone); - // S-shaped Bezier should have an inflection in the trimmed range [0.1, 0.9] - for (int i = 0; i < aResult.Points.Length(); ++i) - { - EXPECT_GE(aResult.Points[i].Parameter, 0.1 - Precision::Confusion()); - EXPECT_LE(aResult.Points[i].Parameter, 0.9 + Precision::Confusion()); - EXPECT_EQ(aResult.Points[i].Type, GeomProp::CIType::Inflection); - } -} - -TEST(GeomProp_OtherCurveTest, VsCLProps_CriticalPoints) -{ - // Trimmed circle - occ::handle aCircle = new Geom_Circle(gp_Ax2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), 5.0); - occ::handle aTrimmed = - new Geom_TrimmedCurve(aCircle, M_PI / 4.0, 3.0 * M_PI / 4.0); - const double aFirst = aTrimmed->FirstParameter(); - const double aLast = aTrimmed->LastParameter(); - const double aMid = (aFirst + aLast) / 2.0; - const double aParams[] = {aFirst, - aFirst + 1.0e-10, - aFirst + 1.0e-6, - aMid, - aMid + 1.0e-6, - aMid - 1.0e-6, - aLast - 1.0e-6, - aLast - 1.0e-10, - aLast}; - for (const double aParam : aParams) - { - compareTangent(aTrimmed, aParam); - compareCurvature(aTrimmed, aParam); - compareNormal(aTrimmed, aParam); - compareCentre(aTrimmed, aParam); - } -} diff --git a/src/ModelingData/TKG3d/GTests/GeomProp_OtherSurface_Test.cxx b/src/ModelingData/TKG3d/GTests/GeomProp_OtherSurface_Test.cxx deleted file mode 100644 index 6910021bc6..0000000000 --- a/src/ModelingData/TKG3d/GTests/GeomProp_OtherSurface_Test.cxx +++ /dev/null @@ -1,391 +0,0 @@ -// 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. - -// Tests for GeomProp_Surface with Geom_RectangularTrimmedSurface (OtherSurface). -// Validates normal, curvatures, mean/Gaussian curvature for trimmed surfaces -// created from spheres, cylinders, planes, and tori. -// Cross-validates against GeomLProp_SLProps. - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -namespace -{ -constexpr double THE_LIN_TOL = Precision::PConfusion(); -constexpr double THE_CURV_TOL = 1.0e-6; -constexpr double THE_DIR_TOL = 1.0e-4; - -//! Compare surface normal from new GeomProp_Surface vs old GeomLProp_SLProps. -void compareNormal(const occ::handle& theSurf, const double theU, const double theV) -{ - GeomProp_Surface aProp(theSurf); - const GeomProp::SurfaceNormalResult aNew = aProp.Normal(theU, theV, THE_LIN_TOL); - - GeomLProp_SLProps anOld(theSurf, theU, theV, 2, THE_LIN_TOL); - if (anOld.IsNormalDefined()) - { - ASSERT_TRUE(aNew.IsDefined) << "New normal undefined at (" << theU << "," << theV << ")"; - const double aDot = aNew.Direction.Dot(anOld.Normal()); - EXPECT_NEAR(std::abs(aDot), 1.0, THE_DIR_TOL) - << "Normal mismatch at (" << theU << "," << theV << ")"; - } -} - -//! Compare curvatures from new GeomProp_Surface vs old GeomLProp_SLProps. -void compareCurvatures(const occ::handle& theSurf, - const double theU, - const double theV) -{ - GeomProp_Surface aProp(theSurf); - const GeomProp::SurfaceCurvatureResult aNew = aProp.Curvatures(theU, theV, THE_LIN_TOL); - - GeomLProp_SLProps anOld(theSurf, theU, theV, 2, THE_LIN_TOL); - if (anOld.IsCurvatureDefined()) - { - ASSERT_TRUE(aNew.IsDefined) << "New curvatures undefined at (" << theU << "," << theV << ")"; - EXPECT_NEAR(aNew.MinCurvature, anOld.MinCurvature(), THE_CURV_TOL) - << "MinCurvature mismatch at (" << theU << "," << theV << ")"; - EXPECT_NEAR(aNew.MaxCurvature, anOld.MaxCurvature(), THE_CURV_TOL) - << "MaxCurvature mismatch at (" << theU << "," << theV << ")"; - } -} - -//! Compare mean and Gaussian curvatures. -void compareMeanGaussian(const occ::handle& theSurf, - const double theU, - const double theV) -{ - GeomProp_Surface aProp(theSurf); - const GeomProp::MeanGaussianResult aNew = aProp.MeanGaussian(theU, theV, THE_LIN_TOL); - - GeomLProp_SLProps anOld(theSurf, theU, theV, 2, THE_LIN_TOL); - if (anOld.IsCurvatureDefined()) - { - ASSERT_TRUE(aNew.IsDefined) << "New MeanGaussian undefined at (" << theU << "," << theV << ")"; - EXPECT_NEAR(aNew.MeanCurvature, anOld.MeanCurvature(), THE_CURV_TOL) - << "Mean curvature mismatch at (" << theU << "," << theV << ")"; - EXPECT_NEAR(aNew.GaussianCurvature, anOld.GaussianCurvature(), THE_CURV_TOL) - << "Gaussian curvature mismatch at (" << theU << "," << theV << ")"; - } -} - -//! Run all surface comparisons at a grid of parameter values. -void compareAllSurface(const occ::handle& theSurf, - const double theUMin, - const double theUMax, - const double theVMin, - const double theVMax, - const int theNbU = 5, - const int theNbV = 5) -{ - const double aUStep = (theUMax - theUMin) / theNbU; - const double aVStep = (theVMax - theVMin) / theNbV; - for (int i = 0; i <= theNbU; ++i) - { - for (int j = 0; j <= theNbV; ++j) - { - const double aU = theUMin + i * aUStep; - const double aV = theVMin + j * aVStep; - compareNormal(theSurf, aU, aV); - compareCurvatures(theSurf, aU, aV); - compareMeanGaussian(theSurf, aU, aV); - } - } -} - -//! Trimmed sphere: R=8, U in [0.5, 2.5], V in [-0.8, 0.8]. -occ::handle makeTrimmedSphere() -{ - occ::handle aSphere = new Geom_SphericalSurface(gp_Ax3(), 8.0); - return new Geom_RectangularTrimmedSurface(aSphere, 0.5, 2.5, -0.8, 0.8); -} - -//! Trimmed cylinder: R=5, U in [0.3, 3.0], V in [-4.0, 4.0]. -occ::handle makeTrimmedCylinder() -{ - occ::handle aCyl = new Geom_CylindricalSurface(gp_Ax3(), 5.0); - return new Geom_RectangularTrimmedSurface(aCyl, 0.3, 3.0, -4.0, 4.0); -} - -//! Trimmed plane: U in [-3.0, 3.0], V in [-3.0, 3.0]. -occ::handle makeTrimmedPlane() -{ - occ::handle aPlane = new Geom_Plane(gp_Ax3()); - return new Geom_RectangularTrimmedSurface(aPlane, -3.0, 3.0, -3.0, 3.0); -} - -//! Trimmed torus: major R=10, minor R=3, U in [0.5, 5.0], V in [0.5, 5.0]. -occ::handle makeTrimmedTorus() -{ - occ::handle aTorus = new Geom_ToroidalSurface(gp_Ax3(), 10.0, 3.0); - return new Geom_RectangularTrimmedSurface(aTorus, 0.5, 5.0, 0.5, 5.0); -} -} // namespace - -// Normal of trimmed sphere in the trimmed range -TEST(GeomProp_OtherSurfaceTest, Normal_TrimmedSphere) -{ - occ::handle aSurf = makeTrimmedSphere(); - GeomProp_Surface aProp(aSurf); - - const GeomProp::SurfaceNormalResult aResult = aProp.Normal(1.5, 0.0, THE_LIN_TOL); - ASSERT_TRUE(aResult.IsDefined); -} - -// Curvatures of trimmed sphere: k = 1/R -TEST(GeomProp_OtherSurfaceTest, Curvatures_TrimmedSphere) -{ - occ::handle aSurf = makeTrimmedSphere(); - GeomProp_Surface aProp(aSurf); - - const double aExpectedK = 1.0 / 8.0; - const GeomProp::SurfaceCurvatureResult aResult = aProp.Curvatures(1.5, 0.0, THE_LIN_TOL); - ASSERT_TRUE(aResult.IsDefined); - EXPECT_NEAR(std::abs(aResult.MinCurvature), aExpectedK, THE_CURV_TOL); - EXPECT_NEAR(std::abs(aResult.MaxCurvature), aExpectedK, THE_CURV_TOL); -} - -// Mean and Gaussian curvature of trimmed sphere -TEST(GeomProp_OtherSurfaceTest, MeanGaussian_TrimmedSphere) -{ - occ::handle aSurf = makeTrimmedSphere(); - GeomProp_Surface aProp(aSurf); - - const GeomProp::MeanGaussianResult aResult = aProp.MeanGaussian(1.5, 0.0, THE_LIN_TOL); - ASSERT_TRUE(aResult.IsDefined); - const double aExpectedK = 1.0 / 8.0; - const double aExpectedGK = aExpectedK * aExpectedK; - EXPECT_NEAR(std::abs(aResult.MeanCurvature), aExpectedK, THE_CURV_TOL); - EXPECT_NEAR(aResult.GaussianCurvature, aExpectedGK, THE_CURV_TOL); -} - -// Normal of trimmed cylinder -TEST(GeomProp_OtherSurfaceTest, Normal_TrimmedCylinder) -{ - occ::handle aSurf = makeTrimmedCylinder(); - GeomProp_Surface aProp(aSurf); - - const GeomProp::SurfaceNormalResult aResult = aProp.Normal(1.5, 0.0, THE_LIN_TOL); - ASSERT_TRUE(aResult.IsDefined); - // Normal should be perpendicular to Z axis - EXPECT_NEAR(aResult.Direction.Z(), 0.0, THE_DIR_TOL); -} - -// Curvatures of trimmed cylinder -TEST(GeomProp_OtherSurfaceTest, Curvatures_TrimmedCylinder) -{ - occ::handle aSurf = makeTrimmedCylinder(); - GeomProp_Surface aProp(aSurf); - - const double aExpectedK = 1.0 / 5.0; - const GeomProp::SurfaceCurvatureResult aResult = aProp.Curvatures(1.5, 0.0, THE_LIN_TOL); - ASSERT_TRUE(aResult.IsDefined); - // MinCurvature = -1/R (concave, signed), MaxCurvature = 0 (along axis). - EXPECT_NEAR(aResult.MinCurvature, -aExpectedK, THE_CURV_TOL); - EXPECT_NEAR(aResult.MaxCurvature, 0.0, THE_CURV_TOL); -} - -// Mean and Gaussian curvature of trimmed cylinder -TEST(GeomProp_OtherSurfaceTest, MeanGaussian_TrimmedCylinder) -{ - occ::handle aSurf = makeTrimmedCylinder(); - GeomProp_Surface aProp(aSurf); - - const GeomProp::MeanGaussianResult aResult = aProp.MeanGaussian(1.5, 0.0, THE_LIN_TOL); - ASSERT_TRUE(aResult.IsDefined); - EXPECT_NEAR(aResult.GaussianCurvature, 0.0, THE_CURV_TOL); -} - -// GetType returns the base surface type because GeomAdaptor unwraps -// RectangularTrimmedSurface to its underlying surface type. -TEST(GeomProp_OtherSurfaceTest, GetType_IsOtherSurface) -{ - occ::handle aSurf = makeTrimmedSphere(); - GeomProp_Surface aProp(aSurf); - EXPECT_EQ(aProp.GetType(), GeomAbs_Sphere); -} - -// Cross-validate trimmed sphere vs SLProps -TEST(GeomProp_OtherSurfaceTest, VsSLProps_TrimmedSphere) -{ - occ::handle aSurf = makeTrimmedSphere(); - compareAllSurface(aSurf, 0.5, 2.5, -0.8, 0.8); -} - -// Cross-validate trimmed cylinder vs SLProps -TEST(GeomProp_OtherSurfaceTest, VsSLProps_TrimmedCylinder) -{ - occ::handle aSurf = makeTrimmedCylinder(); - compareAllSurface(aSurf, 0.3, 3.0, -4.0, 4.0); -} - -// Dense cross-validation for trimmed sphere -TEST(GeomProp_OtherSurfaceTest, VsSLProps_AllProperties_Sphere) -{ - occ::handle aSurf = makeTrimmedSphere(); - compareAllSurface(aSurf, 0.5, 2.5, -0.8, 0.8, 6, 6); -} - -// Dense cross-validation for trimmed cylinder -TEST(GeomProp_OtherSurfaceTest, VsSLProps_AllProperties_Cylinder) -{ - occ::handle aSurf = makeTrimmedCylinder(); - compareAllSurface(aSurf, 0.3, 3.0, -4.0, 4.0, 6, 6); -} - -// Normal of trimmed plane: constant -TEST(GeomProp_OtherSurfaceTest, Normal_TrimmedPlane) -{ - occ::handle aSurf = makeTrimmedPlane(); - GeomProp_Surface aProp(aSurf); - - const gp_Dir aExpected(0.0, 0.0, 1.0); - for (double aU = -3.0; aU <= 3.0; aU += 1.5) - { - for (double aV = -3.0; aV <= 3.0; aV += 1.5) - { - const GeomProp::SurfaceNormalResult aResult = aProp.Normal(aU, aV, THE_LIN_TOL); - ASSERT_TRUE(aResult.IsDefined); - const double aDot = aResult.Direction.Dot(aExpected); - EXPECT_NEAR(std::abs(aDot), 1.0, THE_DIR_TOL); - } - } -} - -// Curvatures of trimmed plane: zeros -TEST(GeomProp_OtherSurfaceTest, Curvatures_TrimmedPlane) -{ - occ::handle aSurf = makeTrimmedPlane(); - GeomProp_Surface aProp(aSurf); - - const GeomProp::SurfaceCurvatureResult aResult = aProp.Curvatures(0.0, 0.0, THE_LIN_TOL); - ASSERT_TRUE(aResult.IsDefined); - EXPECT_NEAR(aResult.MinCurvature, 0.0, THE_CURV_TOL); - EXPECT_NEAR(aResult.MaxCurvature, 0.0, THE_CURV_TOL); -} - -// Mean and Gaussian curvature of trimmed plane: zeros -TEST(GeomProp_OtherSurfaceTest, MeanGaussian_TrimmedPlane) -{ - occ::handle aSurf = makeTrimmedPlane(); - GeomProp_Surface aProp(aSurf); - - const GeomProp::MeanGaussianResult aResult = aProp.MeanGaussian(0.0, 0.0, THE_LIN_TOL); - ASSERT_TRUE(aResult.IsDefined); - EXPECT_NEAR(aResult.MeanCurvature, 0.0, THE_CURV_TOL); - EXPECT_NEAR(aResult.GaussianCurvature, 0.0, THE_CURV_TOL); -} - -// Cross-validate trimmed plane vs SLProps -TEST(GeomProp_OtherSurfaceTest, VsSLProps_TrimmedPlane) -{ - occ::handle aSurf = makeTrimmedPlane(); - compareAllSurface(aSurf, -3.0, 3.0, -3.0, 3.0); -} - -// Normal of trimmed torus -TEST(GeomProp_OtherSurfaceTest, Normal_TrimmedTorus) -{ - occ::handle aSurf = makeTrimmedTorus(); - GeomProp_Surface aProp(aSurf); - - const GeomProp::SurfaceNormalResult aResult = aProp.Normal(2.0, 2.0, THE_LIN_TOL); - ASSERT_TRUE(aResult.IsDefined); -} - -// Curvatures of trimmed torus -TEST(GeomProp_OtherSurfaceTest, Curvatures_TrimmedTorus) -{ - occ::handle aSurf = makeTrimmedTorus(); - GeomProp_Surface aProp(aSurf); - - const GeomProp::SurfaceCurvatureResult aResult = aProp.Curvatures(2.0, 2.0, THE_LIN_TOL); - ASSERT_TRUE(aResult.IsDefined); - EXPECT_LE(aResult.MinCurvature, aResult.MaxCurvature); - // Both curvatures should be non-zero on a torus - EXPECT_GT(std::abs(aResult.MinCurvature), THE_CURV_TOL); - EXPECT_GT(std::abs(aResult.MaxCurvature), THE_CURV_TOL); -} - -// Mean and Gaussian curvature of trimmed torus -TEST(GeomProp_OtherSurfaceTest, MeanGaussian_TrimmedTorus) -{ - occ::handle aSurf = makeTrimmedTorus(); - GeomProp_Surface aProp(aSurf); - - const GeomProp::MeanGaussianResult aResult = aProp.MeanGaussian(2.0, 2.0, THE_LIN_TOL); - ASSERT_TRUE(aResult.IsDefined); -} - -// Cross-validate trimmed torus vs SLProps -TEST(GeomProp_OtherSurfaceTest, VsSLProps_TrimmedTorus) -{ - occ::handle aSurf = makeTrimmedTorus(); - compareAllSurface(aSurf, 0.5, 5.0, 0.5, 5.0); -} - -// Dense 8x8 grid cross-validation for trimmed sphere -TEST(GeomProp_OtherSurfaceTest, VsSLProps_DenseGrid_Sphere) -{ - occ::handle aSurf = makeTrimmedSphere(); - compareAllSurface(aSurf, 0.5, 2.5, -0.8, 0.8, 8, 8); -} - -TEST(GeomProp_OtherSurfaceTest, VsSLProps_CriticalPoints) -{ - // Trimmed sphere - occ::handle aSphere = new Geom_SphericalSurface(gp_Ax3(), 5.0); - occ::handle aSurf = - new Geom_RectangularTrimmedSurface(aSphere, - M_PI / 4.0, - 3.0 * M_PI / 4.0, - -M_PI / 4.0, - M_PI / 4.0); - double aUF, aUL, aVF, aVL; - aSurf->Bounds(aUF, aUL, aVF, aVL); - const double aUMid = (aUF + aUL) / 2.0; - const double aVMid = (aVF + aVL) / 2.0; - // Critical: corners, edge midpoints, center, near-corners - const double aParams[][2] = {{aUF, aVF}, - {aUL, aVF}, - {aUF, aVL}, - {aUL, aVL}, - {aUMid, aVF}, - {aUMid, aVL}, - {aUF, aVMid}, - {aUL, aVMid}, - {aUMid, aVMid}, - {aUF + 1.0e-10, aVF + 1.0e-10}, - {aUL - 1.0e-10, aVL - 1.0e-10}, - {aUMid, aVMid + 1.0e-6}}; - for (const auto& aUV : aParams) - { - compareNormal(aSurf, aUV[0], aUV[1]); - compareCurvatures(aSurf, aUV[0], aUV[1]); - compareMeanGaussian(aSurf, aUV[0], aUV[1]); - } -} diff --git a/src/ModelingData/TKG3d/GTests/GeomProp_Parabola_Test.cxx b/src/ModelingData/TKG3d/GTests/GeomProp_Parabola_Test.cxx deleted file mode 100644 index 61ae7fdc0d..0000000000 --- a/src/ModelingData/TKG3d/GTests/GeomProp_Parabola_Test.cxx +++ /dev/null @@ -1,425 +0,0 @@ -// 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. - -// Tests for GeomProp_Curve with Geom_Parabola curves. -// Validates curvature, tangent, normal, and centre of curvature properties -// against analytical formulas and cross-validates against GeomLProp_CLProps. - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -namespace -{ -constexpr double THE_LIN_TOL = Precision::PConfusion(); -constexpr double THE_CURV_TOL = 1.0e-8; -constexpr double THE_DIR_TOL = 1.0e-6; -constexpr double THE_POINT_TOL = 1.0e-6; - -//! Compare tangent from new GeomProp_Curve vs old GeomLProp_CLProps. -void compareTangent(const occ::handle& theCurve, const double theParam) -{ - GeomProp_Curve aProp(theCurve); - const GeomProp::TangentResult aNew = aProp.Tangent(theParam, THE_LIN_TOL); - - GeomLProp_CLProps anOld(theCurve, theParam, 2, THE_LIN_TOL); - if (anOld.IsTangentDefined()) - { - ASSERT_TRUE(aNew.IsDefined) << "New tangent undefined but old is defined at param=" << theParam; - gp_Dir anOldDir; - anOld.Tangent(anOldDir); - const double aDot = aNew.Direction.Dot(anOldDir); - EXPECT_NEAR(std::abs(aDot), 1.0, THE_DIR_TOL) - << "Tangent direction mismatch at param=" << theParam; - } -} - -//! Compare curvature from new GeomProp_Curve vs old GeomLProp_CLProps. -void compareCurvature(const occ::handle& theCurve, const double theParam) -{ - GeomProp_Curve aProp(theCurve); - const GeomProp::CurvatureResult aNew = aProp.Curvature(theParam, THE_LIN_TOL); - - GeomLProp_CLProps anOld(theCurve, theParam, 2, THE_LIN_TOL); - if (anOld.IsTangentDefined()) - { - ASSERT_TRUE(aNew.IsDefined) << "New curvature undefined at param=" << theParam; - EXPECT_NEAR(aNew.Value, anOld.Curvature(), THE_CURV_TOL) - << "Curvature mismatch at param=" << theParam; - } -} - -//! Compare normal from new GeomProp_Curve vs old GeomLProp_CLProps. -void compareNormal(const occ::handle& theCurve, const double theParam) -{ - GeomProp_Curve aProp(theCurve); - const GeomProp::NormalResult aNew = aProp.Normal(theParam, THE_LIN_TOL); - - GeomLProp_CLProps anOld(theCurve, theParam, 2, THE_LIN_TOL); - if (anOld.IsTangentDefined() && std::abs(anOld.Curvature()) > THE_LIN_TOL) - { - ASSERT_TRUE(aNew.IsDefined) << "New normal undefined at param=" << theParam; - gp_Dir anOldNorm; - anOld.Normal(anOldNorm); - const double aDot = aNew.Direction.Dot(anOldNorm); - EXPECT_NEAR(std::abs(aDot), 1.0, THE_DIR_TOL) - << "Normal direction mismatch at param=" << theParam; - } -} - -//! Compare centre of curvature from new vs old. -void compareCentre(const occ::handle& theCurve, const double theParam) -{ - GeomProp_Curve aProp(theCurve); - const GeomProp::CentreResult aNew = aProp.CentreOfCurvature(theParam, THE_LIN_TOL); - - GeomLProp_CLProps anOld(theCurve, theParam, 2, THE_LIN_TOL); - if (anOld.IsTangentDefined() && std::abs(anOld.Curvature()) > THE_LIN_TOL) - { - ASSERT_TRUE(aNew.IsDefined) << "New centre undefined at param=" << theParam; - gp_Pnt anOldCentre; - anOld.CentreOfCurvature(anOldCentre); - EXPECT_NEAR(aNew.Centre.Distance(anOldCentre), 0.0, THE_POINT_TOL) - << "Centre mismatch at param=" << theParam; - } -} - -//! Run all comparisons at several parameter values. -void compareAll(const occ::handle& theCurve, - const double theFirst, - const double theLast, - const int theNbSamples = 10) -{ - const double aStep = (theLast - theFirst) / theNbSamples; - for (int i = 0; i <= theNbSamples; ++i) - { - const double aParam = theFirst + i * aStep; - compareTangent(theCurve, aParam); - compareCurvature(theCurve, aParam); - compareNormal(theCurve, aParam); - compareCentre(theCurve, aParam); - } -} -} // namespace - -// Curvature at vertex (t=0): k = 1/(2f) -TEST(GeomProp_ParabolaTest, Curvature_AtVertex) -{ - const double aFocal = 2.0; - gp_Parab aParab(gp_Ax2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), aFocal); - occ::handle aParabola = new Geom_Parabola(aParab); - GeomProp_Curve aProp(aParabola); - const GeomProp::CurvatureResult aCurv = aProp.Curvature(0.0, THE_LIN_TOL); - ASSERT_TRUE(aCurv.IsDefined); - const double aExpected = 1.0 / (2.0 * aFocal); - EXPECT_NEAR(aCurv.Value, aExpected, THE_CURV_TOL); -} - -// Curvature is symmetric: k(t) = k(-t) -TEST(GeomProp_ParabolaTest, Curvature_Symmetric) -{ - gp_Parab aParab(gp_Ax2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), 2.0); - occ::handle aParabola = new Geom_Parabola(aParab); - GeomProp_Curve aProp(aParabola); - - for (double aT = 0.5; aT <= 5.0; aT += 0.5) - { - const GeomProp::CurvatureResult aPos = aProp.Curvature(aT, THE_LIN_TOL); - const GeomProp::CurvatureResult aNeg = aProp.Curvature(-aT, THE_LIN_TOL); - ASSERT_TRUE(aPos.IsDefined); - ASSERT_TRUE(aNeg.IsDefined); - EXPECT_NEAR(aPos.Value, aNeg.Value, THE_CURV_TOL) << "Asymmetry at t=" << aT; - } -} - -// Curvature decreases from vertex as |t| increases -TEST(GeomProp_ParabolaTest, Curvature_DecreasesFromVertex) -{ - gp_Parab aParab(gp_Ax2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), 2.0); - occ::handle aParabola = new Geom_Parabola(aParab); - GeomProp_Curve aProp(aParabola); - - const GeomProp::CurvatureResult aCurvVertex = aProp.Curvature(0.0, THE_LIN_TOL); - ASSERT_TRUE(aCurvVertex.IsDefined); - - double aPrevCurv = aCurvVertex.Value; - for (double aT = 1.0; aT <= 5.0; aT += 1.0) - { - const GeomProp::CurvatureResult aCurv = aProp.Curvature(aT, THE_LIN_TOL); - ASSERT_TRUE(aCurv.IsDefined); - EXPECT_LT(aCurv.Value, aPrevCurv) << "Curvature did not decrease at t=" << aT; - aPrevCurv = aCurv.Value; - } -} - -// Tangent at vertex is perpendicular to axis -TEST(GeomProp_ParabolaTest, Tangent_AtVertex) -{ - gp_Ax2 anAx2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)); - gp_Parab aParab(anAx2, 2.0); - occ::handle aParabola = new Geom_Parabola(aParab); - GeomProp_Curve aProp(aParabola); - - const GeomProp::TangentResult aTan = aProp.Tangent(0.0, THE_LIN_TOL); - ASSERT_TRUE(aTan.IsDefined); - // Axis of symmetry is X direction - const gp_Dir anAxis = anAx2.XDirection(); - EXPECT_NEAR(std::abs(aTan.Direction.Dot(anAxis)), 0.0, THE_DIR_TOL); -} - -// Normal at vertex along axis toward focus -TEST(GeomProp_ParabolaTest, Normal_AtVertex) -{ - gp_Ax2 anAx2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)); - gp_Parab aParab(anAx2, 2.0); - occ::handle aParabola = new Geom_Parabola(aParab); - GeomProp_Curve aProp(aParabola); - - const GeomProp::NormalResult aNorm = aProp.Normal(0.0, THE_LIN_TOL); - ASSERT_TRUE(aNorm.IsDefined); - // Normal at vertex should be along the axis (X direction) - const gp_Dir anAxis = anAx2.XDirection(); - EXPECT_NEAR(std::abs(aNorm.Direction.Dot(anAxis)), 1.0, THE_DIR_TOL); -} - -// Centre at vertex is at distance 2f from vertex (coincides with focus) -TEST(GeomProp_ParabolaTest, Centre_AtVertex) -{ - const double aFocal = 2.0; - gp_Parab aParab(gp_Ax2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), aFocal); - occ::handle aParabola = new Geom_Parabola(aParab); - GeomProp_Curve aProp(aParabola); - - const GeomProp::CentreResult aCentre = aProp.CentreOfCurvature(0.0, THE_LIN_TOL); - ASSERT_TRUE(aCentre.IsDefined); - - // Vertex of parabola - gp_Pnt aVertex; - aParabola->D0(0.0, aVertex); - - // Radius of curvature at vertex = 1/k = 2f - const double aRadiusOfCurv = 2.0 * aFocal; - EXPECT_NEAR(aCentre.Centre.Distance(aVertex), aRadiusOfCurv, THE_POINT_TOL); -} - -// FindCurvatureExtrema returns 1 extremum at t=0 -TEST(GeomProp_ParabolaTest, FindCurvatureExtrema_OnePoint) -{ - gp_Parab aParab(gp_Ax2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), 2.0); - occ::handle aParabola = new Geom_Parabola(aParab); - GeomProp_Curve aProp(aParabola); - - const GeomProp::CurveAnalysis aResult = aProp.FindCurvatureExtrema(); - ASSERT_TRUE(aResult.IsDone); - EXPECT_EQ(aResult.Points.Length(), 1); - EXPECT_NEAR(aResult.Points[0].Parameter, 0.0, Precision::Confusion()); -} - -// FindInflections returns no inflections -TEST(GeomProp_ParabolaTest, FindInflections_Empty) -{ - gp_Parab aParab(gp_Ax2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), 2.0); - occ::handle aParabola = new Geom_Parabola(aParab); - GeomProp_Curve aProp(aParabola); - - const GeomProp::CurveAnalysis aResult = aProp.FindInflections(); - ASSERT_TRUE(aResult.IsDone); - EXPECT_EQ(aResult.Points.Length(), 0); -} - -// GetType returns GeomAbs_Parabola -TEST(GeomProp_ParabolaTest, GetType_IsParabola) -{ - gp_Parab aParab(gp_Ax2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), 2.0); - occ::handle aParabola = new Geom_Parabola(aParab); - GeomProp_Curve aProp(aParabola); - EXPECT_EQ(aProp.GetType(), GeomAbs_Parabola); -} - -// Curvature approaches 0 for large |t| -TEST(GeomProp_ParabolaTest, Curvature_LargeParam) -{ - gp_Parab aParab(gp_Ax2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), 2.0); - occ::handle aParabola = new Geom_Parabola(aParab); - GeomProp_Curve aProp(aParabola); - - const GeomProp::CurvatureResult aCurv = aProp.Curvature(50.0, THE_LIN_TOL); - ASSERT_TRUE(aCurv.IsDefined); - EXPECT_LT(aCurv.Value, 0.001); -} - -// Cross-validate vs CLProps: f=2 -TEST(GeomProp_ParabolaTest, VsCLProps_Standard) -{ - gp_Parab aParab(gp_Ax2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), 2.0); - occ::handle aParabola = new Geom_Parabola(aParab); - compareAll(aParabola, -5.0, 5.0); -} - -// Dense cross-validation on [-5, 5] -TEST(GeomProp_ParabolaTest, VsCLProps_AllProperties) -{ - gp_Parab aParab(gp_Ax2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), 2.0); - occ::handle aParabola = new Geom_Parabola(aParab); - compareAll(aParabola, -5.0, 5.0, 20); -} - -// Cross-validate with small focal distance -TEST(GeomProp_ParabolaTest, VsCLProps_SmallFocal) -{ - gp_Parab aParab(gp_Ax2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), 0.1); - occ::handle aParabola = new Geom_Parabola(aParab); - compareAll(aParabola, -3.0, 3.0); -} - -// Cross-validate with large focal distance -TEST(GeomProp_ParabolaTest, VsCLProps_LargeFocal) -{ - gp_Parab aParab(gp_Ax2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), 50.0); - occ::handle aParabola = new Geom_Parabola(aParab); - compareAll(aParabola, -10.0, 10.0); -} - -// Cross-validate with off-center parabola -TEST(GeomProp_ParabolaTest, VsCLProps_OffCenter) -{ - gp_Parab aParab(gp_Ax2(gp_Pnt(3.0, 4.0, 5.0), gp_Dir(0, 0, 1)), 2.0); - occ::handle aParabola = new Geom_Parabola(aParab); - compareAll(aParabola, -5.0, 5.0); -} - -// Tangent for large parameter approaches axis direction -TEST(GeomProp_ParabolaTest, Tangent_LargeParam) -{ - gp_Ax2 anAx2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)); - gp_Parab aParab(anAx2, 2.0); - occ::handle aParabola = new Geom_Parabola(aParab); - GeomProp_Curve aProp(aParabola); - - // For large t, the parabola tangent approaches the axis direction (X direction) - const gp_Dir anAxis = anAx2.XDirection(); - - const GeomProp::TangentResult aTan = aProp.Tangent(100.0, THE_LIN_TOL); - ASSERT_TRUE(aTan.IsDefined); - EXPECT_NEAR(std::abs(aTan.Direction.Dot(anAxis)), 1.0, 1.0e-3); -} - -// Centre moves away from vertex as |t| increases -TEST(GeomProp_ParabolaTest, Centre_MovesAway) -{ - gp_Parab aParab(gp_Ax2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), 2.0); - occ::handle aParabola = new Geom_Parabola(aParab); - GeomProp_Curve aProp(aParabola); - - gp_Pnt aVertex; - aParabola->D0(0.0, aVertex); - - const GeomProp::CentreResult aCentreAtVertex = aProp.CentreOfCurvature(0.0, THE_LIN_TOL); - ASSERT_TRUE(aCentreAtVertex.IsDefined); - - double aPrevDist = aCentreAtVertex.Centre.Distance(aVertex); - for (double aT = 1.0; aT <= 5.0; aT += 1.0) - { - const GeomProp::CentreResult aCentre = aProp.CentreOfCurvature(aT, THE_LIN_TOL); - ASSERT_TRUE(aCentre.IsDefined); - const double aDist = aCentre.Centre.Distance(aVertex); - EXPECT_GT(aDist, aPrevDist - THE_POINT_TOL) - << "Centre did not move away from vertex at t=" << aT; - aPrevDist = aDist; - } -} - -// Fine-grained curvature near vertex -TEST(GeomProp_ParabolaTest, Curvature_NearVertex) -{ - const double aFocal = 2.0; - gp_Parab aParab(gp_Ax2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), aFocal); - occ::handle aParabola = new Geom_Parabola(aParab); - GeomProp_Curve aProp(aParabola); - - const double aExpectedMax = 1.0 / (2.0 * aFocal); - for (double aT = 0.01; aT <= 0.1; aT += 0.01) - { - const GeomProp::CurvatureResult aCurv = aProp.Curvature(aT, THE_LIN_TOL); - ASSERT_TRUE(aCurv.IsDefined); - EXPECT_LT(aCurv.Value, aExpectedMax + THE_CURV_TOL) - << "Curvature exceeds vertex maximum at t=" << aT; - } -} - -// Cross-validate with tilted plane parabola -TEST(GeomProp_ParabolaTest, VsCLProps_TiltedPlane) -{ - gp_Ax2 anAx2(gp_Pnt(0, 0, 0), gp_Dir(1, 1, 1)); - gp_Parab aParab(anAx2, 2.0); - occ::handle aParabola = new Geom_Parabola(aParab); - compareAll(aParabola, -5.0, 5.0); -} - -// Normal directions are symmetric about vertex -TEST(GeomProp_ParabolaTest, Normal_Symmetric) -{ - gp_Parab aParab(gp_Ax2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), 2.0); - occ::handle aParabola = new Geom_Parabola(aParab); - GeomProp_Curve aProp(aParabola); - - for (double aT = 1.0; aT <= 4.0; aT += 1.0) - { - const GeomProp::NormalResult aNormPos = aProp.Normal(aT, THE_LIN_TOL); - const GeomProp::NormalResult aNormNeg = aProp.Normal(-aT, THE_LIN_TOL); - ASSERT_TRUE(aNormPos.IsDefined); - ASSERT_TRUE(aNormNeg.IsDefined); - // For a parabola symmetric about X-axis: - // Normal X-components should be equal, Y-components should be opposite in sign - EXPECT_NEAR(aNormPos.Direction.X(), aNormNeg.Direction.X(), THE_DIR_TOL) - << "Normal X asymmetry at t=" << aT; - } -} - -TEST(GeomProp_ParabolaTest, VsCLProps_CriticalPoints) -{ - gp_Parab aParab(gp_Ax2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), 5.0); - occ::handle aParabola = new Geom_Parabola(aParab); - const double aParams[] = {0.0, - 1.0e-10, - -1.0e-10, - 1.0e-6, - -1.0e-6, - 0.1, - -0.1, - 0.5, - -0.5, - 1.0, - -1.0, - 5.0, - -5.0, - 10.0, - -10.0}; - for (const double aParam : aParams) - { - compareTangent(aParabola, aParam); - compareCurvature(aParabola, aParam); - compareNormal(aParabola, aParam); - compareCentre(aParabola, aParam); - } -} diff --git a/src/ModelingData/TKG3d/GTests/GeomProp_Plane_Test.cxx b/src/ModelingData/TKG3d/GTests/GeomProp_Plane_Test.cxx deleted file mode 100644 index 2a6e687267..0000000000 --- a/src/ModelingData/TKG3d/GTests/GeomProp_Plane_Test.cxx +++ /dev/null @@ -1,371 +0,0 @@ -// 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. - -// Unit tests for GeomProp_Surface with Plane geometry. - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -namespace -{ -constexpr double THE_LIN_TOL = Precision::PConfusion(); -constexpr double THE_CURV_TOL = 1.0e-6; -constexpr double THE_DIR_TOL = 1.0e-4; - -void compareNormal(const occ::handle& theSurf, const double theU, const double theV) -{ - GeomProp_Surface aProp(theSurf); - const GeomProp::SurfaceNormalResult aNew = aProp.Normal(theU, theV, THE_LIN_TOL); - - GeomLProp_SLProps anOld(theSurf, theU, theV, 2, THE_LIN_TOL); - if (anOld.IsNormalDefined()) - { - ASSERT_TRUE(aNew.IsDefined) << "New normal undefined at (" << theU << "," << theV << ")"; - const double aDot = aNew.Direction.Dot(anOld.Normal()); - EXPECT_NEAR(std::abs(aDot), 1.0, THE_DIR_TOL) - << "Normal mismatch at (" << theU << "," << theV << ")"; - } -} - -void compareCurvatures(const occ::handle& theSurf, - const double theU, - const double theV) -{ - GeomProp_Surface aProp(theSurf); - const GeomProp::SurfaceCurvatureResult aNew = aProp.Curvatures(theU, theV, THE_LIN_TOL); - - GeomLProp_SLProps anOld(theSurf, theU, theV, 2, THE_LIN_TOL); - if (anOld.IsCurvatureDefined()) - { - ASSERT_TRUE(aNew.IsDefined) << "New curvatures undefined at (" << theU << "," << theV << ")"; - EXPECT_NEAR(aNew.MinCurvature, anOld.MinCurvature(), THE_CURV_TOL) - << "MinCurvature mismatch at (" << theU << "," << theV << ")"; - EXPECT_NEAR(aNew.MaxCurvature, anOld.MaxCurvature(), THE_CURV_TOL) - << "MaxCurvature mismatch at (" << theU << "," << theV << ")"; - } -} - -void compareMeanGaussian(const occ::handle& theSurf, - const double theU, - const double theV) -{ - GeomProp_Surface aProp(theSurf); - const GeomProp::MeanGaussianResult aNew = aProp.MeanGaussian(theU, theV, THE_LIN_TOL); - - GeomLProp_SLProps anOld(theSurf, theU, theV, 2, THE_LIN_TOL); - if (anOld.IsCurvatureDefined()) - { - ASSERT_TRUE(aNew.IsDefined) << "New MeanGaussian undefined at (" << theU << "," << theV << ")"; - EXPECT_NEAR(aNew.MeanCurvature, anOld.MeanCurvature(), THE_CURV_TOL) - << "Mean curvature mismatch at (" << theU << "," << theV << ")"; - EXPECT_NEAR(aNew.GaussianCurvature, anOld.GaussianCurvature(), THE_CURV_TOL) - << "Gaussian curvature mismatch at (" << theU << "," << theV << ")"; - } -} - -void compareAllSurface(const occ::handle& theSurf, - const double theUMin, - const double theUMax, - const double theVMin, - const double theVMax, - const int theNbU = 5, - const int theNbV = 5) -{ - const double aUStep = (theUMax - theUMin) / theNbU; - const double aVStep = (theVMax - theVMin) / theNbV; - for (int i = 0; i <= theNbU; ++i) - { - for (int j = 0; j <= theNbV; ++j) - { - const double aU = theUMin + i * aUStep; - const double aV = theVMin + j * aVStep; - compareNormal(theSurf, aU, aV); - compareCurvatures(theSurf, aU, aV); - compareMeanGaussian(theSurf, aU, aV); - } - } -} -} // namespace - -// ============================================================================ -// Analytical reference tests -// ============================================================================ - -TEST(GeomProp_PlaneTest, Normal_IsConstant) -{ - occ::handle aPlane = new Geom_Plane(gp_Ax3()); - GeomProp_Surface aProp(aPlane); - - const GeomProp::SurfaceNormalResult aNorm = aProp.Normal(0.0, 0.0, THE_LIN_TOL); - ASSERT_TRUE(aNorm.IsDefined); - EXPECT_NEAR(aNorm.Direction.X(), 0.0, THE_DIR_TOL); - EXPECT_NEAR(aNorm.Direction.Y(), 0.0, THE_DIR_TOL); - EXPECT_NEAR(std::abs(aNorm.Direction.Z()), 1.0, THE_DIR_TOL); -} - -TEST(GeomProp_PlaneTest, Normal_AllParams) -{ - occ::handle aPlane = new Geom_Plane(gp_Ax3()); - GeomProp_Surface aProp(aPlane); - - const GeomProp::SurfaceNormalResult aRef = aProp.Normal(0.0, 0.0, THE_LIN_TOL); - ASSERT_TRUE(aRef.IsDefined); - - for (int i = -5; i <= 5; ++i) - { - for (int j = -5; j <= 5; ++j) - { - const double aU = i * 2.0; - const double aV = j * 2.0; - const GeomProp::SurfaceNormalResult aNorm = aProp.Normal(aU, aV, THE_LIN_TOL); - ASSERT_TRUE(aNorm.IsDefined) << "Normal undefined at (" << aU << "," << aV << ")"; - const double aDot = aNorm.Direction.Dot(aRef.Direction); - EXPECT_NEAR(std::abs(aDot), 1.0, THE_DIR_TOL) - << "Normal differs at (" << aU << "," << aV << ")"; - } - } -} - -TEST(GeomProp_PlaneTest, Curvatures_AllZero) -{ - occ::handle aPlane = new Geom_Plane(gp_Ax3()); - GeomProp_Surface aProp(aPlane); - - const GeomProp::SurfaceCurvatureResult aCurv = aProp.Curvatures(0.0, 0.0, THE_LIN_TOL); - ASSERT_TRUE(aCurv.IsDefined); - EXPECT_NEAR(aCurv.MinCurvature, 0.0, THE_CURV_TOL); - EXPECT_NEAR(aCurv.MaxCurvature, 0.0, THE_CURV_TOL); -} - -TEST(GeomProp_PlaneTest, Curvatures_IsUmbilic) -{ - occ::handle aPlane = new Geom_Plane(gp_Ax3()); - GeomProp_Surface aProp(aPlane); - - // On a plane, min = max = 0, so the point is trivially umbilic. - for (int i = -3; i <= 3; ++i) - { - for (int j = -3; j <= 3; ++j) - { - const double aU = i * 1.5; - const double aV = j * 1.5; - const GeomProp::SurfaceCurvatureResult aCurv = aProp.Curvatures(aU, aV, THE_LIN_TOL); - ASSERT_TRUE(aCurv.IsDefined); - EXPECT_NEAR(aCurv.MinCurvature, aCurv.MaxCurvature, THE_CURV_TOL) - << "Not umbilic at (" << aU << "," << aV << ")"; - } - } -} - -TEST(GeomProp_PlaneTest, MeanGaussian_AllZero) -{ - occ::handle aPlane = new Geom_Plane(gp_Ax3()); - GeomProp_Surface aProp(aPlane); - - const GeomProp::MeanGaussianResult aMG = aProp.MeanGaussian(0.0, 0.0, THE_LIN_TOL); - ASSERT_TRUE(aMG.IsDefined); - EXPECT_NEAR(aMG.MeanCurvature, 0.0, THE_CURV_TOL); - EXPECT_NEAR(aMG.GaussianCurvature, 0.0, THE_CURV_TOL); -} - -TEST(GeomProp_PlaneTest, GetType_IsPlane) -{ - occ::handle aPlane = new Geom_Plane(gp_Ax3()); - GeomProp_Surface aProp(aPlane); - - EXPECT_EQ(aProp.GetType(), GeomAbs_Plane); -} - -TEST(GeomProp_PlaneTest, Normal_TiltedPlane) -{ - const gp_Dir aNormalDir(1.0, 1.0, 1.0); - occ::handle aPlane = new Geom_Plane(gp_Pnt(0, 0, 0), aNormalDir); - GeomProp_Surface aProp(aPlane); - - const GeomProp::SurfaceNormalResult aNorm = aProp.Normal(0.0, 0.0, THE_LIN_TOL); - ASSERT_TRUE(aNorm.IsDefined); - const double aDot = aNorm.Direction.Dot(aNormalDir); - EXPECT_NEAR(std::abs(aDot), 1.0, THE_DIR_TOL); -} - -TEST(GeomProp_PlaneTest, Curvatures_TiltedPlane) -{ - const gp_Dir aNormalDir(1.0, 1.0, 1.0); - occ::handle aPlane = new Geom_Plane(gp_Pnt(0, 0, 0), aNormalDir); - GeomProp_Surface aProp(aPlane); - - const GeomProp::SurfaceCurvatureResult aCurv = aProp.Curvatures(3.0, 4.0, THE_LIN_TOL); - ASSERT_TRUE(aCurv.IsDefined); - EXPECT_NEAR(aCurv.MinCurvature, 0.0, THE_CURV_TOL); - EXPECT_NEAR(aCurv.MaxCurvature, 0.0, THE_CURV_TOL); -} - -TEST(GeomProp_PlaneTest, MeanGaussian_TiltedPlane) -{ - const gp_Dir aNormalDir(1.0, 1.0, 1.0); - occ::handle aPlane = new Geom_Plane(gp_Pnt(0, 0, 0), aNormalDir); - GeomProp_Surface aProp(aPlane); - - const GeomProp::MeanGaussianResult aMG = aProp.MeanGaussian(3.0, 4.0, THE_LIN_TOL); - ASSERT_TRUE(aMG.IsDefined); - EXPECT_NEAR(aMG.MeanCurvature, 0.0, THE_CURV_TOL); - EXPECT_NEAR(aMG.GaussianCurvature, 0.0, THE_CURV_TOL); -} - -TEST(GeomProp_PlaneTest, Normal_OffCenter) -{ - occ::handle aPlane = new Geom_Plane(gp_Pnt(10, 20, 30), gp_Dir(0, 0, 1)); - GeomProp_Surface aProp(aPlane); - - const GeomProp::SurfaceNormalResult aNorm = aProp.Normal(5.0, 5.0, THE_LIN_TOL); - ASSERT_TRUE(aNorm.IsDefined); - EXPECT_NEAR(std::abs(aNorm.Direction.Z()), 1.0, THE_DIR_TOL); -} - -TEST(GeomProp_PlaneTest, VsSLProps_Normal) -{ - occ::handle aPlane = new Geom_Plane(gp_Ax3()); - const double aStep = 2.0; - for (int i = 0; i <= 5; ++i) - { - for (int j = 0; j <= 5; ++j) - { - compareNormal(aPlane, i * aStep, j * aStep); - } - } -} - -TEST(GeomProp_PlaneTest, VsSLProps_Curvatures) -{ - occ::handle aPlane = new Geom_Plane(gp_Ax3()); - const double aStep = 2.0; - for (int i = 0; i <= 5; ++i) - { - for (int j = 0; j <= 5; ++j) - { - compareCurvatures(aPlane, i * aStep, j * aStep); - } - } -} - -TEST(GeomProp_PlaneTest, VsSLProps_MeanGaussian) -{ - occ::handle aPlane = new Geom_Plane(gp_Ax3()); - const double aStep = 2.0; - for (int i = 0; i <= 5; ++i) - { - for (int j = 0; j <= 5; ++j) - { - compareMeanGaussian(aPlane, i * aStep, j * aStep); - } - } -} - -TEST(GeomProp_PlaneTest, VsSLProps_AllProperties) -{ - occ::handle aPlane = new Geom_Plane(gp_Ax3()); - compareAllSurface(aPlane, -10.0, 10.0, -10.0, 10.0, 8, 8); -} - -TEST(GeomProp_PlaneTest, VsSLProps_TiltedPlane) -{ - occ::handle aPlane = new Geom_Plane(gp_Pnt(0, 0, 0), gp_Dir(1, 1, 1)); - compareAllSurface(aPlane, -5.0, 5.0, -5.0, 5.0); -} - -TEST(GeomProp_PlaneTest, VsSLProps_OffCenter) -{ - occ::handle aPlane = new Geom_Plane(gp_Pnt(10, 20, 30), gp_Dir(0, 0, 1)); - compareAllSurface(aPlane, -5.0, 5.0, -5.0, 5.0); -} - -TEST(GeomProp_PlaneTest, VsSLProps_LargeParams) -{ - occ::handle aPlane = new Geom_Plane(gp_Ax3()); - compareAllSurface(aPlane, 900.0, 1100.0, 900.0, 1100.0); -} - -TEST(GeomProp_PlaneTest, Normal_ConsistentOrientation) -{ - occ::handle aPlane = new Geom_Plane(gp_Ax3()); - GeomProp_Surface aProp(aPlane); - - const GeomProp::SurfaceNormalResult aRef = aProp.Normal(0.0, 0.0, THE_LIN_TOL); - ASSERT_TRUE(aRef.IsDefined); - - // Check that the normal is the same at widely separated points. - const double aParams[] = {-100.0, -10.0, 0.0, 10.0, 100.0}; - for (double aU : aParams) - { - for (double aV : aParams) - { - const GeomProp::SurfaceNormalResult aNorm = aProp.Normal(aU, aV, THE_LIN_TOL); - ASSERT_TRUE(aNorm.IsDefined); - const double aDot = aNorm.Direction.Dot(aRef.Direction); - EXPECT_NEAR(std::abs(aDot), 1.0, THE_DIR_TOL) - << "Normal orientation inconsistent at (" << aU << "," << aV << ")"; - } - } -} - -TEST(GeomProp_PlaneTest, Curvatures_ExactlyZero) -{ - occ::handle aPlane = new Geom_Plane(gp_Ax3()); - GeomProp_Surface aProp(aPlane); - - const GeomProp::SurfaceCurvatureResult aCurv = aProp.Curvatures(5.0, 5.0, THE_LIN_TOL); - ASSERT_TRUE(aCurv.IsDefined); - EXPECT_EQ(aCurv.MinCurvature, 0.0); - EXPECT_EQ(aCurv.MaxCurvature, 0.0); -} - -TEST(GeomProp_PlaneTest, MeanGaussian_ExactlyZero) -{ - occ::handle aPlane = new Geom_Plane(gp_Ax3()); - GeomProp_Surface aProp(aPlane); - - const GeomProp::MeanGaussianResult aMG = aProp.MeanGaussian(5.0, 5.0, THE_LIN_TOL); - ASSERT_TRUE(aMG.IsDefined); - EXPECT_EQ(aMG.MeanCurvature, 0.0); - EXPECT_EQ(aMG.GaussianCurvature, 0.0); -} - -TEST(GeomProp_PlaneTest, VsSLProps_CriticalPoints) -{ - occ::handle aPlane = new Geom_Plane(gp_Ax3()); - const double aParams[][2] = {{0.0, 0.0}, - {1.0e-10, 1.0e-10}, - {-1.0e-10, -1.0e-10}, - {1.0e6, 1.0e6}, - {-1.0e6, -1.0e6}, - {1.0e-10, 1.0e6}, - {0.5, 0.5}, - {-100.0, 100.0}}; - for (const auto& aUV : aParams) - { - compareNormal(aPlane, aUV[0], aUV[1]); - compareCurvatures(aPlane, aUV[0], aUV[1]); - compareMeanGaussian(aPlane, aUV[0], aUV[1]); - } -} diff --git a/src/ModelingData/TKG3d/GTests/GeomProp_Sphere_Test.cxx b/src/ModelingData/TKG3d/GTests/GeomProp_Sphere_Test.cxx deleted file mode 100644 index ea8f23f226..0000000000 --- a/src/ModelingData/TKG3d/GTests/GeomProp_Sphere_Test.cxx +++ /dev/null @@ -1,440 +0,0 @@ -// 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. - -// Unit tests for GeomProp_Surface with SphericalSurface geometry. - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -namespace -{ -constexpr double THE_LIN_TOL = Precision::PConfusion(); -constexpr double THE_CURV_TOL = 1.0e-6; -constexpr double THE_DIR_TOL = 1.0e-4; - -void compareNormal(const occ::handle& theSurf, const double theU, const double theV) -{ - GeomProp_Surface aProp(theSurf); - const GeomProp::SurfaceNormalResult aNew = aProp.Normal(theU, theV, THE_LIN_TOL); - - GeomLProp_SLProps anOld(theSurf, theU, theV, 2, THE_LIN_TOL); - if (anOld.IsNormalDefined()) - { - ASSERT_TRUE(aNew.IsDefined) << "New normal undefined at (" << theU << "," << theV << ")"; - const double aDot = aNew.Direction.Dot(anOld.Normal()); - EXPECT_NEAR(std::abs(aDot), 1.0, THE_DIR_TOL) - << "Normal mismatch at (" << theU << "," << theV << ")"; - } -} - -void compareCurvatures(const occ::handle& theSurf, - const double theU, - const double theV) -{ - GeomProp_Surface aProp(theSurf); - const GeomProp::SurfaceCurvatureResult aNew = aProp.Curvatures(theU, theV, THE_LIN_TOL); - - GeomLProp_SLProps anOld(theSurf, theU, theV, 2, THE_LIN_TOL); - if (anOld.IsCurvatureDefined()) - { - ASSERT_TRUE(aNew.IsDefined) << "New curvatures undefined at (" << theU << "," << theV << ")"; - EXPECT_NEAR(aNew.MinCurvature, anOld.MinCurvature(), THE_CURV_TOL) - << "MinCurvature mismatch at (" << theU << "," << theV << ")"; - EXPECT_NEAR(aNew.MaxCurvature, anOld.MaxCurvature(), THE_CURV_TOL) - << "MaxCurvature mismatch at (" << theU << "," << theV << ")"; - } -} - -void compareMeanGaussian(const occ::handle& theSurf, - const double theU, - const double theV) -{ - GeomProp_Surface aProp(theSurf); - const GeomProp::MeanGaussianResult aNew = aProp.MeanGaussian(theU, theV, THE_LIN_TOL); - - GeomLProp_SLProps anOld(theSurf, theU, theV, 2, THE_LIN_TOL); - if (anOld.IsCurvatureDefined()) - { - ASSERT_TRUE(aNew.IsDefined) << "New MeanGaussian undefined at (" << theU << "," << theV << ")"; - EXPECT_NEAR(aNew.MeanCurvature, anOld.MeanCurvature(), THE_CURV_TOL) - << "Mean curvature mismatch at (" << theU << "," << theV << ")"; - EXPECT_NEAR(aNew.GaussianCurvature, anOld.GaussianCurvature(), THE_CURV_TOL) - << "Gaussian curvature mismatch at (" << theU << "," << theV << ")"; - } -} - -void compareAllSurface(const occ::handle& theSurf, - const double theUMin, - const double theUMax, - const double theVMin, - const double theVMax, - const int theNbU = 5, - const int theNbV = 5) -{ - const double aUStep = (theUMax - theUMin) / theNbU; - const double aVStep = (theVMax - theVMin) / theNbV; - for (int i = 0; i <= theNbU; ++i) - { - for (int j = 0; j <= theNbV; ++j) - { - const double aU = theUMin + i * aUStep; - const double aV = theVMin + j * aVStep; - compareNormal(theSurf, aU, aV); - compareCurvatures(theSurf, aU, aV); - compareMeanGaussian(theSurf, aU, aV); - } - } -} -} // namespace - -// ============================================================================ -// Analytical reference tests -// ============================================================================ - -TEST(GeomProp_SphereTest, Normal_PointsOutward) -{ - const double aRadius = 5.0; - occ::handle aSphere = new Geom_SphericalSurface(gp_Ax3(), aRadius); - GeomProp_Surface aProp(aSphere); - - // At u=0, v=0 (equator, X axis), normal should point along +X (outward). - const GeomProp::SurfaceNormalResult aNorm = aProp.Normal(0.0, 0.0, THE_LIN_TOL); - ASSERT_TRUE(aNorm.IsDefined); - EXPECT_NEAR(std::abs(aNorm.Direction.X()), 1.0, THE_DIR_TOL); - EXPECT_NEAR(aNorm.Direction.Y(), 0.0, THE_DIR_TOL); - EXPECT_NEAR(aNorm.Direction.Z(), 0.0, THE_DIR_TOL); -} - -TEST(GeomProp_SphereTest, Normal_Grid) -{ - const double aRadius = 5.0; - occ::handle aSphere = new Geom_SphericalSurface(gp_Ax3(), aRadius); - GeomProp_Surface aProp(aSphere); - - // Avoid poles where D1U degenerates. - for (int i = 0; i < 12; ++i) - { - for (int j = -3; j <= 3; ++j) - { - const double aU = i * M_PI / 6.0; - const double aV = j * M_PI / 9.0; // Range [-PI/3, PI/3] - const GeomProp::SurfaceNormalResult aNorm = aProp.Normal(aU, aV, THE_LIN_TOL); - ASSERT_TRUE(aNorm.IsDefined) << "Normal undefined at (" << aU << "," << aV << ")"; - } - } -} - -TEST(GeomProp_SphereTest, Curvatures_IsUmbilic) -{ - const double aRadius = 5.0; - occ::handle aSphere = new Geom_SphericalSurface(gp_Ax3(), aRadius); - GeomProp_Surface aProp(aSphere); - - for (int i = 0; i < 8; ++i) - { - for (int j = -2; j <= 2; ++j) - { - const double aU = i * M_PI / 4.0; - const double aV = j * M_PI / 6.0; - const GeomProp::SurfaceCurvatureResult aCurv = aProp.Curvatures(aU, aV, THE_LIN_TOL); - ASSERT_TRUE(aCurv.IsDefined); - EXPECT_NEAR(aCurv.MinCurvature, aCurv.MaxCurvature, THE_CURV_TOL) - << "Not umbilic at (" << aU << "," << aV << ")"; - } - } -} - -TEST(GeomProp_SphereTest, Curvatures_Constant) -{ - const double aRadius = 5.0; - occ::handle aSphere = new Geom_SphericalSurface(gp_Ax3(), aRadius); - GeomProp_Surface aProp(aSphere); - - for (int i = 0; i < 8; ++i) - { - for (int j = -2; j <= 2; ++j) - { - const double aU = i * M_PI / 4.0; - const double aV = j * M_PI / 6.0; - const GeomProp::SurfaceCurvatureResult aCurv = aProp.Curvatures(aU, aV, THE_LIN_TOL); - ASSERT_TRUE(aCurv.IsDefined); - EXPECT_NEAR(std::abs(aCurv.MinCurvature), 1.0 / aRadius, THE_CURV_TOL) - << "Curvature magnitude wrong at (" << aU << "," << aV << ")"; - EXPECT_NEAR(std::abs(aCurv.MaxCurvature), 1.0 / aRadius, THE_CURV_TOL) - << "Curvature magnitude wrong at (" << aU << "," << aV << ")"; - } - } -} - -TEST(GeomProp_SphereTest, Curvatures_SmallRadius) -{ - const double aRadius = 0.1; - occ::handle aSphere = new Geom_SphericalSurface(gp_Ax3(), aRadius); - GeomProp_Surface aProp(aSphere); - - const GeomProp::SurfaceCurvatureResult aCurv = aProp.Curvatures(0.5, 0.0, THE_LIN_TOL); - ASSERT_TRUE(aCurv.IsDefined); - EXPECT_NEAR(std::abs(aCurv.MaxCurvature), 1.0 / aRadius, THE_CURV_TOL); -} - -TEST(GeomProp_SphereTest, Curvatures_LargeRadius) -{ - const double aRadius = 1000.0; - occ::handle aSphere = new Geom_SphericalSurface(gp_Ax3(), aRadius); - GeomProp_Surface aProp(aSphere); - - const GeomProp::SurfaceCurvatureResult aCurv = aProp.Curvatures(0.5, 0.0, THE_LIN_TOL); - ASSERT_TRUE(aCurv.IsDefined); - EXPECT_NEAR(std::abs(aCurv.MaxCurvature), 1.0 / aRadius, THE_CURV_TOL); -} - -TEST(GeomProp_SphereTest, MeanGaussian_Gaussian) -{ - const double aRadius = 5.0; - occ::handle aSphere = new Geom_SphericalSurface(gp_Ax3(), aRadius); - GeomProp_Surface aProp(aSphere); - - const GeomProp::MeanGaussianResult aMG = aProp.MeanGaussian(1.0, 0.0, THE_LIN_TOL); - ASSERT_TRUE(aMG.IsDefined); - EXPECT_NEAR(std::abs(aMG.GaussianCurvature), 1.0 / (aRadius * aRadius), THE_CURV_TOL); -} - -TEST(GeomProp_SphereTest, MeanGaussian_Mean) -{ - const double aRadius = 5.0; - occ::handle aSphere = new Geom_SphericalSurface(gp_Ax3(), aRadius); - GeomProp_Surface aProp(aSphere); - - const GeomProp::MeanGaussianResult aMG = aProp.MeanGaussian(1.0, 0.0, THE_LIN_TOL); - ASSERT_TRUE(aMG.IsDefined); - EXPECT_NEAR(std::abs(aMG.MeanCurvature), 1.0 / aRadius, THE_CURV_TOL); -} - -TEST(GeomProp_SphereTest, MeanGaussian_Constant) -{ - const double aRadius = 5.0; - occ::handle aSphere = new Geom_SphericalSurface(gp_Ax3(), aRadius); - GeomProp_Surface aProp(aSphere); - - const GeomProp::MeanGaussianResult aRef = aProp.MeanGaussian(0.0, 0.0, THE_LIN_TOL); - ASSERT_TRUE(aRef.IsDefined); - - for (int i = 0; i < 8; ++i) - { - for (int j = -2; j <= 2; ++j) - { - const double aU = i * M_PI / 4.0; - const double aV = j * M_PI / 6.0; - const GeomProp::MeanGaussianResult aMG = aProp.MeanGaussian(aU, aV, THE_LIN_TOL); - ASSERT_TRUE(aMG.IsDefined); - EXPECT_NEAR(aMG.MeanCurvature, aRef.MeanCurvature, THE_CURV_TOL) - << "Mean curvature not constant at (" << aU << "," << aV << ")"; - EXPECT_NEAR(aMG.GaussianCurvature, aRef.GaussianCurvature, THE_CURV_TOL) - << "Gaussian curvature not constant at (" << aU << "," << aV << ")"; - } - } -} - -TEST(GeomProp_SphereTest, GetType_IsSphere) -{ - occ::handle aSphere = new Geom_SphericalSurface(gp_Ax3(), 5.0); - GeomProp_Surface aProp(aSphere); - - EXPECT_EQ(aProp.GetType(), GeomAbs_Sphere); -} - -// ============================================================================ -// Cross-validation tests vs GeomLProp_SLProps -// ============================================================================ - -TEST(GeomProp_SphereTest, VsSLProps_Normal) -{ - occ::handle aSphere = new Geom_SphericalSurface(gp_Ax3(), 5.0); - // Avoid poles. - const double aUStep = M_PI / 3.0; - const double aVStep = M_PI / 9.0; - for (int i = 0; i <= 6; ++i) - { - for (int j = -3; j <= 3; ++j) - { - compareNormal(aSphere, i * aUStep, j * aVStep); - } - } -} - -TEST(GeomProp_SphereTest, VsSLProps_Curvatures) -{ - occ::handle aSphere = new Geom_SphericalSurface(gp_Ax3(), 5.0); - const double aUStep = M_PI / 3.0; - const double aVStep = M_PI / 9.0; - for (int i = 0; i <= 6; ++i) - { - for (int j = -3; j <= 3; ++j) - { - compareCurvatures(aSphere, i * aUStep, j * aVStep); - } - } -} - -TEST(GeomProp_SphereTest, VsSLProps_MeanGaussian) -{ - occ::handle aSphere = new Geom_SphericalSurface(gp_Ax3(), 5.0); - const double aUStep = M_PI / 3.0; - const double aVStep = M_PI / 9.0; - for (int i = 0; i <= 6; ++i) - { - for (int j = -3; j <= 3; ++j) - { - compareMeanGaussian(aSphere, i * aUStep, j * aVStep); - } - } -} - -TEST(GeomProp_SphereTest, VsSLProps_AllProperties) -{ - occ::handle aSphere = new Geom_SphericalSurface(gp_Ax3(), 5.0); - compareAllSurface(aSphere, 0.0, 2.0 * M_PI, -M_PI / 3.0, M_PI / 3.0, 8, 8); -} - -TEST(GeomProp_SphereTest, VsSLProps_SmallRadius) -{ - occ::handle aSphere = new Geom_SphericalSurface(gp_Ax3(), 0.1); - compareAllSurface(aSphere, 0.0, 2.0 * M_PI, -M_PI / 3.0, M_PI / 3.0); -} - -TEST(GeomProp_SphereTest, VsSLProps_LargeRadius) -{ - occ::handle aSphere = new Geom_SphericalSurface(gp_Ax3(), 1000.0); - compareAllSurface(aSphere, 0.0, 2.0 * M_PI, -M_PI / 3.0, M_PI / 3.0); -} - -TEST(GeomProp_SphereTest, VsSLProps_OffCenter) -{ - const gp_Ax3 anAx3(gp_Pnt(5, 10, 15), gp_Dir(0, 0, 1)); - occ::handle aSphere = new Geom_SphericalSurface(anAx3, 5.0); - compareAllSurface(aSphere, 0.0, 2.0 * M_PI, -M_PI / 3.0, M_PI / 3.0); -} - -TEST(GeomProp_SphereTest, Normal_AtEquator) -{ - const double aRadius = 5.0; - occ::handle aSphere = new Geom_SphericalSurface(gp_Ax3(), aRadius); - GeomProp_Surface aProp(aSphere); - - // At u=PI/2, v=0, the point is (0,R,0), normal should be along +Y. - const GeomProp::SurfaceNormalResult aNorm = aProp.Normal(M_PI / 2.0, 0.0, THE_LIN_TOL); - ASSERT_TRUE(aNorm.IsDefined); - EXPECT_NEAR(aNorm.Direction.X(), 0.0, THE_DIR_TOL); - EXPECT_NEAR(std::abs(aNorm.Direction.Y()), 1.0, THE_DIR_TOL); - EXPECT_NEAR(aNorm.Direction.Z(), 0.0, THE_DIR_TOL); -} - -TEST(GeomProp_SphereTest, Curvatures_SignConsistency) -{ - const double aRadius = 5.0; - occ::handle aSphere = new Geom_SphericalSurface(gp_Ax3(), aRadius); - GeomProp_Surface aProp(aSphere); - - for (int i = 0; i < 8; ++i) - { - const double aU = i * M_PI / 4.0; - const GeomProp::SurfaceCurvatureResult aCurv = aProp.Curvatures(aU, 0.0, THE_LIN_TOL); - ASSERT_TRUE(aCurv.IsDefined); - // Both curvatures should have the same sign on a sphere. - EXPECT_TRUE((aCurv.MinCurvature >= 0.0 && aCurv.MaxCurvature >= 0.0) - || (aCurv.MinCurvature <= 0.0 && aCurv.MaxCurvature <= 0.0)) - << "Curvatures have different signs at u=" << aU; - } -} - -TEST(GeomProp_SphereTest, MeanGaussian_GaussianPositive) -{ - const double aRadius = 5.0; - occ::handle aSphere = new Geom_SphericalSurface(gp_Ax3(), aRadius); - GeomProp_Surface aProp(aSphere); - - for (int i = 0; i < 8; ++i) - { - for (int j = -2; j <= 2; ++j) - { - const double aU = i * M_PI / 4.0; - const double aV = j * M_PI / 6.0; - const GeomProp::MeanGaussianResult aMG = aProp.MeanGaussian(aU, aV, THE_LIN_TOL); - ASSERT_TRUE(aMG.IsDefined); - EXPECT_GT(aMG.GaussianCurvature, 0.0) - << "Gaussian curvature not positive at (" << aU << "," << aV << ")"; - } - } -} - -TEST(GeomProp_SphereTest, VsSLProps_CriticalPoints) -{ - occ::handle aSphere = new Geom_SphericalSurface(gp_Ax3(), 5.0); - // Critical: near poles (v=+-PI/2), equator (v=0), seam (u=0), near-seam - const double aParams[][2] = {{0.0, 0.0}, - {1.0e-10, 0.0}, - {0.0, 1.0e-10}, - {M_PI / 2.0, 0.0}, - {M_PI, 0.0}, - {3.0 * M_PI / 2.0, 0.0}, - {0.0, M_PI / 2.0 - 1.0e-6}, - {0.0, -(M_PI / 2.0 - 1.0e-6)}, - {0.0, M_PI / 4.0}, - {0.0, -M_PI / 4.0}, - {2.0 * M_PI - 1.0e-10, 0.0}, - {M_PI / 4.0, M_PI / 3.0}, - {M_PI / 4.0, -M_PI / 3.0}}; - for (const auto& aUV : aParams) - { - compareNormal(aSphere, aUV[0], aUV[1]); - compareCurvatures(aSphere, aUV[0], aUV[1]); - compareMeanGaussian(aSphere, aUV[0], aUV[1]); - } -} - -TEST(GeomProp_SphereTest, RepeatedCalls_SameParameter_AreStable) -{ - occ::handle aSphere = new Geom_SphericalSurface(gp_Ax3(), 5.0); - GeomProp_Surface aProp(aSphere); - GeomProp_Surface aFreshProp(aSphere); - const double aU = M_PI / 4.0; - const double aV = M_PI / 6.0; - - const GeomProp::SurfaceNormalResult aNormal = aProp.Normal(aU, aV, THE_LIN_TOL); - const GeomProp::SurfaceCurvatureResult aCurv = aProp.Curvatures(aU, aV, THE_LIN_TOL); - const GeomProp::MeanGaussianResult aMeanG = aProp.MeanGaussian(aU, aV, THE_LIN_TOL); - - const GeomProp::SurfaceCurvatureResult aFreshCurv = aFreshProp.Curvatures(aU, aV, THE_LIN_TOL); - const GeomProp::MeanGaussianResult aFreshMeanG = aFreshProp.MeanGaussian(aU, aV, THE_LIN_TOL); - - ASSERT_TRUE(aNormal.IsDefined); - ASSERT_TRUE(aCurv.IsDefined); - ASSERT_TRUE(aMeanG.IsDefined); - ASSERT_TRUE(aFreshCurv.IsDefined); - ASSERT_TRUE(aFreshMeanG.IsDefined); - - EXPECT_NEAR(aCurv.MinCurvature, aFreshCurv.MinCurvature, THE_CURV_TOL); - EXPECT_NEAR(aCurv.MaxCurvature, aFreshCurv.MaxCurvature, THE_CURV_TOL); - EXPECT_NEAR(aMeanG.MeanCurvature, aFreshMeanG.MeanCurvature, THE_CURV_TOL); - EXPECT_NEAR(aMeanG.GaussianCurvature, aFreshMeanG.GaussianCurvature, THE_CURV_TOL); -} diff --git a/src/ModelingData/TKG3d/GTests/GeomProp_SurfaceOfExtrusion_Test.cxx b/src/ModelingData/TKG3d/GTests/GeomProp_SurfaceOfExtrusion_Test.cxx deleted file mode 100644 index 741122f216..0000000000 --- a/src/ModelingData/TKG3d/GTests/GeomProp_SurfaceOfExtrusion_Test.cxx +++ /dev/null @@ -1,414 +0,0 @@ -// 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. - -// Tests for GeomProp_Surface with Geom_SurfaceOfLinearExtrusion. -// Validates normal, curvatures, mean/Gaussian curvature for surfaces -// of extrusion obtained by sweeping circles, lines, ellipses, and Bezier -// curves along a direction. Cross-validates against GeomLProp_SLProps. - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -namespace -{ -constexpr double THE_LIN_TOL = Precision::PConfusion(); -constexpr double THE_CURV_TOL = 1.0e-6; -constexpr double THE_DIR_TOL = 1.0e-4; - -//! Compare surface normal from new GeomProp_Surface vs old GeomLProp_SLProps. -void compareNormal(const occ::handle& theSurf, const double theU, const double theV) -{ - GeomProp_Surface aProp(theSurf); - const GeomProp::SurfaceNormalResult aNew = aProp.Normal(theU, theV, THE_LIN_TOL); - - GeomLProp_SLProps anOld(theSurf, theU, theV, 2, THE_LIN_TOL); - if (anOld.IsNormalDefined()) - { - ASSERT_TRUE(aNew.IsDefined) << "New normal undefined at (" << theU << "," << theV << ")"; - const double aDot = aNew.Direction.Dot(anOld.Normal()); - EXPECT_NEAR(std::abs(aDot), 1.0, THE_DIR_TOL) - << "Normal mismatch at (" << theU << "," << theV << ")"; - } -} - -//! Compare curvatures from new GeomProp_Surface vs old GeomLProp_SLProps. -void compareCurvatures(const occ::handle& theSurf, - const double theU, - const double theV) -{ - GeomProp_Surface aProp(theSurf); - const GeomProp::SurfaceCurvatureResult aNew = aProp.Curvatures(theU, theV, THE_LIN_TOL); - - GeomLProp_SLProps anOld(theSurf, theU, theV, 2, THE_LIN_TOL); - if (anOld.IsCurvatureDefined()) - { - ASSERT_TRUE(aNew.IsDefined) << "New curvatures undefined at (" << theU << "," << theV << ")"; - EXPECT_NEAR(aNew.MinCurvature, anOld.MinCurvature(), THE_CURV_TOL) - << "MinCurvature mismatch at (" << theU << "," << theV << ")"; - EXPECT_NEAR(aNew.MaxCurvature, anOld.MaxCurvature(), THE_CURV_TOL) - << "MaxCurvature mismatch at (" << theU << "," << theV << ")"; - } -} - -//! Compare mean and Gaussian curvatures. -void compareMeanGaussian(const occ::handle& theSurf, - const double theU, - const double theV) -{ - GeomProp_Surface aProp(theSurf); - const GeomProp::MeanGaussianResult aNew = aProp.MeanGaussian(theU, theV, THE_LIN_TOL); - - GeomLProp_SLProps anOld(theSurf, theU, theV, 2, THE_LIN_TOL); - if (anOld.IsCurvatureDefined()) - { - ASSERT_TRUE(aNew.IsDefined) << "New MeanGaussian undefined at (" << theU << "," << theV << ")"; - EXPECT_NEAR(aNew.MeanCurvature, anOld.MeanCurvature(), THE_CURV_TOL) - << "Mean curvature mismatch at (" << theU << "," << theV << ")"; - EXPECT_NEAR(aNew.GaussianCurvature, anOld.GaussianCurvature(), THE_CURV_TOL) - << "Gaussian curvature mismatch at (" << theU << "," << theV << ")"; - } -} - -//! Run all surface comparisons at a grid of parameter values. -void compareAllSurface(const occ::handle& theSurf, - const double theUMin, - const double theUMax, - const double theVMin, - const double theVMax, - const int theNbU = 5, - const int theNbV = 5) -{ - const double aUStep = (theUMax - theUMin) / theNbU; - const double aVStep = (theVMax - theVMin) / theNbV; - for (int i = 0; i <= theNbU; ++i) - { - for (int j = 0; j <= theNbV; ++j) - { - const double aU = theUMin + i * aUStep; - const double aV = theVMin + j * aVStep; - compareNormal(theSurf, aU, aV); - compareCurvatures(theSurf, aU, aV); - compareMeanGaussian(theSurf, aU, aV); - } - } -} - -//! Extrusion direction: along Z. -const gp_Dir THE_EXTRUSION_DIR(0.0, 0.0, 1.0); - -//! Create cylinder by extruding a circle along Z. -//! Circle of radius 5 in XY plane, extruded along Z. -occ::handle makeExtrudeCircle() -{ - gp_Ax2 aCircAx(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(0.0, 0.0, 1.0)); - occ::handle aCircle = new Geom_Circle(aCircAx, 5.0); - return new Geom_SurfaceOfLinearExtrusion(aCircle, THE_EXTRUSION_DIR); -} - -//! Create plane by extruding a line along Z. -occ::handle makeExtrudeLine() -{ - occ::handle aLine = new Geom_Line(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(1.0, 0.0, 0.0)); - return new Geom_SurfaceOfLinearExtrusion(aLine, THE_EXTRUSION_DIR); -} - -//! Create surface by extruding an ellipse along Z. -occ::handle makeExtrudeEllipse() -{ - gp_Ax2 anEllAx(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(0.0, 0.0, 1.0)); - occ::handle anEllipse = new Geom_Ellipse(anEllAx, 6.0, 3.0); - return new Geom_SurfaceOfLinearExtrusion(anEllipse, THE_EXTRUSION_DIR); -} - -//! Create surface by extruding a cubic Bezier curve along Z. -occ::handle makeExtrudeBezier() -{ - NCollection_Array1 aPoles(1, 4); - aPoles(1) = gp_Pnt(0.0, 0.0, 0.0); - aPoles(2) = gp_Pnt(1.0, 3.0, 0.0); - aPoles(3) = gp_Pnt(3.0, -1.0, 0.0); - aPoles(4) = gp_Pnt(4.0, 1.0, 0.0); - occ::handle aBezier = new Geom_BezierCurve(aPoles); - return new Geom_SurfaceOfLinearExtrusion(aBezier, THE_EXTRUSION_DIR); -} -} // namespace - -// Normal on extruded circle (cylinder) points radially outward -TEST(GeomProp_SurfaceOfExtrusionTest, Normal_ExtrudeCircle_IsCylinder) -{ - occ::handle aSurf = makeExtrudeCircle(); - GeomProp_Surface aProp(aSurf); - - for (double aU = 0.0; aU < 2.0 * M_PI; aU += M_PI / 4.0) - { - const GeomProp::SurfaceNormalResult aResult = aProp.Normal(aU, 1.0, THE_LIN_TOL); - ASSERT_TRUE(aResult.IsDefined) << "Normal undefined at u=" << aU; - // Normal should be perpendicular to Z axis for a cylinder - EXPECT_NEAR(aResult.Direction.Z(), 0.0, THE_DIR_TOL) << "Normal has Z component at u=" << aU; - } -} - -// Curvatures of extruded circle: one zero, one 1/R -TEST(GeomProp_SurfaceOfExtrusionTest, Curvatures_ExtrudeCircle) -{ - occ::handle aSurf = makeExtrudeCircle(); - GeomProp_Surface aProp(aSurf); - - const double aExpectedK = 1.0 / 5.0; - const GeomProp::SurfaceCurvatureResult aResult = aProp.Curvatures(1.0, 0.0, THE_LIN_TOL); - ASSERT_TRUE(aResult.IsDefined); - // MinCurvature = -1/R (concave, signed), MaxCurvature = 0 (along extrusion). - EXPECT_NEAR(aResult.MinCurvature, -aExpectedK, THE_CURV_TOL); - EXPECT_NEAR(aResult.MaxCurvature, 0.0, THE_CURV_TOL); -} - -// Gaussian curvature of extruded circle is zero (developable) -TEST(GeomProp_SurfaceOfExtrusionTest, MeanGaussian_ExtrudeCircle) -{ - occ::handle aSurf = makeExtrudeCircle(); - GeomProp_Surface aProp(aSurf); - - const GeomProp::MeanGaussianResult aResult = aProp.MeanGaussian(1.0, 2.0, THE_LIN_TOL); - ASSERT_TRUE(aResult.IsDefined); - EXPECT_NEAR(aResult.GaussianCurvature, 0.0, THE_CURV_TOL); -} - -// Normal on extruded line (plane) is constant -TEST(GeomProp_SurfaceOfExtrusionTest, Normal_ExtrudeLine_IsPlane) -{ - occ::handle aSurf = makeExtrudeLine(); - GeomProp_Surface aProp(aSurf); - - const GeomProp::SurfaceNormalResult aRef = aProp.Normal(0.0, 0.0, THE_LIN_TOL); - ASSERT_TRUE(aRef.IsDefined); - - for (double aU = -5.0; aU <= 5.0; aU += 2.5) - { - for (double aV = -5.0; aV <= 5.0; aV += 2.5) - { - const GeomProp::SurfaceNormalResult aResult = aProp.Normal(aU, aV, THE_LIN_TOL); - ASSERT_TRUE(aResult.IsDefined) << "Normal undefined at (" << aU << "," << aV << ")"; - const double aDot = aResult.Direction.Dot(aRef.Direction); - EXPECT_NEAR(std::abs(aDot), 1.0, THE_DIR_TOL) - << "Normal not constant at (" << aU << "," << aV << ")"; - } - } -} - -// Curvatures of extruded line: all zero -TEST(GeomProp_SurfaceOfExtrusionTest, Curvatures_ExtrudeLine) -{ - occ::handle aSurf = makeExtrudeLine(); - GeomProp_Surface aProp(aSurf); - - const GeomProp::SurfaceCurvatureResult aResult = aProp.Curvatures(1.0, 1.0, THE_LIN_TOL); - ASSERT_TRUE(aResult.IsDefined); - EXPECT_NEAR(aResult.MinCurvature, 0.0, THE_CURV_TOL); - EXPECT_NEAR(aResult.MaxCurvature, 0.0, THE_CURV_TOL); -} - -// Mean and Gaussian curvature of extruded line: H=K=0 -TEST(GeomProp_SurfaceOfExtrusionTest, MeanGaussian_ExtrudeLine) -{ - occ::handle aSurf = makeExtrudeLine(); - GeomProp_Surface aProp(aSurf); - - const GeomProp::MeanGaussianResult aResult = aProp.MeanGaussian(1.0, 1.0, THE_LIN_TOL); - ASSERT_TRUE(aResult.IsDefined); - EXPECT_NEAR(aResult.MeanCurvature, 0.0, THE_CURV_TOL); - EXPECT_NEAR(aResult.GaussianCurvature, 0.0, THE_CURV_TOL); -} - -// GetType returns GeomAbs_SurfaceOfLinearExtrusion -TEST(GeomProp_SurfaceOfExtrusionTest, GetType_IsSurfaceOfExtrusion) -{ - occ::handle aSurf = makeExtrudeCircle(); - GeomProp_Surface aProp(aSurf); - EXPECT_EQ(aProp.GetType(), GeomAbs_SurfaceOfExtrusion); -} - -// Cross-validate extruded circle vs SLProps -TEST(GeomProp_SurfaceOfExtrusionTest, VsSLProps_ExtrudeCircle) -{ - occ::handle aSurf = makeExtrudeCircle(); - compareAllSurface(aSurf, 0.1, 2.0 * M_PI - 0.1, -5.0, 5.0); -} - -// Cross-validate extruded line vs SLProps -TEST(GeomProp_SurfaceOfExtrusionTest, VsSLProps_ExtrudeLine) -{ - occ::handle aSurf = makeExtrudeLine(); - compareAllSurface(aSurf, -5.0, 5.0, -5.0, 5.0); -} - -// Dense cross-validation for extruded circle -TEST(GeomProp_SurfaceOfExtrusionTest, VsSLProps_AllProperties_Circle) -{ - occ::handle aSurf = makeExtrudeCircle(); - compareAllSurface(aSurf, 0.1, 2.0 * M_PI - 0.1, -3.0, 3.0, 6, 6); -} - -// Dense cross-validation for extruded line -TEST(GeomProp_SurfaceOfExtrusionTest, VsSLProps_AllProperties_Line) -{ - occ::handle aSurf = makeExtrudeLine(); - compareAllSurface(aSurf, -5.0, 5.0, -5.0, 5.0, 6, 6); -} - -// Normal on extruded ellipse: varying normal direction -TEST(GeomProp_SurfaceOfExtrusionTest, Normal_ExtrudeEllipse) -{ - occ::handle aSurf = makeExtrudeEllipse(); - GeomProp_Surface aProp(aSurf); - - for (double aU = 0.0; aU < 2.0 * M_PI; aU += M_PI / 4.0) - { - const GeomProp::SurfaceNormalResult aResult = aProp.Normal(aU, 0.0, THE_LIN_TOL); - ASSERT_TRUE(aResult.IsDefined) << "Normal undefined at u=" << aU; - // Normal should be perpendicular to extrusion direction Z - EXPECT_NEAR(aResult.Direction.Z(), 0.0, THE_DIR_TOL); - } -} - -// Curvatures on extruded ellipse: varying along U -TEST(GeomProp_SurfaceOfExtrusionTest, Curvatures_ExtrudeEllipse) -{ - occ::handle aSurf = makeExtrudeEllipse(); - GeomProp_Surface aProp(aSurf); - - const GeomProp::SurfaceCurvatureResult aResult = aProp.Curvatures(0.5, 0.0, THE_LIN_TOL); - ASSERT_TRUE(aResult.IsDefined); - EXPECT_LE(aResult.MinCurvature, aResult.MaxCurvature); - // MaxCurvature is zero (along extrusion direction), MinCurvature is from ellipse (negative). - EXPECT_NEAR(aResult.MaxCurvature, 0.0, THE_CURV_TOL); -} - -// Gaussian curvature of extruded ellipse is zero (developable) -TEST(GeomProp_SurfaceOfExtrusionTest, MeanGaussian_ExtrudeEllipse) -{ - occ::handle aSurf = makeExtrudeEllipse(); - GeomProp_Surface aProp(aSurf); - - const GeomProp::MeanGaussianResult aResult = aProp.MeanGaussian(1.0, 0.0, THE_LIN_TOL); - ASSERT_TRUE(aResult.IsDefined); - EXPECT_NEAR(aResult.GaussianCurvature, 0.0, THE_CURV_TOL); -} - -// Cross-validate extruded ellipse vs SLProps -TEST(GeomProp_SurfaceOfExtrusionTest, VsSLProps_ExtrudeEllipse) -{ - occ::handle aSurf = makeExtrudeEllipse(); - compareAllSurface(aSurf, 0.1, 2.0 * M_PI - 0.1, -3.0, 3.0); -} - -// Normal on extruded Bezier curve -TEST(GeomProp_SurfaceOfExtrusionTest, Normal_ExtrudeBezier) -{ - occ::handle aSurf = makeExtrudeBezier(); - GeomProp_Surface aProp(aSurf); - - for (double aU = 0.0; aU <= 1.0; aU += 0.25) - { - const GeomProp::SurfaceNormalResult aResult = aProp.Normal(aU, 0.0, THE_LIN_TOL); - ASSERT_TRUE(aResult.IsDefined) << "Normal undefined at u=" << aU; - } -} - -// Curvatures on extruded Bezier: varies with U -TEST(GeomProp_SurfaceOfExtrusionTest, Curvatures_ExtrudeBezier) -{ - occ::handle aSurf = makeExtrudeBezier(); - GeomProp_Surface aProp(aSurf); - - const GeomProp::SurfaceCurvatureResult aResult = aProp.Curvatures(0.5, 0.0, THE_LIN_TOL); - ASSERT_TRUE(aResult.IsDefined); - EXPECT_LE(aResult.MinCurvature, aResult.MaxCurvature); -} - -// Cross-validate extruded Bezier vs SLProps -TEST(GeomProp_SurfaceOfExtrusionTest, VsSLProps_ExtrudeBezier) -{ - occ::handle aSurf = makeExtrudeBezier(); - compareAllSurface(aSurf, 0.05, 0.95, -3.0, 3.0); -} - -// Curvatures are constant along extrusion direction (V parameter) -TEST(GeomProp_SurfaceOfExtrusionTest, Curvatures_ConstantAlongV) -{ - occ::handle aSurf = makeExtrudeCircle(); - GeomProp_Surface aProp(aSurf); - - const double aU = 1.0; - const GeomProp::SurfaceCurvatureResult aRefResult = aProp.Curvatures(aU, 0.0, THE_LIN_TOL); - ASSERT_TRUE(aRefResult.IsDefined); - - for (double aV = -5.0; aV <= 5.0; aV += 2.5) - { - const GeomProp::SurfaceCurvatureResult aResult = aProp.Curvatures(aU, aV, THE_LIN_TOL); - ASSERT_TRUE(aResult.IsDefined) << "Curvatures undefined at v=" << aV; - EXPECT_NEAR(aResult.MinCurvature, aRefResult.MinCurvature, THE_CURV_TOL) - << "MinCurvature varies along V at v=" << aV; - EXPECT_NEAR(aResult.MaxCurvature, aRefResult.MaxCurvature, THE_CURV_TOL) - << "MaxCurvature varies along V at v=" << aV; - } -} - -// Dense 8x8 grid cross-validation for extruded circle -TEST(GeomProp_SurfaceOfExtrusionTest, VsSLProps_DenseGrid_Circle) -{ - occ::handle aSurf = makeExtrudeCircle(); - compareAllSurface(aSurf, 0.1, 2.0 * M_PI - 0.1, -3.0, 3.0, 8, 8); -} - -TEST(GeomProp_SurfaceOfExtrusionTest, VsSLProps_CriticalPoints) -{ - // Extrude a circle along Z - occ::handle aCircle = new Geom_Circle(gp_Ax2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), 5.0); - occ::handle aSurf = - new Geom_SurfaceOfLinearExtrusion(aCircle, gp_Dir(0, 0, 1)); - // Critical: seam, various angles, near-seam - const double aParams[][2] = {{0.0, 0.0}, - {1.0e-10, 0.0}, - {2.0 * M_PI - 1.0e-10, 0.0}, - {M_PI / 2.0, 0.0}, - {M_PI, 0.0}, - {0.0, 1.0e-10}, - {0.0, 1.0e6}, - {0.0, -1.0e6}, - {M_PI / 4.0, 0.5}, - {M_PI / 4.0, -0.5}}; - for (const auto& aUV : aParams) - { - compareNormal(aSurf, aUV[0], aUV[1]); - compareCurvatures(aSurf, aUV[0], aUV[1]); - compareMeanGaussian(aSurf, aUV[0], aUV[1]); - } -} diff --git a/src/ModelingData/TKG3d/GTests/GeomProp_SurfaceOfRevolution_Test.cxx b/src/ModelingData/TKG3d/GTests/GeomProp_SurfaceOfRevolution_Test.cxx deleted file mode 100644 index 31fda559a7..0000000000 --- a/src/ModelingData/TKG3d/GTests/GeomProp_SurfaceOfRevolution_Test.cxx +++ /dev/null @@ -1,405 +0,0 @@ -// 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. - -// Tests for GeomProp_Surface with Geom_SurfaceOfRevolution. -// Validates normal, curvatures, mean/Gaussian curvature for surfaces -// of revolution obtained by revolving lines, circles, ellipses, and parabolas. -// Cross-validates against GeomLProp_SLProps. - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -namespace -{ -constexpr double THE_LIN_TOL = Precision::PConfusion(); -constexpr double THE_CURV_TOL = 1.0e-6; -constexpr double THE_DIR_TOL = 1.0e-4; - -//! Compare surface normal from new GeomProp_Surface vs old GeomLProp_SLProps. -void compareNormal(const occ::handle& theSurf, const double theU, const double theV) -{ - GeomProp_Surface aProp(theSurf); - const GeomProp::SurfaceNormalResult aNew = aProp.Normal(theU, theV, THE_LIN_TOL); - - GeomLProp_SLProps anOld(theSurf, theU, theV, 2, THE_LIN_TOL); - if (anOld.IsNormalDefined()) - { - ASSERT_TRUE(aNew.IsDefined) << "New normal undefined at (" << theU << "," << theV << ")"; - const double aDot = aNew.Direction.Dot(anOld.Normal()); - EXPECT_NEAR(std::abs(aDot), 1.0, THE_DIR_TOL) - << "Normal mismatch at (" << theU << "," << theV << ")"; - } -} - -//! Compare curvatures from new GeomProp_Surface vs old GeomLProp_SLProps. -void compareCurvatures(const occ::handle& theSurf, - const double theU, - const double theV) -{ - GeomProp_Surface aProp(theSurf); - const GeomProp::SurfaceCurvatureResult aNew = aProp.Curvatures(theU, theV, THE_LIN_TOL); - - GeomLProp_SLProps anOld(theSurf, theU, theV, 2, THE_LIN_TOL); - if (anOld.IsCurvatureDefined()) - { - ASSERT_TRUE(aNew.IsDefined) << "New curvatures undefined at (" << theU << "," << theV << ")"; - EXPECT_NEAR(aNew.MinCurvature, anOld.MinCurvature(), THE_CURV_TOL) - << "MinCurvature mismatch at (" << theU << "," << theV << ")"; - EXPECT_NEAR(aNew.MaxCurvature, anOld.MaxCurvature(), THE_CURV_TOL) - << "MaxCurvature mismatch at (" << theU << "," << theV << ")"; - } -} - -//! Compare mean and Gaussian curvatures. -void compareMeanGaussian(const occ::handle& theSurf, - const double theU, - const double theV) -{ - GeomProp_Surface aProp(theSurf); - const GeomProp::MeanGaussianResult aNew = aProp.MeanGaussian(theU, theV, THE_LIN_TOL); - - GeomLProp_SLProps anOld(theSurf, theU, theV, 2, THE_LIN_TOL); - if (anOld.IsCurvatureDefined()) - { - ASSERT_TRUE(aNew.IsDefined) << "New MeanGaussian undefined at (" << theU << "," << theV << ")"; - EXPECT_NEAR(aNew.MeanCurvature, anOld.MeanCurvature(), THE_CURV_TOL) - << "Mean curvature mismatch at (" << theU << "," << theV << ")"; - EXPECT_NEAR(aNew.GaussianCurvature, anOld.GaussianCurvature(), THE_CURV_TOL) - << "Gaussian curvature mismatch at (" << theU << "," << theV << ")"; - } -} - -//! Run all surface comparisons at a grid of parameter values. -void compareAllSurface(const occ::handle& theSurf, - const double theUMin, - const double theUMax, - const double theVMin, - const double theVMax, - const int theNbU = 5, - const int theNbV = 5) -{ - const double aUStep = (theUMax - theUMin) / theNbU; - const double aVStep = (theVMax - theVMin) / theNbV; - for (int i = 0; i <= theNbU; ++i) - { - for (int j = 0; j <= theNbV; ++j) - { - const double aU = theUMin + i * aUStep; - const double aV = theVMin + j * aVStep; - compareNormal(theSurf, aU, aV); - compareCurvatures(theSurf, aU, aV); - compareMeanGaussian(theSurf, aU, aV); - } - } -} - -//! Revolution axis: Z axis through origin. -const gp_Ax1 THE_Z_AXIS(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(0.0, 0.0, 1.0)); - -//! Create cylinder by revolving a line parallel to Z around Z axis. -//! Radius = 5.0, line at X=5 parallel to Z. -occ::handle makeRevolveLine() -{ - occ::handle aLine = new Geom_Line(gp_Pnt(5.0, 0.0, 0.0), gp_Dir(0.0, 0.0, 1.0)); - return new Geom_SurfaceOfRevolution(aLine, THE_Z_AXIS); -} - -//! Create torus by revolving a circle around Z axis. -//! Major radius = 10.0, minor radius = 3.0. -occ::handle makeRevolveCircle() -{ - gp_Ax2 aCircAx(gp_Pnt(10.0, 0.0, 0.0), gp_Dir(0.0, 1.0, 0.0)); - occ::handle aCircle = new Geom_Circle(aCircAx, 3.0); - return new Geom_SurfaceOfRevolution(aCircle, THE_Z_AXIS); -} - -//! Create surface by revolving an ellipse around Z axis. -occ::handle makeRevolveEllipse() -{ - gp_Ax2 anEllAx(gp_Pnt(8.0, 0.0, 0.0), gp_Dir(0.0, 1.0, 0.0)); - occ::handle anEllipse = new Geom_Ellipse(anEllAx, 4.0, 2.0); - return new Geom_SurfaceOfRevolution(anEllipse, THE_Z_AXIS); -} - -//! Create surface by revolving a parabola around Z axis. -occ::handle makeRevolveParabola() -{ - gp_Ax2 aParabAx(gp_Pnt(5.0, 0.0, 0.0), gp_Dir(0.0, 1.0, 0.0)); - occ::handle aParab = new Geom_Parabola(aParabAx, 1.0); - return new Geom_SurfaceOfRevolution(aParab, THE_Z_AXIS); -} -} // namespace - -// Normal on cylinder-like surface (line revolved around Z) -TEST(GeomProp_SurfaceOfRevolutionTest, Normal_RevolveLine_IsCylinder) -{ - occ::handle aSurf = makeRevolveLine(); - GeomProp_Surface aProp(aSurf); - - // Normal should point radially outward from Z axis - for (double aU = 0.0; aU < 2.0 * M_PI; aU += M_PI / 4.0) - { - const GeomProp::SurfaceNormalResult aResult = aProp.Normal(aU, 0.0, THE_LIN_TOL); - ASSERT_TRUE(aResult.IsDefined) << "Normal undefined at u=" << aU; - // Normal Z component should be zero for a cylinder - EXPECT_NEAR(aResult.Direction.Z(), 0.0, THE_DIR_TOL) << "Normal has Z component at u=" << aU; - } -} - -// Curvatures of revolved line (cylinder): one zero, one 1/R -TEST(GeomProp_SurfaceOfRevolutionTest, Curvatures_RevolveLine_IsCylinder) -{ - occ::handle aSurf = makeRevolveLine(); - GeomProp_Surface aProp(aSurf); - - const double aExpectedK = 1.0 / 5.0; // 1/R where R=5 - const GeomProp::SurfaceCurvatureResult aResult = aProp.Curvatures(0.5, 0.0, THE_LIN_TOL); - ASSERT_TRUE(aResult.IsDefined); - // MinCurvature = -1/R (concave, signed), MaxCurvature = 0 (along axis). - EXPECT_NEAR(aResult.MinCurvature, -aExpectedK, THE_CURV_TOL); - EXPECT_NEAR(aResult.MaxCurvature, 0.0, THE_CURV_TOL); -} - -// Gaussian curvature of revolved line is zero (developable surface) -TEST(GeomProp_SurfaceOfRevolutionTest, MeanGaussian_RevolveLine) -{ - occ::handle aSurf = makeRevolveLine(); - GeomProp_Surface aProp(aSurf); - - const GeomProp::MeanGaussianResult aResult = aProp.MeanGaussian(1.0, 2.0, THE_LIN_TOL); - ASSERT_TRUE(aResult.IsDefined); - EXPECT_NEAR(aResult.GaussianCurvature, 0.0, THE_CURV_TOL); -} - -// Normal on torus (circle revolved around Z) -TEST(GeomProp_SurfaceOfRevolutionTest, Normal_RevolveCircle_IsTorus) -{ - occ::handle aSurf = makeRevolveCircle(); - GeomProp_Surface aProp(aSurf); - - for (int i = 0; i <= 4; ++i) - { - for (int j = 0; j <= 4; ++j) - { - const double aU = i * M_PI / 2.0; - const double aV = j * M_PI / 2.0; - const GeomProp::SurfaceNormalResult aResult = aProp.Normal(aU, aV, THE_LIN_TOL); - ASSERT_TRUE(aResult.IsDefined) << "Normal undefined at (" << aU << "," << aV << ")"; - } - } -} - -// Curvatures of revolved circle (torus) -TEST(GeomProp_SurfaceOfRevolutionTest, Curvatures_RevolveCircle) -{ - occ::handle aSurf = makeRevolveCircle(); - GeomProp_Surface aProp(aSurf); - - // Evaluate away from boundary parameter v=0 to avoid degenerate point. - const GeomProp::SurfaceCurvatureResult aResult = aProp.Curvatures(0.5, 0.5, THE_LIN_TOL); - ASSERT_TRUE(aResult.IsDefined); - EXPECT_LE(aResult.MinCurvature, aResult.MaxCurvature); - // Both curvatures should be non-zero for a torus away from boundary - EXPECT_GT(std::abs(aResult.MinCurvature), THE_CURV_TOL); - EXPECT_GT(std::abs(aResult.MaxCurvature), THE_CURV_TOL); -} - -// Mean and Gaussian curvature of revolved circle -TEST(GeomProp_SurfaceOfRevolutionTest, MeanGaussian_RevolveCircle) -{ - occ::handle aSurf = makeRevolveCircle(); - GeomProp_Surface aProp(aSurf); - - // Evaluate away from boundary parameter v=0 to avoid degenerate point. - const GeomProp::MeanGaussianResult aResult = aProp.MeanGaussian(0.5, 0.5, THE_LIN_TOL); - ASSERT_TRUE(aResult.IsDefined); - // On the outer side of the torus, Gaussian curvature should be positive - EXPECT_GT(aResult.GaussianCurvature, 0.0); -} - -// GetType returns GeomAbs_SurfaceOfRevolution -TEST(GeomProp_SurfaceOfRevolutionTest, GetType_IsSurfaceOfRevolution) -{ - occ::handle aSurf = makeRevolveLine(); - GeomProp_Surface aProp(aSurf); - EXPECT_EQ(aProp.GetType(), GeomAbs_SurfaceOfRevolution); -} - -// Cross-validate revolved line vs SLProps -TEST(GeomProp_SurfaceOfRevolutionTest, VsSLProps_RevolveLine) -{ - occ::handle aSurf = makeRevolveLine(); - compareAllSurface(aSurf, 0.1, 2.0 * M_PI - 0.1, -5.0, 5.0); -} - -// Cross-validate revolved circle vs SLProps -TEST(GeomProp_SurfaceOfRevolutionTest, VsSLProps_RevolveCircle) -{ - occ::handle aSurf = makeRevolveCircle(); - compareAllSurface(aSurf, 0.1, 2.0 * M_PI - 0.1, 0.1, 2.0 * M_PI - 0.1); -} - -// Dense cross-validation for revolved line -TEST(GeomProp_SurfaceOfRevolutionTest, VsSLProps_AllProperties_Line) -{ - occ::handle aSurf = makeRevolveLine(); - compareAllSurface(aSurf, 0.1, 2.0 * M_PI - 0.1, -3.0, 3.0, 6, 6); -} - -// Dense cross-validation for revolved circle -TEST(GeomProp_SurfaceOfRevolutionTest, VsSLProps_AllProperties_Circle) -{ - occ::handle aSurf = makeRevolveCircle(); - compareAllSurface(aSurf, 0.1, 2.0 * M_PI - 0.1, 0.1, 2.0 * M_PI - 0.1, 6, 6); -} - -// Normal on revolved ellipse -TEST(GeomProp_SurfaceOfRevolutionTest, Normal_RevolveEllipse) -{ - occ::handle aSurf = makeRevolveEllipse(); - GeomProp_Surface aProp(aSurf); - - for (int i = 0; i <= 4; ++i) - { - const double aU = 0.5 + i * M_PI / 2.0; - const GeomProp::SurfaceNormalResult aResult = aProp.Normal(aU, 0.0, THE_LIN_TOL); - ASSERT_TRUE(aResult.IsDefined) << "Normal undefined at u=" << aU; - } -} - -// Curvatures on revolved ellipse: varying curvatures -TEST(GeomProp_SurfaceOfRevolutionTest, Curvatures_RevolveEllipse) -{ - occ::handle aSurf = makeRevolveEllipse(); - GeomProp_Surface aProp(aSurf); - - const GeomProp::SurfaceCurvatureResult aResult = aProp.Curvatures(1.0, 0.0, THE_LIN_TOL); - ASSERT_TRUE(aResult.IsDefined); - EXPECT_LE(aResult.MinCurvature, aResult.MaxCurvature); -} - -// Mean and Gaussian curvature on revolved ellipse -TEST(GeomProp_SurfaceOfRevolutionTest, MeanGaussian_RevolveEllipse) -{ - occ::handle aSurf = makeRevolveEllipse(); - GeomProp_Surface aProp(aSurf); - - const GeomProp::MeanGaussianResult aResult = aProp.MeanGaussian(1.0, 0.0, THE_LIN_TOL); - ASSERT_TRUE(aResult.IsDefined); -} - -// Cross-validate revolved ellipse vs SLProps -TEST(GeomProp_SurfaceOfRevolutionTest, VsSLProps_RevolveEllipse) -{ - occ::handle aSurf = makeRevolveEllipse(); - compareAllSurface(aSurf, 0.1, 2.0 * M_PI - 0.1, 0.1, 2.0 * M_PI - 0.1); -} - -// Normal on revolved parabola -TEST(GeomProp_SurfaceOfRevolutionTest, Normal_RevolveParabola) -{ - occ::handle aSurf = makeRevolveParabola(); - GeomProp_Surface aProp(aSurf); - - const GeomProp::SurfaceNormalResult aResult = aProp.Normal(1.0, 0.5, THE_LIN_TOL); - ASSERT_TRUE(aResult.IsDefined); -} - -// Curvatures on revolved parabola -TEST(GeomProp_SurfaceOfRevolutionTest, Curvatures_RevolveParabola) -{ - occ::handle aSurf = makeRevolveParabola(); - GeomProp_Surface aProp(aSurf); - - const GeomProp::SurfaceCurvatureResult aResult = aProp.Curvatures(1.0, 0.5, THE_LIN_TOL); - ASSERT_TRUE(aResult.IsDefined); - EXPECT_LE(aResult.MinCurvature, aResult.MaxCurvature); -} - -// Cross-validate revolved parabola vs SLProps -TEST(GeomProp_SurfaceOfRevolutionTest, VsSLProps_RevolveParabola) -{ - occ::handle aSurf = makeRevolveParabola(); - compareAllSurface(aSurf, 0.1, 2.0 * M_PI - 0.1, -2.0, 2.0); -} - -// Dense 8x8 grid cross-validation for revolved circle -TEST(GeomProp_SurfaceOfRevolutionTest, VsSLProps_DenseGrid_Circle) -{ - occ::handle aSurf = makeRevolveCircle(); - compareAllSurface(aSurf, 0.1, 2.0 * M_PI - 0.1, 0.1, 2.0 * M_PI - 0.1, 8, 8); -} - -// Circumferential curvature is constant along U for revolved line (cylinder) -TEST(GeomProp_SurfaceOfRevolutionTest, Curvatures_ConstantAlongU) -{ - occ::handle aSurf = makeRevolveLine(); - GeomProp_Surface aProp(aSurf); - - const GeomProp::SurfaceCurvatureResult aRefResult = aProp.Curvatures(0.5, 0.0, THE_LIN_TOL); - ASSERT_TRUE(aRefResult.IsDefined); - - for (double aU = 0.0; aU < 2.0 * M_PI; aU += M_PI / 4.0) - { - const GeomProp::SurfaceCurvatureResult aResult = aProp.Curvatures(aU, 0.0, THE_LIN_TOL); - ASSERT_TRUE(aResult.IsDefined) << "Curvatures undefined at u=" << aU; - EXPECT_NEAR(aResult.MinCurvature, aRefResult.MinCurvature, THE_CURV_TOL) - << "MinCurvature varies along U at u=" << aU; - EXPECT_NEAR(aResult.MaxCurvature, aRefResult.MaxCurvature, THE_CURV_TOL) - << "MaxCurvature varies along U at u=" << aU; - } -} - -TEST(GeomProp_SurfaceOfRevolutionTest, VsSLProps_CriticalPoints) -{ - // Revolve a line to get a cylinder - occ::handle aLine = new Geom_Line(gp_Pnt(5, 0, 0), gp_Dir(0, 0, 1)); - occ::handle aSurf = - new Geom_SurfaceOfRevolution(aLine, gp_Ax1(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1))); - // Critical: seam, various v, near-seam - const double aParams[][2] = {{0.0, 0.0}, - {1.0e-10, 0.0}, - {2.0 * M_PI - 1.0e-10, 0.0}, - {M_PI / 2.0, 0.0}, - {M_PI, 0.0}, - {M_PI / 4.0, 1.0}, - {M_PI / 4.0, -1.0}, - {M_PI / 4.0, 100.0}, - {0.0, 1.0e-10}, - {M_PI, 1.0e-10}}; - for (const auto& aUV : aParams) - { - compareNormal(aSurf, aUV[0], aUV[1]); - compareCurvatures(aSurf, aUV[0], aUV[1]); - compareMeanGaussian(aSurf, aUV[0], aUV[1]); - } -} diff --git a/src/ModelingData/TKG3d/GTests/GeomProp_Test.cxx b/src/ModelingData/TKG3d/GTests/GeomProp_Test.cxx deleted file mode 100644 index e7b717d83a..0000000000 --- a/src/ModelingData/TKG3d/GTests/GeomProp_Test.cxx +++ /dev/null @@ -1,563 +0,0 @@ -// 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. - -// Unit tests for GeomProp free functions and result structures. - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -// ============================================================================ -// Free function tests - ComputeTangent -// ============================================================================ - -TEST(GeomPropTest, ComputeTangent_D1NonZero) -{ - const gp_Vec aD1(1.0, 0.0, 0.0); - const gp_Vec aD2(0.0, 1.0, 0.0); - const gp_Vec aD3(0.0, 0.0, 1.0); - const GeomProp::TangentResult aRes = - GeomProp::ComputeTangent(aD1, aD2, aD3, Precision::Confusion()); - ASSERT_TRUE(aRes.IsDefined); - EXPECT_NEAR(aRes.Direction.X(), 1.0, Precision::Confusion()); - EXPECT_NEAR(aRes.Direction.Y(), 0.0, Precision::Confusion()); - EXPECT_NEAR(aRes.Direction.Z(), 0.0, Precision::Confusion()); -} - -TEST(GeomPropTest, ComputeTangent_D1Zero_D2NonZero) -{ - const gp_Vec aD1(0.0, 0.0, 0.0); - const gp_Vec aD2(0.0, 1.0, 0.0); - const gp_Vec aD3(0.0, 0.0, 1.0); - const GeomProp::TangentResult aRes = - GeomProp::ComputeTangent(aD1, aD2, aD3, Precision::Confusion()); - ASSERT_TRUE(aRes.IsDefined); - EXPECT_NEAR(aRes.Direction.Y(), 1.0, Precision::Confusion()); -} - -TEST(GeomPropTest, ComputeTangent_AllZero) -{ - const gp_Vec aD1(0.0, 0.0, 0.0); - const gp_Vec aD2(0.0, 0.0, 0.0); - const gp_Vec aD3(0.0, 0.0, 0.0); - const GeomProp::TangentResult aRes = - GeomProp::ComputeTangent(aD1, aD2, aD3, Precision::Confusion()); - EXPECT_FALSE(aRes.IsDefined); -} - -// ============================================================================ -// Free function tests - ComputeCurvature -// ============================================================================ - -TEST(GeomPropTest, ComputeCurvature_CircularArc) -{ - // At (1,0,0) on unit circle in XY plane: D1=(0,1,0), D2=(-1,0,0) - const gp_Vec aD1(0.0, 1.0, 0.0); - const gp_Vec aD2(-1.0, 0.0, 0.0); - const GeomProp::CurvatureResult aRes = - GeomProp::ComputeCurvature(aD1, aD2, Precision::Confusion()); - ASSERT_TRUE(aRes.IsDefined); - EXPECT_FALSE(aRes.IsInfinite); - EXPECT_NEAR(aRes.Value, 1.0, 1.0e-10); -} - -TEST(GeomPropTest, ComputeCurvature_ZeroD1) -{ - const gp_Vec aD1(0.0, 0.0, 0.0); - const gp_Vec aD2(1.0, 0.0, 0.0); - const GeomProp::CurvatureResult aRes = - GeomProp::ComputeCurvature(aD1, aD2, Precision::Confusion()); - EXPECT_TRUE(aRes.IsDefined); - EXPECT_TRUE(aRes.IsInfinite); -} - -TEST(GeomPropTest, ComputeCurvature_StraightLine) -{ - const gp_Vec aD1(1.0, 0.0, 0.0); - const gp_Vec aD2(0.0, 0.0, 0.0); - const GeomProp::CurvatureResult aRes = - GeomProp::ComputeCurvature(aD1, aD2, Precision::Confusion()); - EXPECT_TRUE(aRes.IsDefined); - EXPECT_NEAR(aRes.Value, 0.0, Precision::Confusion()); -} - -// ============================================================================ -// Free function tests - ComputeNormal -// ============================================================================ - -TEST(GeomPropTest, ComputeNormal_CircularArc) -{ - const gp_Vec aD1(0.0, 1.0, 0.0); - const gp_Vec aD2(-1.0, 0.0, 0.0); - const GeomProp::NormalResult aRes = GeomProp::ComputeNormal(aD1, aD2, Precision::Confusion()); - ASSERT_TRUE(aRes.IsDefined); - EXPECT_NEAR(aRes.Direction.X(), -1.0, Precision::Confusion()); -} - -// ============================================================================ -// Free function tests - ComputeSurfaceNormal -// ============================================================================ - -TEST(GeomPropTest, ComputeSurfaceNormal_XYPlane) -{ - const gp_Vec aD1U(1.0, 0.0, 0.0); - const gp_Vec aD1V(0.0, 1.0, 0.0); - const GeomProp::SurfaceNormalResult aRes = - GeomProp::ComputeSurfaceNormal(aD1U, aD1V, Precision::Confusion()); - ASSERT_TRUE(aRes.IsDefined); - EXPECT_NEAR(std::abs(aRes.Direction.Z()), 1.0, Precision::Confusion()); -} - -TEST(GeomPropTest, ComputeSurfaceNormal_DegeneratePoint) -{ - const gp_Vec aD1U(0.0, 0.0, 0.0); - const gp_Vec aD1V(0.0, 1.0, 0.0); - const GeomProp::SurfaceNormalResult aRes = - GeomProp::ComputeSurfaceNormal(aD1U, aD1V, Precision::Confusion()); - EXPECT_FALSE(aRes.IsDefined); -} - -// ============================================================================ -// Free function tests - ComputeMeanGaussian -// ============================================================================ - -TEST(GeomPropTest, ComputeMeanGaussian_Sphere) -{ - // At north pole of unit sphere, D1U and D1V are orthogonal unit vectors - const gp_Vec aD1U(1.0, 0.0, 0.0); - const gp_Vec aD1V(0.0, 1.0, 0.0); - const gp_Vec aD2U(0.0, 0.0, -1.0); - const gp_Vec aD2V(0.0, 0.0, -1.0); - const gp_Vec aDUV(0.0, 0.0, 0.0); - const GeomProp::MeanGaussianResult aRes = - GeomProp::ComputeMeanGaussian(aD1U, aD1V, aD2U, aD2V, aDUV, Precision::Confusion()); - ASSERT_TRUE(aRes.IsDefined); - EXPECT_NEAR(aRes.MeanCurvature, -1.0, 1.0e-10); - EXPECT_NEAR(aRes.GaussianCurvature, 1.0, 1.0e-10); -} - -// ============================================================================ -// GeomProp_Curve - initialization and basic queries -// ============================================================================ - -TEST(GeomPropCurveTest, Line_ZeroCurvature) -{ - occ::handle aLine = new Geom_Line(gp_Pnt(0, 0, 0), gp_Dir(1, 0, 0)); - GeomProp_Curve aProp(aLine); - EXPECT_EQ(aProp.GetType(), GeomAbs_Line); - - const GeomProp::CurvatureResult aCurv = aProp.Curvature(0.5, Precision::Confusion()); - EXPECT_TRUE(aCurv.IsDefined); - EXPECT_NEAR(aCurv.Value, 0.0, Precision::Confusion()); -} - -TEST(GeomPropCurveTest, Circle_ConstantCurvature) -{ - const double aRadius = 5.0; - gp_Circ aCirc(gp_Ax2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), aRadius); - occ::handle aCircle = new Geom_Circle(aCirc); - - GeomProp_Curve aProp(aCircle); - EXPECT_EQ(aProp.GetType(), GeomAbs_Circle); - - const GeomProp::CurvatureResult aCurv = aProp.Curvature(1.0, Precision::Confusion()); - ASSERT_TRUE(aCurv.IsDefined); - EXPECT_NEAR(aCurv.Value, 1.0 / aRadius, 1.0e-10); -} - -TEST(GeomPropCurveTest, Ellipse_CurvatureExtrema) -{ - const double aMajor = 10.0; - const double aMinor = 5.0; - gp_Elips anElips(gp_Ax2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), aMajor, aMinor); - occ::handle anEllipse = new Geom_Ellipse(anElips); - - GeomProp_Curve aProp(anEllipse); - - const GeomProp::CurveAnalysis aResult = aProp.FindCurvatureExtrema(); - ASSERT_TRUE(aResult.IsDone); - EXPECT_EQ(aResult.Points.Length(), 4); -} - -TEST(GeomPropCurveTest, Hyperbola_SingleExtremum) -{ - gp_Hypr anHypr(gp_Ax2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), 6.0, 3.0); - occ::handle aHyperbola = new Geom_Hyperbola(anHypr); - - GeomProp_Curve aProp(aHyperbola); - - const GeomProp::CurveAnalysis aResult = aProp.FindCurvatureExtrema(); - ASSERT_TRUE(aResult.IsDone); - EXPECT_EQ(aResult.Points.Length(), 1); - EXPECT_NEAR(aResult.Points[0].Parameter, 0.0, Precision::Confusion()); -} - -TEST(GeomPropCurveTest, Parabola_SingleExtremum) -{ - gp_Parab aParab(gp_Ax2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), 2.0); - occ::handle aParabola = new Geom_Parabola(aParab); - - GeomProp_Curve aProp(aParabola); - - const GeomProp::CurveAnalysis aResult = aProp.FindCurvatureExtrema(); - ASSERT_TRUE(aResult.IsDone); - EXPECT_EQ(aResult.Points.Length(), 1); - EXPECT_NEAR(aResult.Points[0].Parameter, 0.0, Precision::Confusion()); -} - -TEST(GeomPropCurveTest, Circle_NoExtrema) -{ - gp_Circ aCirc(gp_Ax2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), 5.0); - occ::handle aCircle = new Geom_Circle(aCirc); - - GeomProp_Curve aProp(aCircle); - const GeomProp::CurveAnalysis aResult = aProp.FindCurvatureExtrema(); - ASSERT_TRUE(aResult.IsDone); - EXPECT_EQ(aResult.Points.Length(), 0); -} - -TEST(GeomPropCurveTest, Circle_NoInflections) -{ - gp_Circ aCirc(gp_Ax2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), 5.0); - occ::handle aCircle = new Geom_Circle(aCirc); - - GeomProp_Curve aProp(aCircle); - const GeomProp::CurveAnalysis aResult = aProp.FindInflections(); - ASSERT_TRUE(aResult.IsDone); - EXPECT_EQ(aResult.Points.Length(), 0); -} - -TEST(GeomPropCurveTest, BezierCurve_Inflections) -{ - NCollection_Array1 aPoles(1, 4); - aPoles(1) = gp_Pnt(0, 0, 0); - aPoles(2) = gp_Pnt(1, 2, 0); - aPoles(3) = gp_Pnt(3, -1, 0); - aPoles(4) = gp_Pnt(4, 1, 0); - occ::handle aBezier = new Geom_BezierCurve(aPoles); - - GeomProp_Curve aProp(aBezier); - EXPECT_EQ(aProp.GetType(), GeomAbs_BezierCurve); - - const GeomProp::CurveAnalysis aResult = aProp.FindInflections(); - ASSERT_TRUE(aResult.IsDone); - EXPECT_GE(aResult.Points.Length(), 1); -} - -TEST(GeomPropCurveTest, Line_TangentDirection) -{ - occ::handle aLine = new Geom_Line(gp_Pnt(0, 0, 0), gp_Dir(0, 1, 0)); - GeomProp_Curve aProp(aLine); - - const GeomProp::TangentResult aTan = aProp.Tangent(5.0, Precision::Confusion()); - ASSERT_TRUE(aTan.IsDefined); - EXPECT_NEAR(aTan.Direction.Y(), 1.0, Precision::Confusion()); -} - -TEST(GeomPropCurveTest, Circle_Normal) -{ - gp_Circ aCirc(gp_Ax2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), 5.0); - occ::handle aCircle = new Geom_Circle(aCirc); - - GeomProp_Curve aProp(aCircle); - - // At param=0, point is (5,0,0), normal should point toward center (-1,0,0) - const GeomProp::NormalResult aNorm = aProp.Normal(0.0, Precision::Confusion()); - ASSERT_TRUE(aNorm.IsDefined); - EXPECT_NEAR(aNorm.Direction.X(), -1.0, 1.0e-6); -} - -TEST(GeomPropCurveTest, Circle_CentreOfCurvature) -{ - gp_Circ aCirc(gp_Ax2(gp_Pnt(1, 2, 3), gp_Dir(0, 0, 1)), 5.0); - occ::handle aCircle = new Geom_Circle(aCirc); - - GeomProp_Curve aProp(aCircle); - - const GeomProp::CentreResult aCentre = aProp.CentreOfCurvature(0.0, Precision::Confusion()); - ASSERT_TRUE(aCentre.IsDefined); - EXPECT_NEAR(aCentre.Centre.X(), 1.0, 1.0e-6); - EXPECT_NEAR(aCentre.Centre.Y(), 2.0, 1.0e-6); - EXPECT_NEAR(aCentre.Centre.Z(), 3.0, 1.0e-6); -} - -// ============================================================================ -// GeomProp_Surface - initialization and basic queries -// ============================================================================ - -TEST(GeomPropSurfaceTest, Plane_ZeroCurvatures) -{ - occ::handle aPlane = new Geom_Plane(gp_Ax3()); - - GeomProp_Surface aProp(aPlane); - EXPECT_EQ(aProp.GetType(), GeomAbs_Plane); - - const GeomProp::SurfaceCurvatureResult aCurv = aProp.Curvatures(0.0, 0.0, Precision::Confusion()); - ASSERT_TRUE(aCurv.IsDefined); - EXPECT_TRUE(aCurv.IsUmbilic); - EXPECT_NEAR(aCurv.MinCurvature, 0.0, Precision::Confusion()); - EXPECT_NEAR(aCurv.MaxCurvature, 0.0, Precision::Confusion()); -} - -TEST(GeomPropSurfaceTest, Plane_Normal) -{ - occ::handle aPlane = new Geom_Plane(gp_Ax3()); - - GeomProp_Surface aProp(aPlane); - - const GeomProp::SurfaceNormalResult aNorm = aProp.Normal(0.0, 0.0, Precision::Confusion()); - ASSERT_TRUE(aNorm.IsDefined); - EXPECT_NEAR(std::abs(aNorm.Direction.Z()), 1.0, Precision::Confusion()); -} - -TEST(GeomPropSurfaceTest, Plane_MeanGaussian) -{ - occ::handle aPlane = new Geom_Plane(gp_Ax3()); - - GeomProp_Surface aProp(aPlane); - - const GeomProp::MeanGaussianResult aRes = aProp.MeanGaussian(0.0, 0.0, Precision::Confusion()); - ASSERT_TRUE(aRes.IsDefined); - EXPECT_NEAR(aRes.MeanCurvature, 0.0, Precision::Confusion()); - EXPECT_NEAR(aRes.GaussianCurvature, 0.0, Precision::Confusion()); -} - -TEST(GeomPropSurfaceTest, Sphere_ConstantCurvature) -{ - const double aRadius = 5.0; - occ::handle aSphere = new Geom_SphericalSurface(gp_Ax3(), aRadius); - - GeomProp_Surface aProp(aSphere); - EXPECT_EQ(aProp.GetType(), GeomAbs_Sphere); - - // Curvature sign depends on normal orientation. For outward-pointing normal, - // convex surfaces have negative curvature (center on opposite side of normal). - const GeomProp::SurfaceCurvatureResult aCurv = aProp.Curvatures(0.5, 0.5, Precision::Confusion()); - ASSERT_TRUE(aCurv.IsDefined); - EXPECT_NEAR(std::abs(aCurv.MinCurvature), 1.0 / aRadius, 1.0e-10); - EXPECT_NEAR(std::abs(aCurv.MaxCurvature), 1.0 / aRadius, 1.0e-10); -} - -TEST(GeomPropSurfaceTest, Sphere_MeanGaussian) -{ - const double aRadius = 5.0; - occ::handle aSphere = new Geom_SphericalSurface(gp_Ax3(), aRadius); - - GeomProp_Surface aProp(aSphere); - - const GeomProp::MeanGaussianResult aRes = aProp.MeanGaussian(0.5, 0.5, Precision::Confusion()); - ASSERT_TRUE(aRes.IsDefined); - EXPECT_NEAR(std::abs(aRes.MeanCurvature), 1.0 / aRadius, 1.0e-10); - EXPECT_NEAR(aRes.GaussianCurvature, 1.0 / (aRadius * aRadius), 1.0e-10); -} - -TEST(GeomPropSurfaceTest, Cylinder_Curvatures) -{ - const double aRadius = 3.0; - occ::handle aCyl = new Geom_CylindricalSurface(gp_Ax3(), aRadius); - - GeomProp_Surface aProp(aCyl); - EXPECT_EQ(aProp.GetType(), GeomAbs_Cylinder); - - const GeomProp::SurfaceCurvatureResult aCurv = aProp.Curvatures(0.5, 1.0, Precision::Confusion()); - ASSERT_TRUE(aCurv.IsDefined); - // One curvature is zero (along axis), the other is non-zero (1/R with sign from normal). - const double aAbsMin = std::abs(aCurv.MinCurvature); - const double aAbsMax = std::abs(aCurv.MaxCurvature); - EXPECT_TRUE(aAbsMin < 1.0e-10 || aAbsMax < 1.0e-10); - EXPECT_NEAR(std::max(aAbsMin, aAbsMax), 1.0 / aRadius, 1.0e-10); -} - -TEST(GeomPropSurfaceTest, Cylinder_MeanGaussian) -{ - const double aRadius = 3.0; - occ::handle aCyl = new Geom_CylindricalSurface(gp_Ax3(), aRadius); - - GeomProp_Surface aProp(aCyl); - - const GeomProp::MeanGaussianResult aRes = aProp.MeanGaussian(0.5, 1.0, Precision::Confusion()); - ASSERT_TRUE(aRes.IsDefined); - EXPECT_NEAR(std::abs(aRes.MeanCurvature), 1.0 / (2.0 * aRadius), 1.0e-10); - EXPECT_NEAR(aRes.GaussianCurvature, 0.0, Precision::Confusion()); -} - -TEST(GeomPropSurfaceTest, Cone_CurvaturesVaryAlongV) -{ - gp_Ax3 anAx3; - occ::handle aCone = new Geom_ConicalSurface(anAx3, M_PI / 6.0, 5.0); - - GeomProp_Surface aProp(aCone); - EXPECT_EQ(aProp.GetType(), GeomAbs_Cone); - - const GeomProp::SurfaceCurvatureResult aCurv1 = - aProp.Curvatures(0.5, 0.0, Precision::Confusion()); - const GeomProp::SurfaceCurvatureResult aCurv2 = - aProp.Curvatures(0.5, 5.0, Precision::Confusion()); - ASSERT_TRUE(aCurv1.IsDefined); - ASSERT_TRUE(aCurv2.IsDefined); - // One curvature is zero (along ruling), the other varies with V. - // The magnitude of the non-zero curvature should decrease with V (larger radius). - const double aNonZero1 = std::max(std::abs(aCurv1.MinCurvature), std::abs(aCurv1.MaxCurvature)); - const double aNonZero2 = std::max(std::abs(aCurv2.MinCurvature), std::abs(aCurv2.MaxCurvature)); - EXPECT_GT(aNonZero1, aNonZero2); -} - -TEST(GeomPropSurfaceTest, Torus_CurvaturesVaryAlongV) -{ - const double aMajor = 10.0; - const double aMinor = 3.0; - occ::handle aTorus = new Geom_ToroidalSurface(gp_Ax3(), aMajor, aMinor); - - GeomProp_Surface aProp(aTorus); - EXPECT_EQ(aProp.GetType(), GeomAbs_Torus); - - // At V=0 (outer edge): k1=1/r, k2=1/(R+r) - const GeomProp::MeanGaussianResult aRes0 = aProp.MeanGaussian(0.0, 0.0, Precision::Confusion()); - ASSERT_TRUE(aRes0.IsDefined); - EXPECT_GT(aRes0.GaussianCurvature, 0.0); // Both curvatures positive at outer edge - - // At V=PI (inner edge): k1=1/r, k2=-1/(R-r) (negative) - const GeomProp::MeanGaussianResult aResPI = aProp.MeanGaussian(0.0, M_PI, Precision::Confusion()); - ASSERT_TRUE(aResPI.IsDefined); - EXPECT_LT(aResPI.GaussianCurvature, 0.0); // Negative Gaussian curvature at inner edge -} - -// ============================================================================ -// Geometry() / Adaptor() accessor tests -// ============================================================================ - -TEST(GeomPropCurveTest, Geometry_HandlePath_ReturnsNonNull) -{ - occ::handle aLine = new Geom_Line(gp_Pnt(), gp_Dir(1, 0, 0)); - GeomProp_Curve aProp(aLine); - EXPECT_NE(aProp.Geometry(), nullptr); - EXPECT_EQ(aProp.Adaptor(), nullptr); -} - -TEST(GeomPropCurveTest, Geometry_AdaptorPath_Line_ReturnsNonNull) -{ - occ::handle aLine = new Geom_Line(gp_Pnt(), gp_Dir(1, 0, 0)); - GeomAdaptor_Curve anAdaptor(aLine); - GeomProp_Curve aProp(anAdaptor); - // Line evaluator extracts geometry from adaptor - EXPECT_NE(aProp.Geometry(), nullptr); -} - -TEST(GeomPropCurveTest, Geometry_TrimmedCurve_ReturnsBasisCurve) -{ - occ::handle aCircle = new Geom_Circle(gp_Ax2(), 5.0); - occ::handle aTrimmed = new Geom_TrimmedCurve(aCircle, 0.0, M_PI); - GeomProp_Curve aProp(aTrimmed); - - const Geom_Curve* aGeom = aProp.Geometry(); - ASSERT_NE(aGeom, nullptr); - // The geometry should be the unwrapped basis circle, not the trimmed curve. - EXPECT_TRUE(aGeom->IsKind(STANDARD_TYPE(Geom_Circle))); -} - -TEST(GeomPropCurveTest, Geometry_AllCurveTypes_NonNull) -{ - // Line - { - occ::handle aCurve = new Geom_Line(gp_Pnt(), gp_Dir(0, 0, 1)); - GeomProp_Curve aProp(aCurve); - EXPECT_NE(aProp.Geometry(), nullptr); - } - // Ellipse - { - occ::handle aCurve = new Geom_Ellipse(gp_Ax2(), 5.0, 3.0); - GeomProp_Curve aProp(aCurve); - EXPECT_NE(aProp.Geometry(), nullptr); - } - // Hyperbola - { - occ::handle aCurve = new Geom_Hyperbola(gp_Ax2(), 5.0, 3.0); - GeomProp_Curve aProp(aCurve); - EXPECT_NE(aProp.Geometry(), nullptr); - } - // Parabola - { - occ::handle aCurve = new Geom_Parabola(gp_Ax2(), 2.0); - GeomProp_Curve aProp(aCurve); - EXPECT_NE(aProp.Geometry(), nullptr); - } -} - -TEST(GeomPropSurfaceTest, Geometry_HandlePath_ReturnsNonNull) -{ - occ::handle aPlane = new Geom_Plane(gp_Ax3()); - GeomProp_Surface aProp(aPlane); - EXPECT_NE(aProp.Geometry(), nullptr); - EXPECT_EQ(aProp.Adaptor(), nullptr); -} - -TEST(GeomPropSurfaceTest, Geometry_AdaptorPath_ReturnsNull) -{ - // On the adaptor path, most evaluators do not extract the geometry handle - occ::handle aSphere = new Geom_SphericalSurface(gp_Ax3(), 5.0); - GeomAdaptor_Surface anAdaptor(aSphere); - GeomProp_Surface aProp(anAdaptor); - EXPECT_EQ(aProp.Geometry(), nullptr); -} - -TEST(GeomPropCurveTest, Continuity_TwoLines_C1) -{ - occ::handle aL1 = new Geom_Line(gp_Pnt(0, 0, 0), gp_Dir(1, 0, 0)); - occ::handle aL2 = new Geom_Line(gp_Pnt(1, 0, 0), gp_Dir(1, 0, 0)); - // Junction at u1=1 (point (1,0,0)) and u2=0 (point (1,0,0)) - GeomAbs_Shape aCont = GeomProp_Curve::Continuity(aL1, aL2, 1.0, 0.0, false, false); - EXPECT_GE(aCont, GeomAbs_C1); -} - -TEST(GeomPropCurveTest, Continuity_ReversedDirection_G1) -{ - occ::handle aL1 = new Geom_Line(gp_Pnt(0, 0, 0), gp_Dir(1, 0, 0)); - occ::handle aL2 = new Geom_Line(gp_Pnt(1, 0, 0), gp_Dir(-1, 0, 0)); - // Same point, reversed tangent vectors - only G1 with reversal flags - GeomAbs_Shape aCont = GeomProp_Curve::Continuity(aL1, aL2, 1.0, 0.0, false, true); - EXPECT_GE(aCont, GeomAbs_C1); -} diff --git a/src/ModelingData/TKG3d/GTests/GeomProp_Torus_Test.cxx b/src/ModelingData/TKG3d/GTests/GeomProp_Torus_Test.cxx deleted file mode 100644 index c2b7f1ee9b..0000000000 --- a/src/ModelingData/TKG3d/GTests/GeomProp_Torus_Test.cxx +++ /dev/null @@ -1,416 +0,0 @@ -// 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. - -// Unit tests for GeomProp_Surface with ToroidalSurface geometry. - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -namespace -{ -constexpr double THE_LIN_TOL = Precision::PConfusion(); -constexpr double THE_CURV_TOL = 1.0e-6; -constexpr double THE_DIR_TOL = 1.0e-4; - -void compareNormal(const occ::handle& theSurf, const double theU, const double theV) -{ - GeomProp_Surface aProp(theSurf); - const GeomProp::SurfaceNormalResult aNew = aProp.Normal(theU, theV, THE_LIN_TOL); - - GeomLProp_SLProps anOld(theSurf, theU, theV, 2, THE_LIN_TOL); - if (anOld.IsNormalDefined()) - { - ASSERT_TRUE(aNew.IsDefined) << "New normal undefined at (" << theU << "," << theV << ")"; - const double aDot = aNew.Direction.Dot(anOld.Normal()); - EXPECT_NEAR(std::abs(aDot), 1.0, THE_DIR_TOL) - << "Normal mismatch at (" << theU << "," << theV << ")"; - } -} - -void compareCurvatures(const occ::handle& theSurf, - const double theU, - const double theV) -{ - GeomProp_Surface aProp(theSurf); - const GeomProp::SurfaceCurvatureResult aNew = aProp.Curvatures(theU, theV, THE_LIN_TOL); - - GeomLProp_SLProps anOld(theSurf, theU, theV, 2, THE_LIN_TOL); - if (anOld.IsCurvatureDefined()) - { - ASSERT_TRUE(aNew.IsDefined) << "New curvatures undefined at (" << theU << "," << theV << ")"; - EXPECT_NEAR(aNew.MinCurvature, anOld.MinCurvature(), THE_CURV_TOL) - << "MinCurvature mismatch at (" << theU << "," << theV << ")"; - EXPECT_NEAR(aNew.MaxCurvature, anOld.MaxCurvature(), THE_CURV_TOL) - << "MaxCurvature mismatch at (" << theU << "," << theV << ")"; - } -} - -void compareMeanGaussian(const occ::handle& theSurf, - const double theU, - const double theV) -{ - GeomProp_Surface aProp(theSurf); - const GeomProp::MeanGaussianResult aNew = aProp.MeanGaussian(theU, theV, THE_LIN_TOL); - - GeomLProp_SLProps anOld(theSurf, theU, theV, 2, THE_LIN_TOL); - if (anOld.IsCurvatureDefined()) - { - ASSERT_TRUE(aNew.IsDefined) << "New MeanGaussian undefined at (" << theU << "," << theV << ")"; - EXPECT_NEAR(aNew.MeanCurvature, anOld.MeanCurvature(), THE_CURV_TOL) - << "Mean curvature mismatch at (" << theU << "," << theV << ")"; - EXPECT_NEAR(aNew.GaussianCurvature, anOld.GaussianCurvature(), THE_CURV_TOL) - << "Gaussian curvature mismatch at (" << theU << "," << theV << ")"; - } -} - -void compareAllSurface(const occ::handle& theSurf, - const double theUMin, - const double theUMax, - const double theVMin, - const double theVMax, - const int theNbU = 5, - const int theNbV = 5) -{ - const double aUStep = (theUMax - theUMin) / theNbU; - const double aVStep = (theVMax - theVMin) / theNbV; - for (int i = 0; i <= theNbU; ++i) - { - for (int j = 0; j <= theNbV; ++j) - { - const double aU = theUMin + i * aUStep; - const double aV = theVMin + j * aVStep; - compareNormal(theSurf, aU, aV); - compareCurvatures(theSurf, aU, aV); - compareMeanGaussian(theSurf, aU, aV); - } - } -} -} // namespace - -// ============================================================================ -// Analytical reference tests -// ============================================================================ - -TEST(GeomProp_TorusTest, Normal_AtOuterEdge) -{ - const double aMajorR = 10.0; - const double aMinorR = 3.0; - occ::handle aTorus = new Geom_ToroidalSurface(gp_Ax3(), aMajorR, aMinorR); - GeomProp_Surface aProp(aTorus); - - // At u=0, v=0 (outer edge), point is (R+r, 0, 0), normal points outward along +X. - const GeomProp::SurfaceNormalResult aNorm = aProp.Normal(0.0, 0.0, THE_LIN_TOL); - ASSERT_TRUE(aNorm.IsDefined); - EXPECT_NEAR(std::abs(aNorm.Direction.X()), 1.0, THE_DIR_TOL); - EXPECT_NEAR(aNorm.Direction.Y(), 0.0, THE_DIR_TOL); - EXPECT_NEAR(aNorm.Direction.Z(), 0.0, THE_DIR_TOL); -} - -TEST(GeomProp_TorusTest, Normal_Grid) -{ - const double aMajorR = 10.0; - const double aMinorR = 3.0; - occ::handle aTorus = new Geom_ToroidalSurface(gp_Ax3(), aMajorR, aMinorR); - GeomProp_Surface aProp(aTorus); - - for (int i = 0; i < 12; ++i) - { - for (int j = 0; j < 12; ++j) - { - const double aU = i * M_PI / 6.0; - const double aV = j * M_PI / 6.0; - const GeomProp::SurfaceNormalResult aNorm = aProp.Normal(aU, aV, THE_LIN_TOL); - ASSERT_TRUE(aNorm.IsDefined) << "Normal undefined at (" << aU << "," << aV << ")"; - } - } -} - -TEST(GeomProp_TorusTest, Curvatures_AtOuterEdge) -{ - const double aMajorR = 10.0; - const double aMinorR = 3.0; - occ::handle aTorus = new Geom_ToroidalSurface(gp_Ax3(), aMajorR, aMinorR); - GeomProp_Surface aProp(aTorus); - - // At outer edge (v=0): both principal curvatures are positive. - const GeomProp::SurfaceCurvatureResult aCurv = aProp.Curvatures(0.0, 0.0, THE_LIN_TOL); - ASSERT_TRUE(aCurv.IsDefined); - // Both curvatures should have the same sign (positive for outward normal convention). - EXPECT_TRUE((aCurv.MinCurvature >= -THE_CURV_TOL && aCurv.MaxCurvature >= -THE_CURV_TOL) - || (aCurv.MinCurvature <= THE_CURV_TOL && aCurv.MaxCurvature <= THE_CURV_TOL)); -} - -TEST(GeomProp_TorusTest, Curvatures_AtInnerEdge) -{ - const double aMajorR = 10.0; - const double aMinorR = 3.0; - occ::handle aTorus = new Geom_ToroidalSurface(gp_Ax3(), aMajorR, aMinorR); - GeomProp_Surface aProp(aTorus); - - // At inner edge (v=PI): principal curvatures have opposite signs. - const GeomProp::SurfaceCurvatureResult aCurv = aProp.Curvatures(0.0, M_PI, THE_LIN_TOL); - ASSERT_TRUE(aCurv.IsDefined); - EXPECT_LT(aCurv.MinCurvature * aCurv.MaxCurvature, THE_CURV_TOL) - << "Expected opposite sign curvatures at inner edge"; -} - -TEST(GeomProp_TorusTest, Curvatures_VaryWithV) -{ - const double aMajorR = 10.0; - const double aMinorR = 3.0; - occ::handle aTorus = new Geom_ToroidalSurface(gp_Ax3(), aMajorR, aMinorR); - GeomProp_Surface aProp(aTorus); - - const GeomProp::SurfaceCurvatureResult aCurvOuter = aProp.Curvatures(0.0, 0.0, THE_LIN_TOL); - const GeomProp::SurfaceCurvatureResult aCurvInner = aProp.Curvatures(0.0, M_PI, THE_LIN_TOL); - ASSERT_TRUE(aCurvOuter.IsDefined); - ASSERT_TRUE(aCurvInner.IsDefined); - // The circumferential curvature (MaxCurvature) differs between inner and outer edge. - // The meridional curvature (MinCurvature = -1/r) is constant. - EXPECT_NE(aCurvOuter.MaxCurvature, aCurvInner.MaxCurvature); -} - -TEST(GeomProp_TorusTest, MeanGaussian_GaussianPositiveOuter) -{ - const double aMajorR = 10.0; - const double aMinorR = 3.0; - occ::handle aTorus = new Geom_ToroidalSurface(gp_Ax3(), aMajorR, aMinorR); - GeomProp_Surface aProp(aTorus); - - const GeomProp::MeanGaussianResult aMG = aProp.MeanGaussian(0.0, 0.0, THE_LIN_TOL); - ASSERT_TRUE(aMG.IsDefined); - EXPECT_GT(aMG.GaussianCurvature, 0.0); -} - -TEST(GeomProp_TorusTest, MeanGaussian_GaussianNegativeInner) -{ - const double aMajorR = 10.0; - const double aMinorR = 3.0; - occ::handle aTorus = new Geom_ToroidalSurface(gp_Ax3(), aMajorR, aMinorR); - GeomProp_Surface aProp(aTorus); - - const GeomProp::MeanGaussianResult aMG = aProp.MeanGaussian(0.0, M_PI, THE_LIN_TOL); - ASSERT_TRUE(aMG.IsDefined); - EXPECT_LT(aMG.GaussianCurvature, 0.0); -} - -TEST(GeomProp_TorusTest, MeanGaussian_GaussianZeroTop) -{ - const double aMajorR = 10.0; - const double aMinorR = 3.0; - occ::handle aTorus = new Geom_ToroidalSurface(gp_Ax3(), aMajorR, aMinorR); - GeomProp_Surface aProp(aTorus); - - // At v=PI/2, the Gaussian curvature should be approximately zero. - const GeomProp::MeanGaussianResult aMG = aProp.MeanGaussian(0.0, M_PI / 2.0, THE_LIN_TOL); - ASSERT_TRUE(aMG.IsDefined); - EXPECT_NEAR(aMG.GaussianCurvature, 0.0, THE_CURV_TOL); -} - -TEST(GeomProp_TorusTest, GetType_IsTorus) -{ - occ::handle aTorus = new Geom_ToroidalSurface(gp_Ax3(), 10.0, 3.0); - GeomProp_Surface aProp(aTorus); - - EXPECT_EQ(aProp.GetType(), GeomAbs_Torus); -} - -TEST(GeomProp_TorusTest, Curvatures_MinorCurvature) -{ - const double aMajorR = 10.0; - const double aMinorR = 3.0; - occ::handle aTorus = new Geom_ToroidalSurface(gp_Ax3(), aMajorR, aMinorR); - GeomProp_Surface aProp(aTorus); - - // The meridional curvature is always -1/r (signed, constant everywhere). - for (int j = 0; j < 8; ++j) - { - const double aV = j * M_PI / 4.0; - const GeomProp::SurfaceCurvatureResult aCurv = aProp.Curvatures(0.0, aV, THE_LIN_TOL); - ASSERT_TRUE(aCurv.IsDefined); - // MinCurvature is the meridional curvature = -1/r (constant, negative). - EXPECT_NEAR(aCurv.MinCurvature, -1.0 / aMinorR, THE_CURV_TOL) - << "Minor curvature wrong at v=" << aV; - } -} - -// ============================================================================ -// Cross-validation tests vs GeomLProp_SLProps -// ============================================================================ - -TEST(GeomProp_TorusTest, VsSLProps_Normal) -{ - occ::handle aTorus = new Geom_ToroidalSurface(gp_Ax3(), 10.0, 3.0); - const double aStep = M_PI / 3.0; - for (int i = 0; i <= 6; ++i) - { - for (int j = 0; j <= 6; ++j) - { - compareNormal(aTorus, i * aStep, j * aStep); - } - } -} - -TEST(GeomProp_TorusTest, VsSLProps_Curvatures) -{ - occ::handle aTorus = new Geom_ToroidalSurface(gp_Ax3(), 10.0, 3.0); - const double aStep = M_PI / 3.0; - for (int i = 0; i <= 6; ++i) - { - for (int j = 0; j <= 6; ++j) - { - compareCurvatures(aTorus, i * aStep, j * aStep); - } - } -} - -TEST(GeomProp_TorusTest, VsSLProps_MeanGaussian) -{ - occ::handle aTorus = new Geom_ToroidalSurface(gp_Ax3(), 10.0, 3.0); - const double aStep = M_PI / 3.0; - for (int i = 0; i <= 6; ++i) - { - for (int j = 0; j <= 6; ++j) - { - compareMeanGaussian(aTorus, i * aStep, j * aStep); - } - } -} - -TEST(GeomProp_TorusTest, VsSLProps_AllProperties) -{ - occ::handle aTorus = new Geom_ToroidalSurface(gp_Ax3(), 10.0, 3.0); - compareAllSurface(aTorus, 0.0, 2.0 * M_PI, 0.0, 2.0 * M_PI, 8, 8); -} - -TEST(GeomProp_TorusTest, VsSLProps_LargeRadii) -{ - occ::handle aTorus = new Geom_ToroidalSurface(gp_Ax3(), 100.0, 10.0); - compareAllSurface(aTorus, 0.0, 2.0 * M_PI, 0.0, 2.0 * M_PI); -} - -TEST(GeomProp_TorusTest, VsSLProps_SmallRadii) -{ - occ::handle aTorus = new Geom_ToroidalSurface(gp_Ax3(), 2.0, 0.5); - compareAllSurface(aTorus, 0.0, 2.0 * M_PI, 0.0, 2.0 * M_PI); -} - -TEST(GeomProp_TorusTest, MeanGaussian_Mean_AtOuterEdge) -{ - const double aMajorR = 10.0; - const double aMinorR = 3.0; - occ::handle aTorus = new Geom_ToroidalSurface(gp_Ax3(), aMajorR, aMinorR); - GeomProp_Surface aProp(aTorus); - - // H = (1/r + 1/(R+r)) / 2 - const double aExpectedH = (1.0 / aMinorR + 1.0 / (aMajorR + aMinorR)) / 2.0; - const GeomProp::MeanGaussianResult aMG = aProp.MeanGaussian(0.0, 0.0, THE_LIN_TOL); - ASSERT_TRUE(aMG.IsDefined); - EXPECT_NEAR(std::abs(aMG.MeanCurvature), aExpectedH, THE_CURV_TOL); -} - -TEST(GeomProp_TorusTest, MeanGaussian_Gaussian_AtOuterEdge) -{ - const double aMajorR = 10.0; - const double aMinorR = 3.0; - occ::handle aTorus = new Geom_ToroidalSurface(gp_Ax3(), aMajorR, aMinorR); - GeomProp_Surface aProp(aTorus); - - // K = 1 / (r * (R + r)) - const double aExpectedK = 1.0 / (aMinorR * (aMajorR + aMinorR)); - const GeomProp::MeanGaussianResult aMG = aProp.MeanGaussian(0.0, 0.0, THE_LIN_TOL); - ASSERT_TRUE(aMG.IsDefined); - EXPECT_NEAR(std::abs(aMG.GaussianCurvature), aExpectedK, THE_CURV_TOL); -} - -TEST(GeomProp_TorusTest, Curvatures_ConstantAlongU) -{ - const double aMajorR = 10.0; - const double aMinorR = 3.0; - occ::handle aTorus = new Geom_ToroidalSurface(gp_Ax3(), aMajorR, aMinorR); - GeomProp_Surface aProp(aTorus); - - // Curvatures depend only on v, not on u (axial symmetry). - const double aV = 0.5; - const GeomProp::SurfaceCurvatureResult aRef = aProp.Curvatures(0.0, aV, THE_LIN_TOL); - ASSERT_TRUE(aRef.IsDefined); - - for (int i = 1; i < 8; ++i) - { - const double aU = i * M_PI / 4.0; - const GeomProp::SurfaceCurvatureResult aCurv = aProp.Curvatures(aU, aV, THE_LIN_TOL); - ASSERT_TRUE(aCurv.IsDefined); - EXPECT_NEAR(aCurv.MinCurvature, aRef.MinCurvature, THE_CURV_TOL) - << "MinCurvature varies with u at u=" << aU; - EXPECT_NEAR(aCurv.MaxCurvature, aRef.MaxCurvature, THE_CURV_TOL) - << "MaxCurvature varies with u at u=" << aU; - } -} - -TEST(GeomProp_TorusTest, Normal_ConstantMagnitude) -{ - const double aMajorR = 10.0; - const double aMinorR = 3.0; - occ::handle aTorus = new Geom_ToroidalSurface(gp_Ax3(), aMajorR, aMinorR); - GeomProp_Surface aProp(aTorus); - - // gp_Dir is always a unit vector, so the normal magnitude is always 1. - for (int i = 0; i < 8; ++i) - { - for (int j = 0; j < 8; ++j) - { - const double aU = i * M_PI / 4.0; - const double aV = j * M_PI / 4.0; - const GeomProp::SurfaceNormalResult aNorm = aProp.Normal(aU, aV, THE_LIN_TOL); - ASSERT_TRUE(aNorm.IsDefined); - const double aMag = std::sqrt(aNorm.Direction.X() * aNorm.Direction.X() - + aNorm.Direction.Y() * aNorm.Direction.Y() - + aNorm.Direction.Z() * aNorm.Direction.Z()); - EXPECT_NEAR(aMag, 1.0, THE_DIR_TOL) << "Normal not unit at (" << aU << "," << aV << ")"; - } - } -} - -TEST(GeomProp_TorusTest, VsSLProps_CriticalPoints) -{ - occ::handle aTorus = new Geom_ToroidalSurface(gp_Ax3(), 10.0, 3.0); - // Critical: inner ring (v=PI), outer (v=0), top/bottom (v=+-PI/2), seam - const double aParams[][2] = {{0.0, 0.0}, - {0.0, M_PI}, - {0.0, M_PI / 2.0}, - {0.0, -M_PI / 2.0}, - {M_PI / 2.0, 0.0}, - {M_PI / 2.0, M_PI}, - {1.0e-10, 0.0}, - {0.0, 1.0e-10}, - {0.0, M_PI + 1.0e-6}, - {0.0, M_PI - 1.0e-6}, - {2.0 * M_PI - 1.0e-10, M_PI / 4.0}, - {M_PI / 4.0, 3.0 * M_PI / 4.0}}; - for (const auto& aUV : aParams) - { - compareNormal(aTorus, aUV[0], aUV[1]); - compareCurvatures(aTorus, aUV[0], aUV[1]); - compareMeanGaussian(aTorus, aUV[0], aUV[1]); - } -} diff --git a/src/ModelingData/TKG3d/GTests/GeomProp_VsCLProps_Test.cxx b/src/ModelingData/TKG3d/GTests/GeomProp_VsCLProps_Test.cxx deleted file mode 100644 index e9602c7f84..0000000000 --- a/src/ModelingData/TKG3d/GTests/GeomProp_VsCLProps_Test.cxx +++ /dev/null @@ -1,244 +0,0 @@ -// 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. - -// Cross-validation tests comparing GeomProp_Curve against GeomLProp_CLProps -// for local curve differential properties (tangent, curvature, normal, centre). - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -namespace -{ -constexpr double THE_LIN_TOL = Precision::PConfusion(); -constexpr double THE_CURV_TOL = 1.0e-8; -constexpr double THE_DIR_TOL = 1.0e-6; -constexpr double THE_POINT_TOL = 1.0e-6; - -//! Compare tangent from new GeomProp_Curve vs old GeomLProp_CLProps. -void compareTangent(const occ::handle& theCurve, const double theParam) -{ - GeomProp_Curve aProp(theCurve); - const GeomProp::TangentResult aNew = aProp.Tangent(theParam, THE_LIN_TOL); - - GeomLProp_CLProps anOld(theCurve, theParam, 2, THE_LIN_TOL); - if (anOld.IsTangentDefined()) - { - ASSERT_TRUE(aNew.IsDefined) << "New tangent undefined but old is defined at param=" << theParam; - gp_Dir anOldDir; - anOld.Tangent(anOldDir); - // Tangent directions may differ by sign - const double aDot = aNew.Direction.Dot(anOldDir); - EXPECT_NEAR(std::abs(aDot), 1.0, THE_DIR_TOL) - << "Tangent direction mismatch at param=" << theParam; - } -} - -//! Compare curvature from new GeomProp_Curve vs old GeomLProp_CLProps. -void compareCurvature(const occ::handle& theCurve, const double theParam) -{ - GeomProp_Curve aProp(theCurve); - const GeomProp::CurvatureResult aNew = aProp.Curvature(theParam, THE_LIN_TOL); - - GeomLProp_CLProps anOld(theCurve, theParam, 2, THE_LIN_TOL); - if (anOld.IsTangentDefined()) - { - ASSERT_TRUE(aNew.IsDefined) << "New curvature undefined at param=" << theParam; - EXPECT_NEAR(aNew.Value, anOld.Curvature(), THE_CURV_TOL) - << "Curvature mismatch at param=" << theParam; - } -} - -//! Compare normal from new GeomProp_Curve vs old GeomLProp_CLProps. -void compareNormal(const occ::handle& theCurve, const double theParam) -{ - GeomProp_Curve aProp(theCurve); - const GeomProp::NormalResult aNew = aProp.Normal(theParam, THE_LIN_TOL); - - GeomLProp_CLProps anOld(theCurve, theParam, 2, THE_LIN_TOL); - if (anOld.IsTangentDefined() && std::abs(anOld.Curvature()) > THE_LIN_TOL) - { - ASSERT_TRUE(aNew.IsDefined) << "New normal undefined at param=" << theParam; - gp_Dir anOldNorm; - anOld.Normal(anOldNorm); - const double aDot = aNew.Direction.Dot(anOldNorm); - EXPECT_NEAR(std::abs(aDot), 1.0, THE_DIR_TOL) - << "Normal direction mismatch at param=" << theParam; - } -} - -//! Compare centre of curvature from new vs old. -void compareCentre(const occ::handle& theCurve, const double theParam) -{ - GeomProp_Curve aProp(theCurve); - const GeomProp::CentreResult aNew = aProp.CentreOfCurvature(theParam, THE_LIN_TOL); - - GeomLProp_CLProps anOld(theCurve, theParam, 2, THE_LIN_TOL); - if (anOld.IsTangentDefined() && std::abs(anOld.Curvature()) > THE_LIN_TOL) - { - ASSERT_TRUE(aNew.IsDefined) << "New centre undefined at param=" << theParam; - gp_Pnt anOldCentre; - anOld.CentreOfCurvature(anOldCentre); - EXPECT_NEAR(aNew.Centre.Distance(anOldCentre), 0.0, THE_POINT_TOL) - << "Centre mismatch at param=" << theParam; - } -} - -//! Run all comparisons at several parameter values. -void compareAll(const occ::handle& theCurve, - const double theFirst, - const double theLast, - const int theNbSamples = 10) -{ - const double aStep = (theLast - theFirst) / theNbSamples; - for (int i = 0; i <= theNbSamples; ++i) - { - const double aParam = theFirst + i * aStep; - compareTangent(theCurve, aParam); - compareCurvature(theCurve, aParam); - compareNormal(theCurve, aParam); - compareCentre(theCurve, aParam); - } -} -} // namespace - -// ============================================================================ -// Line -// ============================================================================ - -TEST(GeomProp_VsCLPropsTest, Line) -{ - occ::handle aLine = new Geom_Line(gp_Pnt(0, 0, 0), gp_Dir(1, 1, 0)); - compareAll(aLine, -5.0, 5.0); -} - -// ============================================================================ -// Circle -// ============================================================================ - -TEST(GeomProp_VsCLPropsTest, Circle) -{ - gp_Circ aCirc(gp_Ax2(gp_Pnt(1, 2, 3), gp_Dir(0, 0, 1)), 5.0); - occ::handle aCircle = new Geom_Circle(aCirc); - compareAll(aCircle, 0.0, 2.0 * M_PI); -} - -// ============================================================================ -// Ellipse -// ============================================================================ - -TEST(GeomProp_VsCLPropsTest, Ellipse) -{ - gp_Elips anElips(gp_Ax2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), 10.0, 5.0); - occ::handle anEllipse = new Geom_Ellipse(anElips); - compareAll(anEllipse, 0.0, 2.0 * M_PI); -} - -// ============================================================================ -// Hyperbola -// ============================================================================ - -TEST(GeomProp_VsCLPropsTest, Hyperbola) -{ - gp_Hypr anHypr(gp_Ax2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), 6.0, 3.0); - occ::handle aHyperbola = new Geom_Hyperbola(anHypr); - compareAll(aHyperbola, -2.0, 2.0); -} - -// ============================================================================ -// Parabola -// ============================================================================ - -TEST(GeomProp_VsCLPropsTest, Parabola) -{ - gp_Parab aParab(gp_Ax2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), 2.0); - occ::handle aParabola = new Geom_Parabola(aParab); - compareAll(aParabola, -5.0, 5.0); -} - -// ============================================================================ -// Bezier -// ============================================================================ - -TEST(GeomProp_VsCLPropsTest, BezierCubic) -{ - NCollection_Array1 aPoles(1, 4); - aPoles(1) = gp_Pnt(0, 0, 0); - aPoles(2) = gp_Pnt(1, 2, 1); - aPoles(3) = gp_Pnt(3, -1, 0); - aPoles(4) = gp_Pnt(4, 1, 1); - occ::handle aBezier = new Geom_BezierCurve(aPoles); - compareAll(aBezier, 0.0, 1.0); -} - -// ============================================================================ -// BSpline -// ============================================================================ - -TEST(GeomProp_VsCLPropsTest, BSplineCubic) -{ - NCollection_Array1 aPoles(1, 6); - aPoles(1) = gp_Pnt(0, 0, 0); - aPoles(2) = gp_Pnt(1, 3, 0); - aPoles(3) = gp_Pnt(2, 1, 1); - aPoles(4) = gp_Pnt(3, 4, 0); - aPoles(5) = gp_Pnt(4, 2, 1); - aPoles(6) = gp_Pnt(5, 0, 0); - - NCollection_Array1 aKnots(1, 4); - aKnots(1) = 0.0; - aKnots(2) = 0.33; - aKnots(3) = 0.66; - aKnots(4) = 1.0; - - NCollection_Array1 aMults(1, 4); - aMults(1) = 4; - aMults(2) = 1; - aMults(3) = 1; - aMults(4) = 4; - - occ::handle aBSpline = new Geom_BSplineCurve(aPoles, aKnots, aMults, 3); - compareAll(aBSpline, 0.0, 1.0); -} - -// ============================================================================ -// Offset curve -// ============================================================================ - -TEST(GeomProp_VsCLPropsTest, OffsetCircle) -{ - gp_Circ aCirc(gp_Ax2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), 5.0); - occ::handle aCircle = new Geom_Circle(aCirc); - occ::handle anOffset = new Geom_OffsetCurve(aCircle, 2.0, gp_Dir(0, 0, 1)); - compareAll(anOffset, 0.0, 2.0 * M_PI); -} diff --git a/src/ModelingData/TKG3d/GTests/GeomProp_VsSLProps_Test.cxx b/src/ModelingData/TKG3d/GTests/GeomProp_VsSLProps_Test.cxx deleted file mode 100644 index c76027fdcd..0000000000 --- a/src/ModelingData/TKG3d/GTests/GeomProp_VsSLProps_Test.cxx +++ /dev/null @@ -1,210 +0,0 @@ -// 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. - -// Cross-validation tests comparing GeomProp_Surface against GeomLProp_SLProps -// for local surface differential properties (normal, curvatures). - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -namespace -{ -constexpr double THE_LIN_TOL = Precision::PConfusion(); -constexpr double THE_CURV_TOL = 1.0e-6; -constexpr double THE_DIR_TOL = 1.0e-4; - -//! Compare surface normal from new GeomProp_Surface vs old GeomLProp_SLProps. -void compareNormal(const occ::handle& theSurf, const double theU, const double theV) -{ - GeomProp_Surface aProp(theSurf); - const GeomProp::SurfaceNormalResult aNew = aProp.Normal(theU, theV, THE_LIN_TOL); - - GeomLProp_SLProps anOld(theSurf, theU, theV, 2, THE_LIN_TOL); - if (anOld.IsNormalDefined()) - { - ASSERT_TRUE(aNew.IsDefined) << "New normal undefined at (" << theU << "," << theV << ")"; - const gp_Dir anOldNorm = anOld.Normal(); - const double aDot = aNew.Direction.Dot(anOldNorm); - EXPECT_NEAR(std::abs(aDot), 1.0, THE_DIR_TOL) - << "Normal mismatch at (" << theU << "," << theV << ")"; - } -} - -//! Compare curvatures from new GeomProp_Surface vs old GeomLProp_SLProps. -void compareCurvatures(const occ::handle& theSurf, - const double theU, - const double theV) -{ - GeomProp_Surface aProp(theSurf); - const GeomProp::SurfaceCurvatureResult aNew = aProp.Curvatures(theU, theV, THE_LIN_TOL); - - GeomLProp_SLProps anOld(theSurf, theU, theV, 2, THE_LIN_TOL); - if (anOld.IsCurvatureDefined()) - { - ASSERT_TRUE(aNew.IsDefined) << "New curvatures undefined at (" << theU << "," << theV << ")"; - EXPECT_NEAR(aNew.MinCurvature, anOld.MinCurvature(), THE_CURV_TOL) - << "MinCurvature mismatch at (" << theU << "," << theV << ")"; - EXPECT_NEAR(aNew.MaxCurvature, anOld.MaxCurvature(), THE_CURV_TOL) - << "MaxCurvature mismatch at (" << theU << "," << theV << ")"; - // Note: IsUmbilic comparison intentionally omitted - the flag is tolerance-dependent - // and may differ between implementations while curvature values agree. - } -} - -//! Compare mean and Gaussian curvatures. -void compareMeanGaussian(const occ::handle& theSurf, - const double theU, - const double theV) -{ - GeomProp_Surface aProp(theSurf); - const GeomProp::MeanGaussianResult aNew = aProp.MeanGaussian(theU, theV, THE_LIN_TOL); - - GeomLProp_SLProps anOld(theSurf, theU, theV, 2, THE_LIN_TOL); - if (anOld.IsCurvatureDefined()) - { - ASSERT_TRUE(aNew.IsDefined) << "New MeanGaussian undefined at (" << theU << "," << theV << ")"; - EXPECT_NEAR(aNew.MeanCurvature, anOld.MeanCurvature(), THE_CURV_TOL) - << "Mean curvature mismatch at (" << theU << "," << theV << ")"; - EXPECT_NEAR(aNew.GaussianCurvature, anOld.GaussianCurvature(), THE_CURV_TOL) - << "Gaussian curvature mismatch at (" << theU << "," << theV << ")"; - } -} - -//! Run all surface comparisons at a grid of parameter values. -void compareAllSurface(const occ::handle& theSurf, - const double theUMin, - const double theUMax, - const double theVMin, - const double theVMax, - const int theNbU = 5, - const int theNbV = 5) -{ - const double aUStep = (theUMax - theUMin) / theNbU; - const double aVStep = (theVMax - theVMin) / theNbV; - for (int i = 0; i <= theNbU; ++i) - { - for (int j = 0; j <= theNbV; ++j) - { - const double aU = theUMin + i * aUStep; - const double aV = theVMin + j * aVStep; - compareNormal(theSurf, aU, aV); - compareCurvatures(theSurf, aU, aV); - compareMeanGaussian(theSurf, aU, aV); - } - } -} -} // namespace - -// ============================================================================ -// Plane -// ============================================================================ - -TEST(GeomProp_VsSLPropsTest, Plane) -{ - occ::handle aPlane = new Geom_Plane(gp_Ax3()); - compareAllSurface(aPlane, -5.0, 5.0, -5.0, 5.0); -} - -// ============================================================================ -// Sphere -// ============================================================================ - -TEST(GeomProp_VsSLPropsTest, Sphere) -{ - occ::handle aSphere = new Geom_SphericalSurface(gp_Ax3(), 5.0); - // Avoid poles where D1U degenerates - compareAllSurface(aSphere, 0.0, 2.0 * M_PI, -M_PI / 3.0, M_PI / 3.0); -} - -// ============================================================================ -// Cylinder -// ============================================================================ - -TEST(GeomProp_VsSLPropsTest, Cylinder) -{ - occ::handle aCyl = new Geom_CylindricalSurface(gp_Ax3(), 3.0); - compareAllSurface(aCyl, 0.0, 2.0 * M_PI, -5.0, 5.0); -} - -// ============================================================================ -// Cone -// ============================================================================ - -TEST(GeomProp_VsSLPropsTest, Cone) -{ - occ::handle aCone = new Geom_ConicalSurface(gp_Ax3(), M_PI / 6.0, 5.0); - // Stay away from the apex (at V = -R/sin(alpha) = -10) - compareAllSurface(aCone, 0.0, 2.0 * M_PI, 0.0, 10.0); -} - -// ============================================================================ -// Torus -// ============================================================================ - -TEST(GeomProp_VsSLPropsTest, Torus) -{ - occ::handle aTorus = new Geom_ToroidalSurface(gp_Ax3(), 10.0, 3.0); - compareAllSurface(aTorus, 0.0, 2.0 * M_PI, 0.0, 2.0 * M_PI); -} - -// ============================================================================ -// BSpline Surface -// ============================================================================ - -TEST(GeomProp_VsSLPropsTest, BSplineSurface) -{ - // Simple 4x4 bicubic patch - NCollection_Array2 aPoles(1, 4, 1, 4); - NCollection_Array1 aUKnots(1, 2), aVKnots(1, 2); - NCollection_Array1 aUMults(1, 2), aVMults(1, 2); - - aUKnots(1) = 0.0; - aUKnots(2) = 1.0; - aVKnots(1) = 0.0; - aVKnots(2) = 1.0; - aUMults(1) = 4; - aUMults(2) = 4; - aVMults(1) = 4; - aVMults(2) = 4; - - for (int i = 1; i <= 4; ++i) - { - for (int j = 1; j <= 4; ++j) - { - const double aX = i - 1; - const double aY = j - 1; - const double aZ = std::sin((i - 1) * 0.5) * std::cos((j - 1) * 0.5); - aPoles.SetValue(i, j, gp_Pnt(aX, aY, aZ)); - } - } - - occ::handle aSurf = - new Geom_BSplineSurface(aPoles, aUKnots, aVKnots, aUMults, aVMults, 3, 3); - - compareAllSurface(aSurf, 0.0, 1.0, 0.0, 1.0, 4, 4); -} diff --git a/src/ModelingData/TKG3d/GeomProp/FILES.cmake b/src/ModelingData/TKG3d/GeomProp/FILES.cmake deleted file mode 100644 index 85463e036a..0000000000 --- a/src/ModelingData/TKG3d/GeomProp/FILES.cmake +++ /dev/null @@ -1,48 +0,0 @@ -# Source files for GeomProp package -set(OCCT_GeomProp_FILES_LOCATION "${CMAKE_CURRENT_LIST_DIR}") - -set(OCCT_GeomProp_FILES - GeomProp.hxx - GeomProp.cxx - GeomProp_BezierCurve.hxx - GeomProp_BezierCurve.cxx - GeomProp_CurveAnalysisTools.pxx - GeomProp_SurfaceAnalysisTools.pxx - GeomProp_BezierSurface.hxx - GeomProp_BezierSurface.cxx - GeomProp_BSplineCurve.hxx - GeomProp_BSplineCurve.cxx - GeomProp_BSplineSurface.hxx - GeomProp_BSplineSurface.cxx - GeomProp_Circle.hxx - GeomProp_Cone.hxx - GeomProp_Cone.cxx - GeomProp_Curve.hxx - GeomProp_Curve.cxx - GeomProp_Cylinder.hxx - GeomProp_Ellipse.hxx - GeomProp_Ellipse.cxx - GeomProp_Hyperbola.hxx - GeomProp_Hyperbola.cxx - GeomProp_Line.hxx - GeomProp_OffsetCurve.hxx - GeomProp_OffsetCurve.cxx - GeomProp_OffsetSurface.hxx - GeomProp_OffsetSurface.cxx - GeomProp_OtherCurve.hxx - GeomProp_OtherCurve.cxx - GeomProp_OtherSurface.hxx - GeomProp_OtherSurface.cxx - GeomProp_Parabola.hxx - GeomProp_Parabola.cxx - GeomProp_Plane.hxx - GeomProp_Sphere.hxx - GeomProp_Surface.hxx - GeomProp_Surface.cxx - GeomProp_SurfaceOfExtrusion.hxx - GeomProp_SurfaceOfExtrusion.cxx - GeomProp_SurfaceOfRevolution.hxx - GeomProp_SurfaceOfRevolution.cxx - GeomProp_Torus.hxx - GeomProp_Torus.cxx -) diff --git a/src/ModelingData/TKG3d/GeomProp/GeomProp.cxx b/src/ModelingData/TKG3d/GeomProp/GeomProp.cxx deleted file mode 100644 index 84b58e7e9b..0000000000 --- a/src/ModelingData/TKG3d/GeomProp/GeomProp.cxx +++ /dev/null @@ -1,446 +0,0 @@ -// 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 - -#include - -//================================================================================================= - -GeomProp::TangentResult GeomProp::ComputeTangent(const gp_Vec& theD1, - const gp_Vec& theD2, - const gp_Vec& theD3, - const double theTol) -{ - const double aTol2 = theTol * theTol; - - // Try first derivative - if (theD1.SquareMagnitude() > aTol2) - { - return {gp_Dir(theD1), true}; - } - - // Try second derivative - if (theD2.SquareMagnitude() > aTol2) - { - return {gp_Dir(theD2), true}; - } - - // Try third derivative - if (theD3.SquareMagnitude() > aTol2) - { - return {gp_Dir(theD3), true}; - } - - return {{}, false}; -} - -//================================================================================================= - -GeomProp::TangentResult GeomProp::ComputeTangent(const gp_Vec& theD1, - const gp_Vec& theD2, - const gp_Vec& theD3, - const double theTol, - const gp_Pnt& thePntBefore, - const gp_Pnt& thePntAfter) -{ - const double aTol2 = theTol * theTol; - - // If D1 is non-null, use it directly (no sign ambiguity). - if (theD1.SquareMagnitude() > aTol2) - { - return {gp_Dir(theD1), true}; - } - - // D1 is null: find first non-null higher derivative. - gp_Vec aVec; - if (theD2.SquareMagnitude() > aTol2) - aVec = theD2; - else if (theD3.SquareMagnitude() > aTol2) - aVec = theD3; - else - return {{}, false}; - - // Correct sign of higher-order derivative using finite-difference direction. - const gp_Vec aFiniteDiff(thePntBefore, thePntAfter); - if (aVec.Dot(aFiniteDiff) < 0.0) - aVec.Reverse(); - - return {gp_Dir(aVec), true}; -} - -//================================================================================================= - -GeomProp::CurvatureResult GeomProp::ComputeCurvature(const gp_Vec& theD1, - const gp_Vec& theD2, - const double theTol) -{ - const double aTol2 = theTol * theTol; - const double aDD1 = theD1.SquareMagnitude(); - - // If first derivative is null, curvature is infinite (singular point). - if (aDD1 <= aTol2) - { - return {0.0, true, true}; - } - - const double aDD2 = theD2.SquareMagnitude(); - - // If second derivative is null, curvature is zero. - if (aDD2 <= aTol2) - { - return {0.0, true, false}; - } - - // Cross product magnitude squared: |D1 x D2|^2 - const gp_Vec aCross = theD1.Crossed(theD2); - const double aN = aCross.SquareMagnitude(); - - // If D1 and D2 are collinear, curvature is zero. - const double aT = aN / aDD1 / aDD2; - if (aT <= aTol2) - { - return {0.0, true, false}; - } - - // Curvature = |D1 x D2| / |D1|^3 - const double aCurvature = std::sqrt(aN) / aDD1 / std::sqrt(aDD1); - return {aCurvature, true, false}; -} - -//================================================================================================= - -GeomProp::NormalResult GeomProp::ComputeNormal(const gp_Vec& theD1, - const gp_Vec& theD2, - const double theTol) -{ - // First compute curvature to check if normal is defined. - const CurvatureResult aCurvRes = ComputeCurvature(theD1, theD2, theTol); - if (!aCurvRes.IsDefined || aCurvRes.IsInfinite || std::abs(aCurvRes.Value) <= theTol) - { - return {{}, false}; - } - - // Normal = D2 * (D1.D1) - D1 * (D1.D2) - // This is equivalent to (D1 x D2) x D1 using the vector triple product identity. - const gp_Vec aNorm = theD2 * theD1.Dot(theD1) - theD1 * theD1.Dot(theD2); - if (aNorm.SquareMagnitude() <= theTol * theTol) - { - return {{}, false}; - } - return {gp_Dir(aNorm), true}; -} - -//================================================================================================= - -GeomProp::CentreResult GeomProp::ComputeCentreOfCurvature(const gp_Pnt& thePnt, - const gp_Vec& theD1, - const gp_Vec& theD2, - const double theTol) -{ - const CurvatureResult aCurvRes = ComputeCurvature(theD1, theD2, theTol); - if (!aCurvRes.IsDefined || aCurvRes.IsInfinite || std::abs(aCurvRes.Value) <= theTol) - { - return {{}, false}; - } - - // Normal vector (unnormalized) = D2 * (D1.D1) - D1 * (D1.D2) - gp_Vec aNorm = theD2 * theD1.Dot(theD1) - theD1 * theD1.Dot(theD2); - if (aNorm.SquareMagnitude() <= theTol * theTol) - { - return {{}, false}; - } - aNorm.Normalize(); - aNorm.Divide(aCurvRes.Value); - - return {thePnt.Translated(aNorm), true}; -} - -//================================================================================================= - -GeomProp::SurfaceNormalResult GeomProp::ComputeSurfaceNormal(const gp_Vec& theD1U, - const gp_Vec& theD1V, - const double theTol) -{ - const gp_Vec aCross = theD1U.Crossed(theD1V); - if (aCross.SquareMagnitude() <= theTol * theTol) - { - return {{}, false}; - } - return {gp_Dir(aCross), true}; -} - -//================================================================================================= - -GeomProp::SurfaceCurvatureResult GeomProp::ComputeSurfaceCurvatures(const gp_Vec& theD1U, - const gp_Vec& theD1V, - const gp_Vec& theD2U, - const gp_Vec& theD2V, - const gp_Vec& theDUV, - const double theTol) -{ - // Compute surface normal. - const SurfaceNormalResult aNormRes = ComputeSurfaceNormal(theD1U, theD1V, theTol); - if (!aNormRes.IsDefined) - { - return {}; - } - - const gp_Vec aNormal(aNormRes.Direction); - - // First fundamental form coefficients. - const double aE = theD1U.Dot(theD1U); - const double aF = theD1U.Dot(theD1V); - const double aG = theD1V.Dot(theD1V); - - // Check that both tangent directions are non-degenerate. - // This matches the old LProp_SLProps guard against "pointed patches" - // where one tangent is degenerate, preventing division by zero below. - const double aTol2 = theTol * theTol; - if (aE <= aTol2 || aG <= aTol2) - { - return {}; - } - - // Second fundamental form coefficients. - const double aL = aNormal.Dot(theD2U); - const double aM = aNormal.Dot(theDUV); - const double aN_ = aNormal.Dot(theD2V); - - // Discriminant of first fundamental form. - const double aDet = aE * aG - aF * aF; - if (std::abs(aDet) <= aTol2) - { - return {}; - } - - // Compute principal curvatures and directions using the directional equation - // approach (matching the legacy LProp_SLProps algorithm). - // - // The principal directions satisfy the equation: - // A*t^2 + B*t + C = 0 - // where A = E*M - F*L, B = E*N - G*L, C = F*N - G*M, - // and t is the ratio defining the direction in parameter space. - const double aA = aE * aM - aF * aL; - const double aB = aE * aN_ - aG * aL; - const double aC = aF * aN_ - aG * aM; - - const double aMaxABC = std::max({std::abs(aA), std::abs(aB), std::abs(aC)}); - - SurfaceCurvatureResult aResult; - aResult.IsDefined = true; - - if (aMaxABC < RealEpsilon()) - { - // Umbilic point: both principal curvatures are equal. - const double aUmbilicCurv = (std::abs(aG) > theTol * theTol) ? aN_ / aG : 0.0; - aResult.MinCurvature = aUmbilicCurv; - aResult.MaxCurvature = aUmbilicCurv; - aResult.IsUmbilic = true; - if (theD1U.SquareMagnitude() > theTol * theTol) - { - aResult.MinDirection = gp_Dir(theD1U); - const gp_Vec aMaxDir = theD1U.Crossed(aNormal); - if (aMaxDir.SquareMagnitude() > theTol * theTol) - { - aResult.MaxDirection = gp_Dir(aMaxDir); - } - } - return aResult; - } - - // Lambda to handle umbilic (double root or degenerate) cases. - auto handleUmbilic = [&]() { - const double aUmbilicCurv = (std::abs(aG) > theTol * theTol) ? aN_ / aG : 0.0; - aResult.MinCurvature = aUmbilicCurv; - aResult.MaxCurvature = aUmbilicCurv; - aResult.IsUmbilic = true; - if (theD1U.SquareMagnitude() > theTol * theTol) - { - aResult.MinDirection = gp_Dir(theD1U); - const gp_Vec aMaxDir = theD1U.Crossed(aNormal); - if (aMaxDir.SquareMagnitude() > theTol * theTol) - { - aResult.MaxDirection = gp_Dir(aMaxDir); - } - } - return aResult; - }; - - double aCurv1, aCurv2; - gp_Vec aVecCurv1, aVecCurv2; - - // Normalize coefficients for numerical stability. - const double aNormA = aA / aMaxABC; - const double aNormB = aB / aMaxABC; - const double aNormC = aC / aMaxABC; - - if (std::abs(aNormA) > RealEpsilon()) - { - // Solve A*t^2 + B*t + C = 0; direction = t * D1U + D1V. - // Use error-bounded discriminant check matching math_DirectPolynomialRoots behavior: - // clamp discriminant to zero when within floating-point noise threshold. - const double aP = aNormB / aNormA; - const double aQ = aNormC / aNormA; - const double aEpsD = 3.0 * RealEpsilon() * (aP * aP + std::abs(4.0 * aQ)); - double aDisc = aP * aP - 4.0 * aQ; - if (std::abs(aDisc) <= aEpsD) - { - aDisc = 0.0; - } - if (aDisc < 0.0) - { - return handleUmbilic(); - } - if (aDisc == 0.0) - { - return handleUmbilic(); - } - const double aSqrtDisc = std::sqrt(aDisc); - // Use numerically stable root formula (same as math_DirectPolynomialRoots). - double aRoot1, aRoot2; - if (aP > 0.0) - { - aRoot1 = -(aP + aSqrtDisc) / 2.0; - } - else - { - aRoot1 = -(aP - aSqrtDisc) / 2.0; - } - aRoot2 = aQ / aRoot1; - const double aDenom1 = (aE * aRoot1 + 2.0 * aF) * aRoot1 + aG; - const double aDenom2 = (aE * aRoot2 + 2.0 * aF) * aRoot2 + aG; - if (std::abs(aDenom1) < RealEpsilon() || std::abs(aDenom2) < RealEpsilon()) - { - return handleUmbilic(); - } - aCurv1 = ((aL * aRoot1 + 2.0 * aM) * aRoot1 + aN_) / aDenom1; - aCurv2 = ((aL * aRoot2 + 2.0 * aM) * aRoot2 + aN_) / aDenom2; - aVecCurv1 = theD1U * aRoot1 + theD1V; - aVecCurv2 = theD1U * aRoot2 + theD1V; - } - else if (std::abs(aNormC) > RealEpsilon()) - { - // Solve C*t^2 + B*t + A = 0; direction = D1U + t * D1V. - const double aP = aNormB / aNormC; - const double aQ = aNormA / aNormC; - const double aEpsD = 3.0 * RealEpsilon() * (aP * aP + std::abs(4.0 * aQ)); - double aDisc = aP * aP - 4.0 * aQ; - if (std::abs(aDisc) <= aEpsD) - { - aDisc = 0.0; - } - if (aDisc < 0.0) - { - return handleUmbilic(); - } - if (aDisc == 0.0) - { - return handleUmbilic(); - } - const double aSqrtDisc = std::sqrt(aDisc); - double aRoot1, aRoot2; - if (aP > 0.0) - { - aRoot1 = -(aP + aSqrtDisc) / 2.0; - } - else - { - aRoot1 = -(aP - aSqrtDisc) / 2.0; - } - aRoot2 = aQ / aRoot1; - const double aDenom1 = (aG * aRoot1 + 2.0 * aF) * aRoot1 + aE; - const double aDenom2 = (aG * aRoot2 + 2.0 * aF) * aRoot2 + aE; - if (std::abs(aDenom1) < RealEpsilon() || std::abs(aDenom2) < RealEpsilon()) - { - return handleUmbilic(); - } - aCurv1 = ((aN_ * aRoot1 + 2.0 * aM) * aRoot1 + aL) / aDenom1; - aCurv2 = ((aN_ * aRoot2 + 2.0 * aM) * aRoot2 + aL) / aDenom2; - aVecCurv1 = theD1U + theD1V * aRoot1; - aVecCurv2 = theD1U + theD1V * aRoot2; - } - else - { - // Both A and C are near zero: principal directions align with D1U and D1V. - aCurv1 = aL / aE; - aCurv2 = aN_ / aG; - aVecCurv1 = theD1U; - aVecCurv2 = theD1V; - } - - // Sort so that min curvature is first. - if (aCurv1 < aCurv2) - { - aResult.MinCurvature = aCurv1; - aResult.MaxCurvature = aCurv2; - if (aVecCurv1.SquareMagnitude() > theTol * theTol) - aResult.MinDirection = gp_Dir(aVecCurv1); - if (aVecCurv2.SquareMagnitude() > theTol * theTol) - aResult.MaxDirection = gp_Dir(aVecCurv2); - } - else - { - aResult.MinCurvature = aCurv2; - aResult.MaxCurvature = aCurv1; - if (aVecCurv2.SquareMagnitude() > theTol * theTol) - aResult.MinDirection = gp_Dir(aVecCurv2); - if (aVecCurv1.SquareMagnitude() > theTol * theTol) - aResult.MaxDirection = gp_Dir(aVecCurv1); - } - aResult.IsUmbilic = false; - - return aResult; -} - -//================================================================================================= - -GeomProp::MeanGaussianResult GeomProp::ComputeMeanGaussian(const gp_Vec& theD1U, - const gp_Vec& theD1V, - const gp_Vec& theD2U, - const gp_Vec& theD2V, - const gp_Vec& theDUV, - const double theTol) -{ - // Compute surface normal. - const SurfaceNormalResult aNormRes = ComputeSurfaceNormal(theD1U, theD1V, theTol); - if (!aNormRes.IsDefined) - { - return {}; - } - - const gp_Vec aNormal(aNormRes.Direction); - - // First fundamental form coefficients. - const double aE = theD1U.Dot(theD1U); - const double aF = theD1U.Dot(theD1V); - const double aG = theD1V.Dot(theD1V); - - // Second fundamental form coefficients. - const double aL = aNormal.Dot(theD2U); - const double aM = aNormal.Dot(theDUV); - const double aN_ = aNormal.Dot(theD2V); - - // Discriminant of first fundamental form. - const double aDet = aE * aG - aF * aF; - if (std::abs(aDet) <= theTol * theTol) - { - return {}; - } - - MeanGaussianResult aResult; - aResult.IsDefined = true; - aResult.MeanCurvature = (aE * aN_ - 2.0 * aF * aM + aG * aL) / (2.0 * aDet); - aResult.GaussianCurvature = (aL * aN_ - aM * aM) / aDet; - return aResult; -} diff --git a/src/ModelingData/TKG3d/GeomProp/GeomProp.hxx b/src/ModelingData/TKG3d/GeomProp/GeomProp.hxx deleted file mode 100644 index 985fd9b4b2..0000000000 --- a/src/ModelingData/TKG3d/GeomProp/GeomProp.hxx +++ /dev/null @@ -1,331 +0,0 @@ -// 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. - -#ifndef _GeomProp_HeaderFile -#define _GeomProp_HeaderFile - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -//! @brief Namespace containing result structures and free functions for 3D curve -//! and surface differential property computation. -//! -//! Provides lightweight result structures with explicit validity flags instead of -//! exception-based APIs, and geometry-agnostic free functions that compute local -//! differential properties from derivative vectors. -namespace GeomProp -{ - -// ============================================================================ -// Domain structures -// ============================================================================ - -//! Parameter domain for a 3D curve (used for trimmed curves). -struct CurveDomain -{ - double First; //!< First parameter - double Last; //!< Last parameter -}; - -//! Parameter domain for a 3D surface (used for rectangular trimmed surfaces). -struct SurfaceDomain -{ - double FirstU; //!< First U parameter - double LastU; //!< Last U parameter - double FirstV; //!< First V parameter - double LastV; //!< Last V parameter -}; - -// ============================================================================ -// Curve result structures -// ============================================================================ - -//! Result of tangent direction computation. -struct TangentResult -{ - gp_Dir Direction; //!< Tangent direction (valid only when IsDefined is true) - bool IsDefined = false; //!< True if the tangent is well-defined -}; - -//! Result of curvature computation. -struct CurvatureResult -{ - double Value = 0.0; //!< Curvature value (valid only when IsDefined is true) - bool IsDefined = false; //!< True if curvature could be computed - bool IsInfinite = false; //!< True if first derivative is null (singular point) -}; - -//! Result of normal direction computation. -struct NormalResult -{ - gp_Dir Direction; //!< Normal direction (valid only when IsDefined is true) - bool IsDefined = false; //!< True if the normal is well-defined -}; - -//! Result of centre of curvature computation. -struct CentreResult -{ - gp_Pnt Centre; //!< Centre of curvature (valid only when IsDefined is true) - bool IsDefined = false; //!< True if the centre is well-defined -}; - -//! Type of a special curve point (curvature extremum or inflection). -enum class CIType -{ - Inflection, //!< Inflection point (curvature changes sign) - MinCurvature, //!< Local minimum of the radius of curvature (maximum of |curvature|) - MaxCurvature //!< Local maximum of the radius of curvature (minimum of |curvature|) -}; - -//! A special point on a curve with its parameter and type. -struct CurveSpecialPoint -{ - double Parameter = 0.0; //!< Curve parameter - CIType Type = CIType::Inflection; //!< Point type -}; - -//! Result of global curve analysis (curvature extrema and inflection points). -struct CurveAnalysis -{ - NCollection_DynamicArray Points; //!< Special points sorted by parameter - bool IsDone = false; //!< True if analysis completed -}; - -// ============================================================================ -// Surface result structures -// ============================================================================ - -//! Result of surface normal computation. -struct SurfaceNormalResult -{ - gp_Dir Direction; //!< Surface normal direction (valid only when IsDefined is true) - bool IsDefined = false; //!< True if the normal is well-defined -}; - -//! Result of surface principal curvature computation. -struct SurfaceCurvatureResult -{ - double MinCurvature = 0.0; //!< Minimum principal curvature (valid only when IsDefined is true) - double MaxCurvature = 0.0; //!< Maximum principal curvature (valid only when IsDefined is true) - gp_Dir MinDirection; //!< Direction of minimum curvature (valid only when IsDefined is true) - gp_Dir MaxDirection; //!< Direction of maximum curvature (valid only when IsDefined is true) - bool IsDefined = false; //!< True if curvatures could be computed - bool IsUmbilic = false; //!< True if the point is umbilic (all curvatures equal) -}; - -//! Result of mean and Gaussian curvature computation. -struct MeanGaussianResult -{ - double MeanCurvature = 0.0; //!< Mean curvature H = (k1 + k2) / 2 - double GaussianCurvature = 0.0; //!< Gaussian curvature K = k1 * k2 - bool IsDefined = false; //!< True if curvatures could be computed -}; - -// ============================================================================ -// Derivative caching -// ============================================================================ - -//! Derivative order for 3D curve property caching. -//! Values must match std::variant alternative indices in CurveCache::Data. -enum class CurveDerivOrder -{ - Undefined = 0, //!< No caching specified (monostate) - Value = 1, //!< Cache point only (gp_Pnt) - Tangent = 2, //!< Cache up to D1 (Geom_Curve::ResD1) - Curvature = 3, //!< Cache up to D2 (Geom_Curve::ResD2) - CurvatureDeriv = 4 //!< Cache up to D3 (Geom_Curve::ResD3) -}; - -//! Derivative order for 3D surface property caching. -//! Values must match std::variant alternative indices in SurfaceCache::Data. -enum class SurfaceDerivOrder -{ - Undefined = 0, //!< No caching specified (monostate) - Value = 1, //!< Cache point only (gp_Pnt) - Normal = 2, //!< Cache up to D1U + D1V (Geom_Surface::ResD1) - Curvature = 3 //!< Cache up to D2 (Geom_Surface::ResD2) -}; - -//! Cached 3D curve derivatives at a parameter value. -//! @note The variant alternative indices must match CurveDerivOrder enum values. -struct CurveCache -{ - double Param = std::numeric_limits::quiet_NaN(); - std::variant - Data; - - bool IsValid(double theParam) const { return Param == theParam; } - - CurveDerivOrder Order() const { return static_cast(Data.index()); } - - bool HasOrder(CurveDerivOrder theNeeded) const - { - return static_cast(Order()) >= static_cast(theNeeded); - } - - void Invalidate() - { - Param = std::numeric_limits::quiet_NaN(); - Data.emplace(); - } -}; - -//! Cached 3D surface derivatives at a (U, V) parameter pair. -//! @note The variant alternative indices must match SurfaceDerivOrder enum values. -struct SurfaceCache -{ - double ParamU = std::numeric_limits::quiet_NaN(); - double ParamV = std::numeric_limits::quiet_NaN(); - std::variant Data; - - bool IsValid(double theU, double theV) const { return ParamU == theU && ParamV == theV; } - - SurfaceDerivOrder Order() const { return static_cast(Data.index()); } - - bool HasOrder(SurfaceDerivOrder theNeeded) const - { - return static_cast(Order()) >= static_cast(theNeeded); - } - - void Invalidate() - { - ParamU = ParamV = std::numeric_limits::quiet_NaN(); - Data.emplace(); - } -}; - -// ============================================================================ -// Curve free functions -// ============================================================================ - -//! Compute tangent direction from derivative vectors. -//! Tries D1 first; if D1 magnitude^2 <= theTol^2, tries D2, then D3. -//! @note When D1 is null and a higher-order derivative is used, the sign of -//! the direction may be wrong. Use the overload with finite-difference points -//! for sign correction when the curve parameterization is available. -//! @param[in] theD1 first derivative vector -//! @param[in] theD2 second derivative vector -//! @param[in] theD3 third derivative vector -//! @param[in] theTol linear tolerance for zero-vector detection -//! @return tangent result with validity flag -Standard_EXPORT TangentResult ComputeTangent(const gp_Vec& theD1, - const gp_Vec& theD2, - const gp_Vec& theD3, - double theTol); - -//! Compute tangent direction with sign correction for higher-order derivatives. -//! Same as ComputeTangent, but when D1 is null and a higher-order derivative is -//! used, corrects the sign by comparing with a finite-difference direction vector. -//! @param[in] theD1 first derivative vector -//! @param[in] theD2 second derivative vector -//! @param[in] theD3 third derivative vector -//! @param[in] theTol linear tolerance for zero-vector detection -//! @param[in] thePntBefore point on the curve before the evaluation point -//! @param[in] thePntAfter point on the curve after the evaluation point -//! @return tangent result with validity flag and corrected sign -Standard_EXPORT TangentResult ComputeTangent(const gp_Vec& theD1, - const gp_Vec& theD2, - const gp_Vec& theD3, - double theTol, - const gp_Pnt& thePntBefore, - const gp_Pnt& thePntAfter); - -//! Compute curvature from first and second derivative vectors. -//! Curvature = |D1 x D2| / |D1|^3 -//! @param[in] theD1 first derivative vector -//! @param[in] theD2 second derivative vector -//! @param[in] theTol linear tolerance for zero-vector detection -//! @return curvature result with validity and infinity flags -Standard_EXPORT CurvatureResult ComputeCurvature(const gp_Vec& theD1, - const gp_Vec& theD2, - double theTol); - -//! Compute normal direction from first and second derivative vectors. -//! Normal = D1 x (D2 x D1) (normalized), perpendicular to tangent pointing toward center. -//! @param[in] theD1 first derivative vector -//! @param[in] theD2 second derivative vector -//! @param[in] theTol linear tolerance for zero-vector detection -//! @return normal result with validity flag -Standard_EXPORT NormalResult ComputeNormal(const gp_Vec& theD1, const gp_Vec& theD2, double theTol); - -//! Compute centre of curvature from point and derivative vectors. -//! Centre = Point + Normal / Curvature -//! @param[in] thePnt point on the curve -//! @param[in] theD1 first derivative vector -//! @param[in] theD2 second derivative vector -//! @param[in] theTol linear tolerance for zero-vector detection -//! @return centre result with validity flag -Standard_EXPORT CentreResult ComputeCentreOfCurvature(const gp_Pnt& thePnt, - const gp_Vec& theD1, - const gp_Vec& theD2, - double theTol); - -// ============================================================================ -// Surface free functions -// ============================================================================ - -//! Compute surface normal from first partial derivatives. -//! Normal = D1U x D1V (normalized). -//! @param[in] theD1U first partial derivative in U direction -//! @param[in] theD1V first partial derivative in V direction -//! @param[in] theTol linear tolerance for zero-vector detection -//! @return surface normal result with validity flag -Standard_EXPORT SurfaceNormalResult ComputeSurfaceNormal(const gp_Vec& theD1U, - const gp_Vec& theD1V, - double theTol); - -//! Compute principal curvatures and directions from surface derivatives. -//! Uses first and second fundamental forms to compute principal curvatures. -//! @param[in] theD1U first partial derivative in U direction -//! @param[in] theD1V first partial derivative in V direction -//! @param[in] theD2U second partial derivative in U direction -//! @param[in] theD2V second partial derivative in V direction -//! @param[in] theDUV mixed partial derivative -//! @param[in] theTol linear tolerance for zero-vector detection -//! @return surface curvature result with principal curvatures and directions -Standard_EXPORT SurfaceCurvatureResult ComputeSurfaceCurvatures(const gp_Vec& theD1U, - const gp_Vec& theD1V, - const gp_Vec& theD2U, - const gp_Vec& theD2V, - const gp_Vec& theDUV, - double theTol); - -//! Compute mean and Gaussian curvatures from surface derivatives. -//! Mean curvature H = (EN - 2FM + GL) / (2(EG - F^2)) -//! Gaussian curvature K = (LN - M^2) / (EG - F^2) -//! @param[in] theD1U first partial derivative in U direction -//! @param[in] theD1V first partial derivative in V direction -//! @param[in] theD2U second partial derivative in U direction -//! @param[in] theD2V second partial derivative in V direction -//! @param[in] theDUV mixed partial derivative -//! @param[in] theTol linear tolerance for zero-vector detection -//! @return mean and Gaussian curvature result -Standard_EXPORT MeanGaussianResult ComputeMeanGaussian(const gp_Vec& theD1U, - const gp_Vec& theD1V, - const gp_Vec& theD2U, - const gp_Vec& theD2V, - const gp_Vec& theDUV, - double theTol); - -} // namespace GeomProp - -#endif // _GeomProp_HeaderFile diff --git a/src/ModelingData/TKG3d/GeomProp/GeomProp_BSplineCurve.cxx b/src/ModelingData/TKG3d/GeomProp/GeomProp_BSplineCurve.cxx deleted file mode 100644 index 1b68319b23..0000000000 --- a/src/ModelingData/TKG3d/GeomProp/GeomProp_BSplineCurve.cxx +++ /dev/null @@ -1,125 +0,0 @@ -// 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 -#include - -#include - -//================================================================================================= - -GeomProp::TangentResult GeomProp_BSplineCurve::Tangent(const double theParam, - const double theTol) const -{ - if (!myCurve.IsNull()) - { - return GeomProp_CurveAnalysisTools::EvaluateTangentCached(myCurve.get(), - theParam, - theTol, - myRequestedOrder, - myCache); - } - return GeomProp_CurveAnalysisTools::EvaluateTangentCached(myAdaptor, - theParam, - theTol, - myRequestedOrder, - myCache); -} - -//================================================================================================= - -GeomProp::CurvatureResult GeomProp_BSplineCurve::Curvature(const double theParam, - const double theTol) const -{ - if (!myCurve.IsNull()) - { - return GeomProp_CurveAnalysisTools::EvaluateCurvatureCached(myCurve.get(), - theParam, - theTol, - myRequestedOrder, - myCache); - } - return GeomProp_CurveAnalysisTools::EvaluateCurvatureCached(myAdaptor, - theParam, - theTol, - myRequestedOrder, - myCache); -} - -//================================================================================================= - -GeomProp::NormalResult GeomProp_BSplineCurve::Normal(const double theParam, - const double theTol) const -{ - if (!myCurve.IsNull()) - { - return GeomProp_CurveAnalysisTools::EvaluateNormalCached(myCurve.get(), - theParam, - theTol, - myRequestedOrder, - myCache); - } - return GeomProp_CurveAnalysisTools::EvaluateNormalCached(myAdaptor, - theParam, - theTol, - myRequestedOrder, - myCache); -} - -//================================================================================================= - -GeomProp::CentreResult GeomProp_BSplineCurve::CentreOfCurvature(const double theParam, - const double theTol) const -{ - if (!myCurve.IsNull()) - { - return GeomProp_CurveAnalysisTools::EvaluateCentreOfCurvatureCached(myCurve.get(), - theParam, - theTol, - myRequestedOrder, - myCache); - } - return GeomProp_CurveAnalysisTools::EvaluateCentreOfCurvatureCached(myAdaptor, - theParam, - theTol, - myRequestedOrder, - myCache); -} - -//================================================================================================= - -GeomProp::CurveAnalysis GeomProp_BSplineCurve::FindCurvatureExtrema() const -{ - if (!myCurve.IsNull()) - { - const double aFirst = myDomain.has_value() ? myDomain->First : myCurve->FirstParameter(); - const double aLast = myDomain.has_value() ? myDomain->Last : myCurve->LastParameter(); - GeomAdaptor_Curve anAdaptor(myCurve, aFirst, aLast); - return GeomProp_CurveAnalysisTools::FindCurvatureExtremaBySpans(&anAdaptor, GeomAbs_C3); - } - return GeomProp_CurveAnalysisTools::FindCurvatureExtremaBySpans(myAdaptor, GeomAbs_C3); -} - -//================================================================================================= - -GeomProp::CurveAnalysis GeomProp_BSplineCurve::FindInflections() const -{ - if (!myCurve.IsNull()) - { - const double aFirst = myDomain.has_value() ? myDomain->First : myCurve->FirstParameter(); - const double aLast = myDomain.has_value() ? myDomain->Last : myCurve->LastParameter(); - GeomAdaptor_Curve anAdaptor(myCurve, aFirst, aLast); - return GeomProp_CurveAnalysisTools::FindInflectionsBySpans(&anAdaptor, GeomAbs_C3); - } - return GeomProp_CurveAnalysisTools::FindInflectionsBySpans(myAdaptor, GeomAbs_C3); -} diff --git a/src/ModelingData/TKG3d/GeomProp/GeomProp_BSplineCurve.hxx b/src/ModelingData/TKG3d/GeomProp/GeomProp_BSplineCurve.hxx deleted file mode 100644 index 1e390f1412..0000000000 --- a/src/ModelingData/TKG3d/GeomProp/GeomProp_BSplineCurve.hxx +++ /dev/null @@ -1,107 +0,0 @@ -// 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. - -#ifndef _GeomProp_BSplineCurve_HeaderFile -#define _GeomProp_BSplineCurve_HeaderFile - -#include -#include -#include -#include -#include - -#include - -//! @brief Local differential properties for a 3D B-spline curve. -//! -//! Uses numeric root-finding for curvature extrema and inflection points. -//! For B-splines with continuity less than C3, the parameter range is subdivided -//! into C3 intervals for more robust root-finding. -//! -//! Can be constructed from either a GeomAdaptor_Curve pointer or a occ::handle. -//! When constructed from a handle, no adaptor is created; for complex methods -//! (FindCurvatureExtrema, FindInflections) a stack-local adaptor is created on demand. -class GeomProp_BSplineCurve -{ -public: - DEFINE_STANDARD_ALLOC - - //! Constructor with adaptor pointer (non-owning). - //! @param theAdaptor the 3D curve adaptor (must wrap a B-spline curve, must not be null) - GeomProp_BSplineCurve(const GeomAdaptor_Curve* theAdaptor, - GeomProp::CurveDerivOrder theOrder = GeomProp::CurveDerivOrder::Curvature) - : myAdaptor(theAdaptor), - myRequestedOrder(theOrder) - { - } - - //! Constructor from geometry handle. - //! @param theCurve the 3D B-spline curve geometry - //! @param theDomain optional parameter domain (for trimmed curves) - GeomProp_BSplineCurve(const occ::handle& theCurve, - const std::optional& theDomain = std::nullopt, - GeomProp::CurveDerivOrder theOrder = GeomProp::CurveDerivOrder::Curvature) - : myAdaptor(nullptr), - myRequestedOrder(theOrder), - myCurve(theCurve), - myDomain(theDomain) - { - } - - //! Non-copyable and non-movable. - GeomProp_BSplineCurve(const GeomProp_BSplineCurve&) = delete; - GeomProp_BSplineCurve& operator=(const GeomProp_BSplineCurve&) = delete; - GeomProp_BSplineCurve(GeomProp_BSplineCurve&&) = delete; - GeomProp_BSplineCurve& operator=(GeomProp_BSplineCurve&&) = delete; - - //! Sets the derivative caching order. - void SetDerivOrder(GeomProp::CurveDerivOrder theOrder) { myRequestedOrder = theOrder; } - - //! Returns the derivative caching order. - GeomProp::CurveDerivOrder DerivOrder() const { return myRequestedOrder; } - - //! Returns the adaptor pointer (nullptr when constructed from handle). - const GeomAdaptor_Curve* Adaptor() const { return myAdaptor; } - - //! Returns pointer to underlying geometry, or nullptr if constructed from adaptor. - const Geom_Curve* Geometry() const { return myCurve.get(); } - - //! Compute tangent at given parameter. - Standard_EXPORT GeomProp::TangentResult Tangent(double theParam, double theTol) const; - - //! Compute curvature at given parameter. - Standard_EXPORT GeomProp::CurvatureResult Curvature(double theParam, double theTol) const; - - //! Compute normal at given parameter. - Standard_EXPORT GeomProp::NormalResult Normal(double theParam, double theTol) const; - - //! Compute centre of curvature at given parameter. - Standard_EXPORT GeomProp::CentreResult CentreOfCurvature(double theParam, double theTol) const; - - //! Find curvature extrema using numeric root-finding. - //! For non-C3 B-splines, subdivides into C3 intervals. - Standard_EXPORT GeomProp::CurveAnalysis FindCurvatureExtrema() const; - - //! Find inflection points using numeric root-finding. - //! For non-C3 B-splines, subdivides into C3 intervals. - Standard_EXPORT GeomProp::CurveAnalysis FindInflections() const; - -private: - const GeomAdaptor_Curve* myAdaptor; - GeomProp::CurveDerivOrder myRequestedOrder; - mutable GeomProp::CurveCache myCache; - occ::handle myCurve; //!< Geometry handle (handle path) - std::optional myDomain; //!< Optional parameter domain -}; - -#endif // _GeomProp_BSplineCurve_HeaderFile diff --git a/src/ModelingData/TKG3d/GeomProp/GeomProp_BSplineSurface.cxx b/src/ModelingData/TKG3d/GeomProp/GeomProp_BSplineSurface.cxx deleted file mode 100644 index f32c647b94..0000000000 --- a/src/ModelingData/TKG3d/GeomProp/GeomProp_BSplineSurface.cxx +++ /dev/null @@ -1,84 +0,0 @@ -// 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 -#include - -//================================================================================================= - -GeomProp::SurfaceNormalResult GeomProp_BSplineSurface::Normal(const double theU, - const double theV, - const double theTol) const -{ - if (!mySurface.IsNull()) - { - return GeomProp_SurfaceAnalysisTools::EvaluateNormalCached(mySurface.get(), - theU, - theV, - theTol, - myRequestedOrder, - myCache); - } - return GeomProp_SurfaceAnalysisTools::EvaluateNormalCached(myAdaptor, - theU, - theV, - theTol, - myRequestedOrder, - myCache); -} - -//================================================================================================= - -GeomProp::SurfaceCurvatureResult GeomProp_BSplineSurface::Curvatures(const double theU, - const double theV, - const double theTol) const -{ - if (!mySurface.IsNull()) - { - return GeomProp_SurfaceAnalysisTools::EvaluateCurvaturesCached(mySurface.get(), - theU, - theV, - theTol, - myRequestedOrder, - myCache); - } - return GeomProp_SurfaceAnalysisTools::EvaluateCurvaturesCached(myAdaptor, - theU, - theV, - theTol, - myRequestedOrder, - myCache); -} - -//================================================================================================= - -GeomProp::MeanGaussianResult GeomProp_BSplineSurface::MeanGaussian(const double theU, - const double theV, - const double theTol) const -{ - if (!mySurface.IsNull()) - { - return GeomProp_SurfaceAnalysisTools::EvaluateMeanGaussianCached(mySurface.get(), - theU, - theV, - theTol, - myRequestedOrder, - myCache); - } - return GeomProp_SurfaceAnalysisTools::EvaluateMeanGaussianCached(myAdaptor, - theU, - theV, - theTol, - myRequestedOrder, - myCache); -} diff --git a/src/ModelingData/TKG3d/GeomProp/GeomProp_BSplineSurface.hxx b/src/ModelingData/TKG3d/GeomProp/GeomProp_BSplineSurface.hxx deleted file mode 100644 index 6be5fb89e7..0000000000 --- a/src/ModelingData/TKG3d/GeomProp/GeomProp_BSplineSurface.hxx +++ /dev/null @@ -1,100 +0,0 @@ -// 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. - -#ifndef _GeomProp_BSplineSurface_HeaderFile -#define _GeomProp_BSplineSurface_HeaderFile - -#include -#include -#include -#include - -#include - -//! @brief Local differential properties for a B-spline surface. -//! -//! Uses numeric evaluation from surface derivatives. -//! -//! Can be constructed from either a GeomAdaptor_Surface pointer or a occ::handle. -//! When constructed from a handle, no adaptor is created. -class GeomProp_BSplineSurface -{ -public: - DEFINE_STANDARD_ALLOC - - //! Constructor with adaptor pointer (non-owning). - //! @param theAdaptor the surface adaptor (must not be null) - GeomProp_BSplineSurface( - const GeomAdaptor_Surface* theAdaptor, - GeomProp::SurfaceDerivOrder theOrder = GeomProp::SurfaceDerivOrder::Curvature) - : myAdaptor(theAdaptor), - myRequestedOrder(theOrder) - { - } - - //! Constructor from geometry handle. - //! @param theSurface the 3D B-spline surface geometry - //! @param theDomain optional parameter domain (for trimmed surfaces) - GeomProp_BSplineSurface( - const occ::handle& theSurface, - const std::optional& theDomain = std::nullopt, - GeomProp::SurfaceDerivOrder theOrder = GeomProp::SurfaceDerivOrder::Curvature) - : myAdaptor(nullptr), - myRequestedOrder(theOrder), - mySurface(theSurface), - myDomain(theDomain) - { - } - - //! Non-copyable and non-movable. - GeomProp_BSplineSurface(const GeomProp_BSplineSurface&) = delete; - GeomProp_BSplineSurface& operator=(const GeomProp_BSplineSurface&) = delete; - GeomProp_BSplineSurface(GeomProp_BSplineSurface&&) = delete; - GeomProp_BSplineSurface& operator=(GeomProp_BSplineSurface&&) = delete; - - //! Sets the derivative caching order. - void SetDerivOrder(GeomProp::SurfaceDerivOrder theOrder) { myRequestedOrder = theOrder; } - - //! Returns the derivative caching order. - GeomProp::SurfaceDerivOrder DerivOrder() const { return myRequestedOrder; } - - //! Returns the adaptor pointer (nullptr when constructed from handle). - const GeomAdaptor_Surface* Adaptor() const { return myAdaptor; } - - //! Returns pointer to underlying geometry, or nullptr if constructed from adaptor. - const Geom_Surface* Geometry() const { return mySurface.get(); } - - //! Compute surface normal at given parameter. - Standard_EXPORT GeomProp::SurfaceNormalResult Normal(double theU, - double theV, - double theTol) const; - - //! Compute principal curvatures at given parameter. - Standard_EXPORT GeomProp::SurfaceCurvatureResult Curvatures(double theU, - double theV, - double theTol) const; - - //! Compute mean and Gaussian curvatures at given parameter. - Standard_EXPORT GeomProp::MeanGaussianResult MeanGaussian(double theU, - double theV, - double theTol) const; - -private: - const GeomAdaptor_Surface* myAdaptor; - GeomProp::SurfaceDerivOrder myRequestedOrder; - mutable GeomProp::SurfaceCache myCache; - occ::handle mySurface; //!< Geometry handle (handle path) - std::optional myDomain; //!< Optional parameter domain -}; - -#endif // _GeomProp_BSplineSurface_HeaderFile diff --git a/src/ModelingData/TKG3d/GeomProp/GeomProp_BezierCurve.cxx b/src/ModelingData/TKG3d/GeomProp/GeomProp_BezierCurve.cxx deleted file mode 100644 index 66ac4b49c4..0000000000 --- a/src/ModelingData/TKG3d/GeomProp/GeomProp_BezierCurve.cxx +++ /dev/null @@ -1,124 +0,0 @@ -// 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 -#include - -//================================================================================================= - -GeomProp::TangentResult GeomProp_BezierCurve::Tangent(const double theParam, - const double theTol) const -{ - if (!myCurve.IsNull()) - { - return GeomProp_CurveAnalysisTools::EvaluateTangentCached(myCurve.get(), - theParam, - theTol, - myRequestedOrder, - myCache); - } - return GeomProp_CurveAnalysisTools::EvaluateTangentCached(myAdaptor, - theParam, - theTol, - myRequestedOrder, - myCache); -} - -//================================================================================================= - -GeomProp::CurvatureResult GeomProp_BezierCurve::Curvature(const double theParam, - const double theTol) const -{ - if (!myCurve.IsNull()) - { - return GeomProp_CurveAnalysisTools::EvaluateCurvatureCached(myCurve.get(), - theParam, - theTol, - myRequestedOrder, - myCache); - } - return GeomProp_CurveAnalysisTools::EvaluateCurvatureCached(myAdaptor, - theParam, - theTol, - myRequestedOrder, - myCache); -} - -//================================================================================================= - -GeomProp::NormalResult GeomProp_BezierCurve::Normal(const double theParam, - const double theTol) const -{ - if (!myCurve.IsNull()) - { - return GeomProp_CurveAnalysisTools::EvaluateNormalCached(myCurve.get(), - theParam, - theTol, - myRequestedOrder, - myCache); - } - return GeomProp_CurveAnalysisTools::EvaluateNormalCached(myAdaptor, - theParam, - theTol, - myRequestedOrder, - myCache); -} - -//================================================================================================= - -GeomProp::CentreResult GeomProp_BezierCurve::CentreOfCurvature(const double theParam, - const double theTol) const -{ - if (!myCurve.IsNull()) - { - return GeomProp_CurveAnalysisTools::EvaluateCentreOfCurvatureCached(myCurve.get(), - theParam, - theTol, - myRequestedOrder, - myCache); - } - return GeomProp_CurveAnalysisTools::EvaluateCentreOfCurvatureCached(myAdaptor, - theParam, - theTol, - myRequestedOrder, - myCache); -} - -//================================================================================================= - -GeomProp::CurveAnalysis GeomProp_BezierCurve::FindCurvatureExtrema() const -{ - if (!myCurve.IsNull()) - { - // Create a stack-local adaptor for the span-based numeric search. - const double aFirst = myDomain.has_value() ? myDomain->First : myCurve->FirstParameter(); - const double aLast = myDomain.has_value() ? myDomain->Last : myCurve->LastParameter(); - GeomAdaptor_Curve anAdaptor(myCurve, aFirst, aLast); - return GeomProp_CurveAnalysisTools::FindCurvatureExtrema(&anAdaptor); - } - return GeomProp_CurveAnalysisTools::FindCurvatureExtrema(myAdaptor); -} - -//================================================================================================= - -GeomProp::CurveAnalysis GeomProp_BezierCurve::FindInflections() const -{ - if (!myCurve.IsNull()) - { - const double aFirst = myDomain.has_value() ? myDomain->First : myCurve->FirstParameter(); - const double aLast = myDomain.has_value() ? myDomain->Last : myCurve->LastParameter(); - GeomAdaptor_Curve anAdaptor(myCurve, aFirst, aLast); - return GeomProp_CurveAnalysisTools::FindInflections(&anAdaptor); - } - return GeomProp_CurveAnalysisTools::FindInflections(myAdaptor); -} diff --git a/src/ModelingData/TKG3d/GeomProp/GeomProp_BezierCurve.hxx b/src/ModelingData/TKG3d/GeomProp/GeomProp_BezierCurve.hxx deleted file mode 100644 index d41d03d1be..0000000000 --- a/src/ModelingData/TKG3d/GeomProp/GeomProp_BezierCurve.hxx +++ /dev/null @@ -1,103 +0,0 @@ -// 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. - -#ifndef _GeomProp_BezierCurve_HeaderFile -#define _GeomProp_BezierCurve_HeaderFile - -#include -#include -#include -#include -#include - -#include - -//! @brief Local differential properties for a 3D Bezier curve. -//! -//! Uses numeric root-finding for curvature extrema and inflection points. -//! -//! Can be constructed from either a GeomAdaptor_Curve pointer or a occ::handle. -//! When constructed from a handle, no adaptor is created; for complex methods -//! (FindCurvatureExtrema, FindInflections) a stack-local adaptor is created on demand. -class GeomProp_BezierCurve -{ -public: - DEFINE_STANDARD_ALLOC - - //! Constructor with adaptor pointer (non-owning). - //! @param theAdaptor the 3D curve adaptor (must wrap a Bezier curve, must not be null) - GeomProp_BezierCurve(const GeomAdaptor_Curve* theAdaptor, - GeomProp::CurveDerivOrder theOrder = GeomProp::CurveDerivOrder::Curvature) - : myAdaptor(theAdaptor), - myRequestedOrder(theOrder) - { - } - - //! Constructor from geometry handle. - //! @param theCurve the 3D Bezier curve geometry - //! @param theDomain optional parameter domain (for trimmed curves) - GeomProp_BezierCurve(const occ::handle& theCurve, - const std::optional& theDomain = std::nullopt, - GeomProp::CurveDerivOrder theOrder = GeomProp::CurveDerivOrder::Curvature) - : myAdaptor(nullptr), - myRequestedOrder(theOrder), - myCurve(theCurve), - myDomain(theDomain) - { - } - - //! Non-copyable and non-movable. - GeomProp_BezierCurve(const GeomProp_BezierCurve&) = delete; - GeomProp_BezierCurve& operator=(const GeomProp_BezierCurve&) = delete; - GeomProp_BezierCurve(GeomProp_BezierCurve&&) = delete; - GeomProp_BezierCurve& operator=(GeomProp_BezierCurve&&) = delete; - - //! Sets the derivative caching order. - void SetDerivOrder(GeomProp::CurveDerivOrder theOrder) { myRequestedOrder = theOrder; } - - //! Returns the derivative caching order. - GeomProp::CurveDerivOrder DerivOrder() const { return myRequestedOrder; } - - //! Returns the adaptor pointer (nullptr when constructed from handle). - const GeomAdaptor_Curve* Adaptor() const { return myAdaptor; } - - //! Returns pointer to underlying geometry, or nullptr if constructed from adaptor. - const Geom_Curve* Geometry() const { return myCurve.get(); } - - //! Compute tangent at given parameter. - Standard_EXPORT GeomProp::TangentResult Tangent(double theParam, double theTol) const; - - //! Compute curvature at given parameter. - Standard_EXPORT GeomProp::CurvatureResult Curvature(double theParam, double theTol) const; - - //! Compute normal at given parameter. - Standard_EXPORT GeomProp::NormalResult Normal(double theParam, double theTol) const; - - //! Compute centre of curvature at given parameter. - Standard_EXPORT GeomProp::CentreResult CentreOfCurvature(double theParam, double theTol) const; - - //! Find curvature extrema using numeric root-finding. - Standard_EXPORT GeomProp::CurveAnalysis FindCurvatureExtrema() const; - - //! Find inflection points using numeric root-finding. - Standard_EXPORT GeomProp::CurveAnalysis FindInflections() const; - -private: - const GeomAdaptor_Curve* myAdaptor; - GeomProp::CurveDerivOrder myRequestedOrder; - mutable GeomProp::CurveCache myCache; - occ::handle myCurve; //!< Geometry handle (handle path) - std::optional myDomain; //!< Optional parameter domain -}; - -#endif // _GeomProp_BezierCurve_HeaderFile diff --git a/src/ModelingData/TKG3d/GeomProp/GeomProp_BezierSurface.cxx b/src/ModelingData/TKG3d/GeomProp/GeomProp_BezierSurface.cxx deleted file mode 100644 index 0402d8876b..0000000000 --- a/src/ModelingData/TKG3d/GeomProp/GeomProp_BezierSurface.cxx +++ /dev/null @@ -1,84 +0,0 @@ -// 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 -#include - -//================================================================================================= - -GeomProp::SurfaceNormalResult GeomProp_BezierSurface::Normal(const double theU, - const double theV, - const double theTol) const -{ - if (!mySurface.IsNull()) - { - return GeomProp_SurfaceAnalysisTools::EvaluateNormalCached(mySurface.get(), - theU, - theV, - theTol, - myRequestedOrder, - myCache); - } - return GeomProp_SurfaceAnalysisTools::EvaluateNormalCached(myAdaptor, - theU, - theV, - theTol, - myRequestedOrder, - myCache); -} - -//================================================================================================= - -GeomProp::SurfaceCurvatureResult GeomProp_BezierSurface::Curvatures(const double theU, - const double theV, - const double theTol) const -{ - if (!mySurface.IsNull()) - { - return GeomProp_SurfaceAnalysisTools::EvaluateCurvaturesCached(mySurface.get(), - theU, - theV, - theTol, - myRequestedOrder, - myCache); - } - return GeomProp_SurfaceAnalysisTools::EvaluateCurvaturesCached(myAdaptor, - theU, - theV, - theTol, - myRequestedOrder, - myCache); -} - -//================================================================================================= - -GeomProp::MeanGaussianResult GeomProp_BezierSurface::MeanGaussian(const double theU, - const double theV, - const double theTol) const -{ - if (!mySurface.IsNull()) - { - return GeomProp_SurfaceAnalysisTools::EvaluateMeanGaussianCached(mySurface.get(), - theU, - theV, - theTol, - myRequestedOrder, - myCache); - } - return GeomProp_SurfaceAnalysisTools::EvaluateMeanGaussianCached(myAdaptor, - theU, - theV, - theTol, - myRequestedOrder, - myCache); -} diff --git a/src/ModelingData/TKG3d/GeomProp/GeomProp_BezierSurface.hxx b/src/ModelingData/TKG3d/GeomProp/GeomProp_BezierSurface.hxx deleted file mode 100644 index 42967923c1..0000000000 --- a/src/ModelingData/TKG3d/GeomProp/GeomProp_BezierSurface.hxx +++ /dev/null @@ -1,100 +0,0 @@ -// 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. - -#ifndef _GeomProp_BezierSurface_HeaderFile -#define _GeomProp_BezierSurface_HeaderFile - -#include -#include -#include -#include - -#include - -//! @brief Local differential properties for a Bezier surface. -//! -//! Uses numeric evaluation from surface derivatives. -//! -//! Can be constructed from either a GeomAdaptor_Surface pointer or a occ::handle. -//! When constructed from a handle, no adaptor is created. -class GeomProp_BezierSurface -{ -public: - DEFINE_STANDARD_ALLOC - - //! Constructor with adaptor pointer (non-owning). - //! @param theAdaptor the surface adaptor (must not be null) - GeomProp_BezierSurface( - const GeomAdaptor_Surface* theAdaptor, - GeomProp::SurfaceDerivOrder theOrder = GeomProp::SurfaceDerivOrder::Curvature) - : myAdaptor(theAdaptor), - myRequestedOrder(theOrder) - { - } - - //! Constructor from geometry handle. - //! @param theSurface the 3D Bezier surface geometry - //! @param theDomain optional parameter domain (for trimmed surfaces) - GeomProp_BezierSurface( - const occ::handle& theSurface, - const std::optional& theDomain = std::nullopt, - GeomProp::SurfaceDerivOrder theOrder = GeomProp::SurfaceDerivOrder::Curvature) - : myAdaptor(nullptr), - myRequestedOrder(theOrder), - mySurface(theSurface), - myDomain(theDomain) - { - } - - //! Non-copyable and non-movable. - GeomProp_BezierSurface(const GeomProp_BezierSurface&) = delete; - GeomProp_BezierSurface& operator=(const GeomProp_BezierSurface&) = delete; - GeomProp_BezierSurface(GeomProp_BezierSurface&&) = delete; - GeomProp_BezierSurface& operator=(GeomProp_BezierSurface&&) = delete; - - //! Sets the derivative caching order. - void SetDerivOrder(GeomProp::SurfaceDerivOrder theOrder) { myRequestedOrder = theOrder; } - - //! Returns the derivative caching order. - GeomProp::SurfaceDerivOrder DerivOrder() const { return myRequestedOrder; } - - //! Returns the adaptor pointer (nullptr when constructed from handle). - const GeomAdaptor_Surface* Adaptor() const { return myAdaptor; } - - //! Returns pointer to underlying geometry, or nullptr if constructed from adaptor. - const Geom_Surface* Geometry() const { return mySurface.get(); } - - //! Compute surface normal at given parameter. - Standard_EXPORT GeomProp::SurfaceNormalResult Normal(double theU, - double theV, - double theTol) const; - - //! Compute principal curvatures at given parameter. - Standard_EXPORT GeomProp::SurfaceCurvatureResult Curvatures(double theU, - double theV, - double theTol) const; - - //! Compute mean and Gaussian curvatures at given parameter. - Standard_EXPORT GeomProp::MeanGaussianResult MeanGaussian(double theU, - double theV, - double theTol) const; - -private: - const GeomAdaptor_Surface* myAdaptor; - GeomProp::SurfaceDerivOrder myRequestedOrder; - mutable GeomProp::SurfaceCache myCache; - occ::handle mySurface; //!< Geometry handle (handle path) - std::optional myDomain; //!< Optional parameter domain -}; - -#endif // _GeomProp_BezierSurface_HeaderFile diff --git a/src/ModelingData/TKG3d/GeomProp/GeomProp_Circle.hxx b/src/ModelingData/TKG3d/GeomProp/GeomProp_Circle.hxx deleted file mode 100644 index 49dff0427f..0000000000 --- a/src/ModelingData/TKG3d/GeomProp/GeomProp_Circle.hxx +++ /dev/null @@ -1,164 +0,0 @@ -// 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. - -#ifndef _GeomProp_Circle_HeaderFile -#define _GeomProp_Circle_HeaderFile - -#include -#include -#include -#include - -#include - -//! @brief Local differential properties for a 3D circle. -//! -//! A circle has constant curvature = 1/R, well-defined tangent and normal -//! at every point, and no curvature extrema or inflection points. -//! -//! Can be constructed from either a GeomAdaptor_Curve pointer or a occ::handle. -//! When constructed from a handle, no adaptor is created. -class GeomProp_Circle -{ -public: - DEFINE_STANDARD_ALLOC - - //! Constructor with adaptor pointer (non-owning). - //! @param theAdaptor the 3D curve adaptor (must wrap a circle, must not be null) - GeomProp_Circle(const GeomAdaptor_Curve* theAdaptor, - GeomProp::CurveDerivOrder theOrder = GeomProp::CurveDerivOrder::Undefined) - : myAdaptor(theAdaptor), - myRadius(theAdaptor->Circle().Radius()), - myCenter(theAdaptor->Circle().Location()) - { - (void)theOrder; - } - - //! Constructor from geometry handle. - //! @param theCurve the 3D circle geometry (must be a Geom_Circle or downcastable to it) - //! @param theDomain optional parameter domain (unused for circle) - GeomProp_Circle(const occ::handle& theCurve, - const std::optional& theDomain = std::nullopt, - GeomProp::CurveDerivOrder theOrder = GeomProp::CurveDerivOrder::Undefined) - : myAdaptor(nullptr), - myCurve(theCurve) - { - (void)theDomain; - (void)theOrder; - const occ::handle aCircle = occ::down_cast(theCurve); - myRadius = aCircle->Radius(); - myCenter = aCircle->Circ().Location(); - } - - //! Non-copyable and non-movable. - GeomProp_Circle(const GeomProp_Circle&) = delete; - GeomProp_Circle& operator=(const GeomProp_Circle&) = delete; - GeomProp_Circle(GeomProp_Circle&&) = delete; - GeomProp_Circle& operator=(GeomProp_Circle&&) = delete; - - //! Sets the derivative caching order (no-op for analytical curves). - void SetDerivOrder(GeomProp::CurveDerivOrder) {} - - //! Returns the derivative caching order (always Undefined for analytical curves). - GeomProp::CurveDerivOrder DerivOrder() const { return GeomProp::CurveDerivOrder::Undefined; } - - //! Returns the adaptor pointer (nullptr when constructed from handle). - const GeomAdaptor_Curve* Adaptor() const { return myAdaptor; } - - //! Returns pointer to underlying geometry, or nullptr if constructed from adaptor. - const Geom_Curve* Geometry() const { return myCurve.get(); } - - //! Compute tangent at given parameter. - //! @param[in] theParam curve parameter - //! @param[in] theTol tolerance (unused for circle) - //! @return tangent result (always defined) - GeomProp::TangentResult Tangent(double theParam, double theTol) const - { - (void)theTol; - gp_Pnt aPnt; - gp_Vec aD1; - if (!myCurve.IsNull()) - { - myCurve->D1(theParam, aPnt, aD1); - } - else - { - myAdaptor->D1(theParam, aPnt, aD1); - } - return {gp_Dir(aD1), true}; - } - - //! Compute curvature at given parameter. - //! For a circle, curvature = 1/R (constant). - //! @param[in] theParam curve parameter (unused) - //! @param[in] theTol tolerance (unused) - //! @return curvature result (always defined, constant) - GeomProp::CurvatureResult Curvature(double theParam, double theTol) const - { - (void)theParam; - (void)theTol; - return {1.0 / myRadius, true, false}; - } - - //! Compute normal at given parameter. - //! @param[in] theParam curve parameter - //! @param[in] theTol tolerance (unused) - //! @return normal result (always defined) - GeomProp::NormalResult Normal(double theParam, double theTol) const - { - (void)theTol; - gp_Pnt aPnt; - gp_Vec aD1, aD2; - if (!myCurve.IsNull()) - { - myCurve->D2(theParam, aPnt, aD1, aD2); - } - else - { - myAdaptor->D2(theParam, aPnt, aD1, aD2); - } - // Normal = D2 * (D1.D1) - D1 * (D1.D2) - const gp_Vec aNorm = aD2 * aD1.Dot(aD1) - aD1 * aD1.Dot(aD2); - return {gp_Dir(aNorm), true}; - } - - //! Compute centre of curvature at given parameter. - //! For a circle, the centre of curvature is the geometric centre. - //! @param[in] theParam curve parameter (unused) - //! @param[in] theTol tolerance (unused) - //! @return centre result (always the circle centre) - GeomProp::CentreResult CentreOfCurvature(double theParam, double theTol) const - { - (void)theParam; - (void)theTol; - return {myCenter, true}; - } - - //! Find curvature extrema on the circle. - //! A circle has constant curvature, so no extrema. - //! @return empty analysis (always done) - GeomProp::CurveAnalysis FindCurvatureExtrema() const { return {{}, true}; } - - //! Find inflection points on the circle. - //! A circle has no inflection points. - //! @return empty analysis (always done) - GeomProp::CurveAnalysis FindInflections() const { return {{}, true}; } - -private: - const GeomAdaptor_Curve* myAdaptor = nullptr; //!< Non-owning adaptor pointer (adaptor path) - occ::handle myCurve; //!< Geometry handle (handle path) - double myRadius; //!< Cached circle radius - gp_Pnt myCenter; //!< Cached circle centre -}; - -#endif // _GeomProp_Circle_HeaderFile diff --git a/src/ModelingData/TKG3d/GeomProp/GeomProp_Cone.cxx b/src/ModelingData/TKG3d/GeomProp/GeomProp_Cone.cxx deleted file mode 100644 index 5208b8d92b..0000000000 --- a/src/ModelingData/TKG3d/GeomProp/GeomProp_Cone.cxx +++ /dev/null @@ -1,83 +0,0 @@ -// 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 - -//================================================================================================= - -GeomProp::SurfaceNormalResult GeomProp_Cone::Normal(const double theU, - const double theV, - const double theTol) const -{ - gp_Pnt aPnt; - gp_Vec aD1U, aD1V; - if (!mySurface.IsNull()) - { - mySurface->D1(theU, theV, aPnt, aD1U, aD1V); - } - else if (myAdaptor != nullptr) - { - myAdaptor->D1(theU, theV, aPnt, aD1U, aD1V); - } - else - { - return {{}, false}; - } - return GeomProp::ComputeSurfaceNormal(aD1U, aD1V, theTol); -} - -//================================================================================================= - -GeomProp::SurfaceCurvatureResult GeomProp_Cone::Curvatures(const double theU, - const double theV, - const double theTol) const -{ - gp_Pnt aPnt; - gp_Vec aD1U, aD1V, aD2U, aD2V, aD2UV; - if (!mySurface.IsNull()) - { - mySurface->D2(theU, theV, aPnt, aD1U, aD1V, aD2U, aD2V, aD2UV); - } - else if (myAdaptor != nullptr) - { - myAdaptor->D2(theU, theV, aPnt, aD1U, aD1V, aD2U, aD2V, aD2UV); - } - else - { - return {}; - } - return GeomProp::ComputeSurfaceCurvatures(aD1U, aD1V, aD2U, aD2V, aD2UV, theTol); -} - -//================================================================================================= - -GeomProp::MeanGaussianResult GeomProp_Cone::MeanGaussian(const double theU, - const double theV, - const double theTol) const -{ - gp_Pnt aPnt; - gp_Vec aD1U, aD1V, aD2U, aD2V, aD2UV; - if (!mySurface.IsNull()) - { - mySurface->D2(theU, theV, aPnt, aD1U, aD1V, aD2U, aD2V, aD2UV); - } - else if (myAdaptor != nullptr) - { - myAdaptor->D2(theU, theV, aPnt, aD1U, aD1V, aD2U, aD2V, aD2UV); - } - else - { - return {}; - } - return GeomProp::ComputeMeanGaussian(aD1U, aD1V, aD2U, aD2V, aD2UV, theTol); -} diff --git a/src/ModelingData/TKG3d/GeomProp/GeomProp_Cone.hxx b/src/ModelingData/TKG3d/GeomProp/GeomProp_Cone.hxx deleted file mode 100644 index b01224d529..0000000000 --- a/src/ModelingData/TKG3d/GeomProp/GeomProp_Cone.hxx +++ /dev/null @@ -1,100 +0,0 @@ -// 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. - -#ifndef _GeomProp_Cone_HeaderFile -#define _GeomProp_Cone_HeaderFile - -#include -#include -#include -#include - -#include - -//! @brief Local differential properties for a conical surface. -//! -//! Uses analytical formulas where possible; the curvature -//! varies along the meridian (V direction). -//! Min principal curvature = 0 (along the ruling direction). -//! Max principal curvature = cos(alpha) / R(V), where alpha is the half-angle -//! and R(V) is the radius at parameter V. -//! -//! Can be constructed from either a GeomAdaptor_Surface pointer or a occ::handle. -//! When constructed from a handle, no adaptor is created. -class GeomProp_Cone -{ -public: - DEFINE_STANDARD_ALLOC - - //! Constructor with adaptor pointer (non-owning). - //! @param theAdaptor the surface adaptor (must not be null) - GeomProp_Cone(const GeomAdaptor_Surface* theAdaptor, - GeomProp::SurfaceDerivOrder theOrder = GeomProp::SurfaceDerivOrder::Undefined) - : myAdaptor(theAdaptor) - { - (void)theOrder; - } - - //! Constructor from geometry handle. - //! @param theSurface the 3D conical surface geometry - //! @param theDomain optional parameter domain (for trimmed surfaces) - GeomProp_Cone(const occ::handle& theSurface, - const std::optional& theDomain = std::nullopt, - GeomProp::SurfaceDerivOrder theOrder = GeomProp::SurfaceDerivOrder::Undefined) - : myAdaptor(nullptr), - mySurface(theSurface), - myDomain(theDomain) - { - (void)theOrder; - } - - //! Non-copyable and non-movable. - GeomProp_Cone(const GeomProp_Cone&) = delete; - GeomProp_Cone& operator=(const GeomProp_Cone&) = delete; - GeomProp_Cone(GeomProp_Cone&&) = delete; - GeomProp_Cone& operator=(GeomProp_Cone&&) = delete; - - //! Sets the derivative caching order (no-op for analytical surfaces). - void SetDerivOrder(GeomProp::SurfaceDerivOrder) {} - - //! Returns the derivative caching order (always Undefined for analytical surfaces). - GeomProp::SurfaceDerivOrder DerivOrder() const { return GeomProp::SurfaceDerivOrder::Undefined; } - - //! Returns the adaptor pointer (nullptr when constructed from handle). - const GeomAdaptor_Surface* Adaptor() const { return myAdaptor; } - - //! Returns pointer to underlying geometry, or nullptr if constructed from adaptor. - const Geom_Surface* Geometry() const { return mySurface.get(); } - - //! Compute surface normal at given parameter. - Standard_EXPORT GeomProp::SurfaceNormalResult Normal(double theU, - double theV, - double theTol) const; - - //! Compute principal curvatures at given parameter. - Standard_EXPORT GeomProp::SurfaceCurvatureResult Curvatures(double theU, - double theV, - double theTol) const; - - //! Compute mean and Gaussian curvatures at given parameter. - Standard_EXPORT GeomProp::MeanGaussianResult MeanGaussian(double theU, - double theV, - double theTol) const; - -private: - const GeomAdaptor_Surface* myAdaptor; - occ::handle mySurface; //!< Geometry handle (handle path) - std::optional myDomain; //!< Optional parameter domain -}; - -#endif // _GeomProp_Cone_HeaderFile diff --git a/src/ModelingData/TKG3d/GeomProp/GeomProp_Curve.cxx b/src/ModelingData/TKG3d/GeomProp/GeomProp_Curve.cxx deleted file mode 100644 index 1e49a9fe94..0000000000 --- a/src/ModelingData/TKG3d/GeomProp/GeomProp_Curve.cxx +++ /dev/null @@ -1,550 +0,0 @@ -// 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 - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -//================================================================================================= - -GeomProp_Curve::GeomProp_Curve(const Adaptor3d_Curve& theCurve, - const GeomProp::CurveDerivOrder theOrder) - : myEvaluator(std::monostate{}), - myCurveType(GeomAbs_OtherCurve) -{ - initialization(theCurve, theOrder); -} - -//================================================================================================= - -GeomProp_Curve::GeomProp_Curve(const occ::handle& theCurve, - const GeomProp::CurveDerivOrder theOrder) - : myEvaluator(std::monostate{}), - myCurveType(GeomAbs_OtherCurve) -{ - initialization(theCurve, theOrder); -} - -//================================================================================================= - -void GeomProp_Curve::initialization(const Adaptor3d_Curve& theCurve, - const GeomProp::CurveDerivOrder theOrder) -{ - if (theCurve.IsKind(STANDARD_TYPE(GeomAdaptor_Curve))) - { - const GeomAdaptor_Curve& aGeomAdaptor = static_cast(theCurve); - if (!aGeomAdaptor.Curve().IsNull()) - { - // Dispatch specialized evaluators directly from the GeomAdaptor. - myOwnedAdaptor.Nullify(); - myCurveType = aGeomAdaptor.GetType(); - switch (myCurveType) - { - case GeomAbs_Line: - myEvaluator.emplace(&aGeomAdaptor, theOrder); - break; - case GeomAbs_Circle: - myEvaluator.emplace(&aGeomAdaptor, theOrder); - break; - case GeomAbs_Ellipse: - myEvaluator.emplace(&aGeomAdaptor, theOrder); - break; - case GeomAbs_Hyperbola: - myEvaluator.emplace(&aGeomAdaptor, theOrder); - break; - case GeomAbs_Parabola: - myEvaluator.emplace(&aGeomAdaptor, theOrder); - break; - case GeomAbs_BezierCurve: - myEvaluator.emplace(&aGeomAdaptor, theOrder); - break; - case GeomAbs_BSplineCurve: - myEvaluator.emplace(&aGeomAdaptor, theOrder); - break; - case GeomAbs_OffsetCurve: - myEvaluator.emplace(&aGeomAdaptor, theOrder); - break; - default: - myEvaluator.emplace(&theCurve, theOrder); - break; - } - return; - } - } - - // Non-Geom adaptor or empty curve handle: use OtherCurve with adaptor pointer. - myOwnedAdaptor.Nullify(); - myCurveType = theCurve.GetType(); - myEvaluator.emplace(&theCurve, theOrder); -} - -//================================================================================================= - -void GeomProp_Curve::initialization(const occ::handle& theCurve, - const GeomProp::CurveDerivOrder theOrder) -{ - if (theCurve.IsNull()) - { - myOwnedAdaptor.Nullify(); - myEvaluator.emplace(); - myCurveType = GeomAbs_OtherCurve; - return; - } - - // No adaptor creation for the handle path. - myOwnedAdaptor.Nullify(); - - // Unwrap TrimmedCurve to basis curve + optional CurveDomain. - occ::handle aBasis = theCurve; - std::optional aDomain; - if (aBasis->IsKind(STANDARD_TYPE(Geom_TrimmedCurve))) - { - aDomain = GeomProp::CurveDomain{theCurve->FirstParameter(), theCurve->LastParameter()}; - while (aBasis->IsKind(STANDARD_TYPE(Geom_TrimmedCurve))) - { - aBasis = occ::down_cast(aBasis)->BasisCurve(); - } - } - - // Type detection using DynamicType() - extracted once to avoid repeated virtual calls. - const occ::handle& aType = aBasis->DynamicType(); - if (aType == STANDARD_TYPE(Geom_Line)) - { - myCurveType = GeomAbs_Line; - myEvaluator.emplace(aBasis, aDomain, theOrder); - } - else if (aType == STANDARD_TYPE(Geom_Circle)) - { - myCurveType = GeomAbs_Circle; - myEvaluator.emplace(aBasis, aDomain, theOrder); - } - else if (aType == STANDARD_TYPE(Geom_Ellipse)) - { - myCurveType = GeomAbs_Ellipse; - myEvaluator.emplace(aBasis, aDomain, theOrder); - } - else if (aType == STANDARD_TYPE(Geom_Hyperbola)) - { - myCurveType = GeomAbs_Hyperbola; - myEvaluator.emplace(aBasis, aDomain, theOrder); - } - else if (aType == STANDARD_TYPE(Geom_Parabola)) - { - myCurveType = GeomAbs_Parabola; - myEvaluator.emplace(aBasis, aDomain, theOrder); - } - else if (aType == STANDARD_TYPE(Geom_BezierCurve)) - { - myCurveType = GeomAbs_BezierCurve; - myEvaluator.emplace(aBasis, aDomain, theOrder); - } - else if (aType == STANDARD_TYPE(Geom_BSplineCurve)) - { - myCurveType = GeomAbs_BSplineCurve; - myEvaluator.emplace(aBasis, aDomain, theOrder); - } - else if (aType == STANDARD_TYPE(Geom_OffsetCurve)) - { - myCurveType = GeomAbs_OffsetCurve; - myEvaluator.emplace(aBasis, aDomain, theOrder); - } - else - { - myCurveType = GeomAbs_OtherCurve; - myEvaluator.emplace(aBasis, aDomain, theOrder); - } -} - -//================================================================================================= - -void GeomProp_Curve::SetDerivOrder(const GeomProp::CurveDerivOrder theOrder) -{ - std::visit( - [theOrder](auto& theEval) { - using T = std::decay_t; - if constexpr (!std::is_same_v) - { - theEval.SetDerivOrder(theOrder); - } - }, - myEvaluator); -} - -//================================================================================================= - -GeomProp::CurveDerivOrder GeomProp_Curve::DerivOrder() const -{ - return std::visit( - [](const auto& theEval) -> GeomProp::CurveDerivOrder { - using T = std::decay_t; - if constexpr (std::is_same_v) - { - return GeomProp::CurveDerivOrder::Undefined; - } - else - { - return theEval.DerivOrder(); - } - }, - myEvaluator); -} - -//================================================================================================= - -const Adaptor3d_Curve* GeomProp_Curve::Adaptor() const -{ - if (!myOwnedAdaptor.IsNull()) - { - return myOwnedAdaptor.get(); - } - return nullptr; -} - -//================================================================================================= - -const Geom_Curve* GeomProp_Curve::Geometry() const -{ - return std::visit( - [](const auto& theEval) -> const Geom_Curve* { - using T = std::decay_t; - if constexpr (std::is_same_v) - { - return nullptr; - } - else - { - return theEval.Geometry(); - } - }, - myEvaluator); -} - -//================================================================================================= - -GeomProp::TangentResult GeomProp_Curve::Tangent(const double theParam, const double theTol) const -{ - return std::visit( - [theParam, theTol](const auto& theEval) -> GeomProp::TangentResult { - using T = std::decay_t; - if constexpr (std::is_same_v) - { - return {{}, false}; - } - else - { - return theEval.Tangent(theParam, theTol); - } - }, - myEvaluator); -} - -//================================================================================================= - -GeomProp::CurvatureResult GeomProp_Curve::Curvature(const double theParam, - const double theTol) const -{ - return std::visit( - [theParam, theTol](const auto& theEval) -> GeomProp::CurvatureResult { - using T = std::decay_t; - if constexpr (std::is_same_v) - { - return {0.0, false, false}; - } - else - { - return theEval.Curvature(theParam, theTol); - } - }, - myEvaluator); -} - -//================================================================================================= - -GeomProp::NormalResult GeomProp_Curve::Normal(const double theParam, const double theTol) const -{ - return std::visit( - [theParam, theTol](const auto& theEval) -> GeomProp::NormalResult { - using T = std::decay_t; - if constexpr (std::is_same_v) - { - return {{}, false}; - } - else - { - return theEval.Normal(theParam, theTol); - } - }, - myEvaluator); -} - -//================================================================================================= - -GeomProp::CentreResult GeomProp_Curve::CentreOfCurvature(const double theParam, - const double theTol) const -{ - return std::visit( - [theParam, theTol](const auto& theEval) -> GeomProp::CentreResult { - using T = std::decay_t; - if constexpr (std::is_same_v) - { - return {{}, false}; - } - else - { - return theEval.CentreOfCurvature(theParam, theTol); - } - }, - myEvaluator); -} - -//================================================================================================= - -GeomProp::CurveAnalysis GeomProp_Curve::FindCurvatureExtrema() const -{ - return std::visit( - [](const auto& theEval) -> GeomProp::CurveAnalysis { - using T = std::decay_t; - if constexpr (std::is_same_v) - { - return {{}, false}; - } - else - { - return theEval.FindCurvatureExtrema(); - } - }, - myEvaluator); -} - -//================================================================================================= - -GeomProp::CurveAnalysis GeomProp_Curve::FindInflections() const -{ - return std::visit( - [](const auto& theEval) -> GeomProp::CurveAnalysis { - using T = std::decay_t; - if constexpr (std::is_same_v) - { - return {{}, false}; - } - else - { - return theEval.FindInflections(); - } - }, - myEvaluator); -} - -//================================================================================================= - -// Helper to convert GeomAbs_Shape to integer for comparison. -static int geomAbsToInteger(const GeomAbs_Shape theCont) -{ - switch (theCont) - { - case GeomAbs_C0: - return 0; - case GeomAbs_G1: - return 1; - case GeomAbs_C1: - return 2; - case GeomAbs_G2: - return 3; - case GeomAbs_C2: - return 4; - case GeomAbs_C3: - return 5; - case GeomAbs_CN: - return 6; - } - return 0; -} - -//================================================================================================= - -GeomAbs_Shape GeomProp_Curve::Continuity(const occ::handle& theC1, - const occ::handle& theC2, - const double theU1, - const double theU2, - const bool theR1, - const bool theR2, - const double theTolLinear, - const double theTolAngular) -{ - GeomAbs_Shape aCont = GeomAbs_C0; - bool isChecked = false; - - // Determine continuity order of each curve. - int aCont1 = geomAbsToInteger(theC1->Continuity()); - int aCont2 = geomAbsToInteger(theC2->Continuity()); - - // Unwrap TrimmedCurve to basis curve for BSpline knot analysis. - occ::handle aCurve1 = theC1; - occ::handle aCurve2 = theC2; - if (aCurve1->IsKind(STANDARD_TYPE(Geom_TrimmedCurve))) - { - aCurve1 = occ::down_cast(aCurve1)->BasisCurve(); - } - if (aCurve2->IsKind(STANDARD_TYPE(Geom_TrimmedCurve))) - { - aCurve2 = occ::down_cast(aCurve2)->BasisCurve(); - } - - // For BSpline curves, refine continuity from knot multiplicity. - if (aCurve1->IsKind(STANDARD_TYPE(Geom_BSplineCurve))) - { - const occ::handle aBSpl = occ::down_cast(aCurve1); - double aTolerance = 0.0; - int anIdx1 = 0, anIdx2 = 0; - aBSpl->Resolution(theTolLinear, aTolerance); - aBSpl->LocateU(theU1, aTolerance, anIdx1, anIdx2); - if (anIdx1 > 1 && anIdx2 < aBSpl->NbKnots() && anIdx1 == anIdx2) - { - aCont1 = aBSpl->Degree() - aBSpl->Multiplicity(anIdx1); - } - else - { - aCont1 = 5; - } - } - if (aCurve2->IsKind(STANDARD_TYPE(Geom_BSplineCurve))) - { - const occ::handle aBSpl = occ::down_cast(aCurve2); - double aTolerance = 0.0; - int anIdx1 = 0, anIdx2 = 0; - aBSpl->Resolution(theTolLinear, aTolerance); - aBSpl->LocateU(theU2, aTolerance, anIdx1, anIdx2); - if (anIdx1 > 1 && anIdx2 < aBSpl->NbKnots() && anIdx1 == anIdx2) - { - aCont2 = aBSpl->Degree() - aBSpl->Multiplicity(anIdx1); - } - else - { - aCont2 = 5; - } - } - - // Determine maximum derivative order to evaluate. - int aN1 = 0, aN2 = 0; - if (aCont1 >= 5) - aN1 = 3; - else if (aCont1 == 4) - aN1 = 2; - else if (aCont1 >= 2) - aN1 = 1; - if (aCont2 >= 5) - aN2 = 3; - else if (aCont2 == 4) - aN2 = 2; - else if (aCont2 >= 2) - aN2 = 1; - - // Evaluate derivatives at junction points. - GeomAdaptor_Curve anAdapt1(theC1); - GeomAdaptor_Curve anAdapt2(theC2); - - // Check point coincidence using D0 only. - gp_Pnt aPnt1 = anAdapt1.Value(theU1); - gp_Pnt aPnt2 = anAdapt2.Value(theU2); - if (!aPnt1.IsEqual(aPnt2, theTolLinear)) - { - throw Standard_Failure("Curves not connected"); - } - - const int aMinOrder = std::min(aN1, aN2); - if (aMinOrder >= 1) - { - gp_Pnt aDummyPnt; - gp_Vec aD1_1, aD1_2; - anAdapt1.D1(theU1, aDummyPnt, aD1_1); - anAdapt2.D1(theU2, aDummyPnt, aD1_2); - gp_Vec aVec1 = aD1_1; - gp_Vec aVec2 = aD1_2; - if (theR1) - aVec1.Reverse(); - if (theR2) - aVec2.Reverse(); - - if (aVec1.IsEqual(aVec2, theTolLinear, theTolAngular)) - { - aCont = GeomAbs_C1; - } - else - { - // Check G1 continuity via tangent directions. - GeomProp_Curve aProp1(theC1); - GeomProp_Curve aProp2(theC2); - const GeomProp::TangentResult aTan1 = aProp1.Tangent(theU1, theTolLinear); - const GeomProp::TangentResult aTan2 = aProp2.Tangent(theU2, theTolLinear); - if (aTan1.IsDefined && aTan2.IsDefined) - { - gp_Dir aDir1 = aTan1.Direction; - gp_Dir aDir2 = aTan2.Direction; - if (theR1) - aDir1.Reverse(); - if (theR2) - aDir2.Reverse(); - if (aDir1.IsEqual(aDir2, theTolAngular)) - { - aCont = GeomAbs_G1; - } - } - isChecked = true; - } - } - - if (aMinOrder >= 2 && !isChecked) - { - // Compare second derivatives. - gp_Pnt aDummy; - gp_Vec aDummy1, aDummy2; - gp_Vec aD2_1, aD2_2; - anAdapt1.D2(theU1, aDummy, aDummy1, aD2_1); - anAdapt2.D2(theU2, aDummy, aDummy2, aD2_2); - if (aD2_1.IsEqual(aD2_2, theTolLinear, theTolAngular)) - { - aCont = GeomAbs_C2; - } - } - - return aCont; -} - -//================================================================================================= - -GeomAbs_Shape GeomProp_Curve::Continuity(const occ::handle& theC1, - const occ::handle& theC2, - const double theU1, - const double theU2, - const bool theR1, - const bool theR2) -{ - return Continuity(theC1, - theC2, - theU1, - theU2, - theR1, - theR2, - Precision::Confusion(), - Precision::Angular()); -} diff --git a/src/ModelingData/TKG3d/GeomProp/GeomProp_Curve.hxx b/src/ModelingData/TKG3d/GeomProp/GeomProp_Curve.hxx deleted file mode 100644 index 89c4ec6d17..0000000000 --- a/src/ModelingData/TKG3d/GeomProp/GeomProp_Curve.hxx +++ /dev/null @@ -1,200 +0,0 @@ -// 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. - -#ifndef _GeomProp_Curve_HeaderFile -#define _GeomProp_Curve_HeaderFile - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -//! @brief Unified local differential property evaluator for any 3D curve. -//! -//! Uses std::variant for compile-time type safety and zero heap allocation -//! for the evaluator itself. Automatically detects curve type from -//! Adaptor3d_Curve or Geom_Curve and dispatches to the appropriate -//! specialized evaluator. -//! -//! Supported curve types with optimized evaluation: -//! - Line: Trivial (zero curvature, constant tangent) -//! - Circle: Constant curvature 1/R -//! - Ellipse: Analytical curvature extrema at vertices -//! - Hyperbola: Analytical curvature extremum at vertex -//! - Parabola: Analytical curvature extremum at vertex -//! - BezierCurve: Numeric curvature extrema/inflection finding -//! - BSplineCurve: Numeric with C3 interval subdivision -//! - OffsetCurve: Numeric approach -//! - Other: Fallback using Geom_Curve virtual D1/D2/D3 -//! -//! Usage: -//! @code -//! GeomProp_Curve aProp(myGeomCurve); -//! GeomProp::CurvatureResult aCurv = aProp.Curvature(0.5, Precision::Confusion()); -//! if (aCurv.IsDefined) -//! { -//! double aValue = aCurv.Value; -//! } -//! @endcode -class GeomProp_Curve -{ -public: - DEFINE_STANDARD_ALLOC - - //! Variant type holding all possible 3D curve property evaluators. - using EvaluatorVariant = std::variant; - - //! Construct from 3D adaptor reference (auto-detects curve type). - //! For GeomAdaptor_Curve, extracts underlying Geom_Curve for optimized evaluation. - //! @param[in] theCurve 3D curve adaptor reference - //! @param[in] theOrder derivative caching order - Standard_EXPORT GeomProp_Curve( - const Adaptor3d_Curve& theCurve, - GeomProp::CurveDerivOrder theOrder = GeomProp::CurveDerivOrder::Curvature); - - //! Construct from geometry handle (auto-detects curve type). - //! @param[in] theCurve 3D geometry to evaluate - //! @param[in] theOrder derivative caching order - Standard_EXPORT GeomProp_Curve( - const occ::handle& theCurve, - GeomProp::CurveDerivOrder theOrder = GeomProp::CurveDerivOrder::Curvature); - - //! Non-copyable and non-movable. - GeomProp_Curve(const GeomProp_Curve&) = delete; - GeomProp_Curve& operator=(const GeomProp_Curve&) = delete; - GeomProp_Curve(GeomProp_Curve&&) = delete; - GeomProp_Curve& operator=(GeomProp_Curve&&) = delete; - - //! Returns the detected curve type. - GeomAbs_CurveType GetType() const { return myCurveType; } - - //! Sets the derivative caching order for the active evaluator. - //! Only effective for non-analytical curve types (BSpline, Bezier, Offset, Other). - Standard_EXPORT void SetDerivOrder(GeomProp::CurveDerivOrder theOrder); - - //! Returns the derivative caching order of the active evaluator. - Standard_EXPORT GeomProp::CurveDerivOrder DerivOrder() const; - - //! Returns the stored adaptor pointer, or null if not initialized. - Standard_EXPORT const Adaptor3d_Curve* Adaptor() const; - - //! Returns pointer to underlying geometry, or nullptr if not available. - //! When constructed from a handle, trimmed curves are unwrapped to their basis curve. - Standard_EXPORT const Geom_Curve* Geometry() const; - - //! Compute tangent at given parameter. - //! @param[in] theParam curve parameter - //! @param[in] theTol linear tolerance - //! @return tangent result with validity flag - Standard_EXPORT GeomProp::TangentResult Tangent(double theParam, double theTol) const; - - //! Compute curvature at given parameter. - //! @param[in] theParam curve parameter - //! @param[in] theTol linear tolerance - //! @return curvature result with validity and infinity flags - Standard_EXPORT GeomProp::CurvatureResult Curvature(double theParam, double theTol) const; - - //! Compute normal at given parameter. - //! @param[in] theParam curve parameter - //! @param[in] theTol linear tolerance - //! @return normal result with validity flag - Standard_EXPORT GeomProp::NormalResult Normal(double theParam, double theTol) const; - - //! Compute centre of curvature at given parameter. - //! @param[in] theParam curve parameter - //! @param[in] theTol linear tolerance - //! @return centre result with validity flag - Standard_EXPORT GeomProp::CentreResult CentreOfCurvature(double theParam, double theTol) const; - - //! Find curvature extrema on the curve. - //! @return analysis result with special points sorted by parameter - Standard_EXPORT GeomProp::CurveAnalysis FindCurvatureExtrema() const; - - //! Find inflection points on the curve. - //! @return analysis result with inflection points sorted by parameter - Standard_EXPORT GeomProp::CurveAnalysis FindInflections() const; - - //! Compute the degree of continuity at the junction between two curves. - //! The point theU1 on theC1 and the point theU2 on theC2 must be coincident. - //! For BSpline curves, knot multiplicity is used to determine available derivatives. - //! @param[in] theC1 first curve - //! @param[in] theC2 second curve - //! @param[in] theU1 parameter on first curve at junction - //! @param[in] theU2 parameter on second curve at junction - //! @param[in] theR1 true if first curve should be taken reversed - //! @param[in] theR2 true if second curve should be taken reversed - //! @param[in] theTolLinear linear tolerance for derivative comparison - //! @param[in] theTolAngular angular tolerance for direction comparison - //! @return degree of continuity at junction (C0, G1, C1, C2) - Standard_EXPORT static GeomAbs_Shape Continuity(const occ::handle& theC1, - const occ::handle& theC2, - double theU1, - double theU2, - bool theR1, - bool theR2, - double theTolLinear, - double theTolAngular); - - //! Same as above but using the standard tolerances from package Precision. - Standard_EXPORT static GeomAbs_Shape Continuity(const occ::handle& theC1, - const occ::handle& theC2, - double theU1, - double theU2, - bool theR1, - bool theR2); - -protected: - //! Initialize from 3D adaptor reference (auto-detects curve type). - //! @param[in] theCurve 3D curve adaptor reference - //! @param[in] theOrder derivative caching order - Standard_EXPORT void initialization(const Adaptor3d_Curve& theCurve, - GeomProp::CurveDerivOrder theOrder); - - //! Initialize from geometry handle (auto-detects curve type). - //! @param[in] theCurve 3D geometry to evaluate - //! @param[in] theOrder derivative caching order - Standard_EXPORT void initialization(const occ::handle& theCurve, - GeomProp::CurveDerivOrder theOrder); - -private: - occ::handle myOwnedAdaptor; //!< Owned adaptor when lifetime must be managed. - EvaluatorVariant myEvaluator; - GeomAbs_CurveType myCurveType; -}; - -#endif // _GeomProp_Curve_HeaderFile diff --git a/src/ModelingData/TKG3d/GeomProp/GeomProp_CurveAnalysisTools.pxx b/src/ModelingData/TKG3d/GeomProp/GeomProp_CurveAnalysisTools.pxx deleted file mode 100644 index c79032d0d3..0000000000 --- a/src/ModelingData/TKG3d/GeomProp/GeomProp_CurveAnalysisTools.pxx +++ /dev/null @@ -1,795 +0,0 @@ -// 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. - -#ifndef GeomProp_CurveAnalysisTools_PHeaderFile -#define GeomProp_CurveAnalysisTools_PHeaderFile - -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -//! Internal helper utilities for numeric curve analysis shared across all -//! GeomProp curve evaluators (Bezier, BSpline, Offset, Other). -//! This header is not part of the public API. -namespace GeomProp_CurveAnalysisTools -{ - -constexpr double THE_CURVATURE_DERIV_COEFF = 3.0; //!< Coefficient in d(KC)/dU formula -constexpr double THE_DIFF_STEP_DIVISOR = 100.0; //!< Divisor for numerical differentiation step -constexpr double THE_D2_MAGNITUDE_THRESHOLD = 1.0e-4; //!< Threshold for second derivative magnitude -constexpr double THE_EPSILON_SCALE = 1.0e-4; //!< Scale factor for epsilon relative to domain -constexpr int THE_EXTREMA_NB_SAMPLES = 100; //!< Number of samples for curvature extrema search -constexpr int THE_INFLECTION_NB_SAMPLES = 30; //!< Number of samples for inflection search -constexpr double THE_INFLECTION_TOLERANCE = 1.0e-6; //!< Tolerance for inflection point finding - -//! Function for finding curvature extrema: F = d(curvature)/dU = 0 -//! In 3D: KC = |V1 x V2| / ||V1||^3 -//! F = d KC / dU -template -class FuncCurExt -{ -public: - FuncCurExt(const CurveAdaptor* theCurve, const double theTol) - : myCurve(theCurve), - myEpsX(theTol) - { - } - - bool Value(const double X, double& F) - { - gp_Pnt aP; - gp_Vec aV1, aV2, aV3; - myCurve->D3(X, aP, aV1, aV2, aV3); - - // In 3D: |V1 x V2| = magnitude of cross product vector - const gp_Vec aCPV1V2 = aV1.Crossed(aV2); - const double aCPMag = aCPV1V2.Magnitude(); - const gp_Vec aCPV1V3 = aV1.Crossed(aV3); - const double aV1V2 = aV1.Dot(aV2); - const double aV1V1 = aV1.SquareMagnitude(); - const double aNV1 = std::sqrt(aV1V1); - const double aV13 = aV1V1 * aNV1; - const double aV15 = aV13 * aV1V1; - - if (aV15 < gp::Resolution()) - { - return false; - } - - // d(KC)/dU for 3D curves. - // KC = |V1 x V2| / |V1|^3 - // dKC/dU = d|V1xV2|/dU / |V1|^3 - 3 * |V1xV2| * (V1.V2) / |V1|^5 - // d|V1xV2|/dU = (V1xV2).(V1xV3) / |V1xV2| - if (aCPMag < gp::Resolution()) - { - // Cross product is zero - inflection or straight region. - // Use simplified formula. - F = aCPV1V3.Magnitude() / aV13; - return true; - } - const double aDCrossDU = aCPV1V2.Dot(aCPV1V3) / aCPMag; - F = aDCrossDU / aV13 - THE_CURVATURE_DERIV_COEFF * aCPMag * aV1V2 / aV15; - return true; - } - - bool Values(const double X, double& F, double& D) - { - double aDx = myEpsX / THE_DIFF_STEP_DIVISOR; - if (X + aDx > myCurve->LastParameter()) - { - aDx = -aDx; - } - - Value(X, F); - double aF2; - Value(X + aDx, aF2); - D = (aF2 - F) / aDx; - return true; - } - - //! Test if parameter corresponds to a minimum of the radius of curvature - //! (maximum of |curvature|) by comparison with a neighboring point. - bool IsMinKC(const double X) const - { - gp_Pnt aP; - gp_Vec aV1, aV2, aV3; - - myCurve->D3(X, aP, aV1, aV2, aV3); - const double aCPMag = aV1.Crossed(aV2).Magnitude(); - const double aV1V1 = aV1.SquareMagnitude(); - const double aNV1 = std::sqrt(aV1V1); - const double aV13 = aV1V1 * aNV1; - - if (aV13 < gp::Resolution()) - { - return false; - } - const double aKC = aCPMag / aV13; - - double aDx = myEpsX; - if (X + aDx > myCurve->LastParameter()) - { - aDx = -aDx; - } - - myCurve->D3(X + aDx, aP, aV1, aV2, aV3); - const double aCPMagN = aV1.Crossed(aV2).Magnitude(); - const double aV1V1n = aV1.SquareMagnitude(); - const double aNV1n = std::sqrt(aV1V1n); - const double aV13n = aV1V1n * aNV1n; - - if (aV13n < gp::Resolution()) - { - return false; - } - const double aKP = aCPMagN / aV13n; - - return std::abs(aKC) > std::abs(aKP); - } - -private: - const CurveAdaptor* myCurve; - double myEpsX; -}; - -//! Function for finding inflection points: F = |V1 x V2| / (||V1|| * ||V2||) = 0 -template -class FuncCurNul -{ -public: - FuncCurNul(const CurveAdaptor* theCurve) - : myCurve(theCurve) - { - } - - bool Value(const double X, double& F) - { - double aD; - return Values(X, F, aD); - } - - bool Values(const double X, double& F, double& D) - { - gp_Pnt aP; - gp_Vec aV1, aV2, aV3; - myCurve->D3(X, aP, aV1, aV2, aV3); - - const gp_Vec aCPV1V2 = aV1.Crossed(aV2); - const double aCPMag = aCPV1V2.Magnitude(); - const gp_Vec aCPV1V3 = aV1.Crossed(aV3); - const double aV1V2 = aV1.Dot(aV2); - const double aV2V3 = aV2.Dot(aV3); - const double aNV1 = aV1.Magnitude(); - const double aNV2 = aV2.Magnitude(); - - F = 0.0; - D = 0.0; - - if (aNV2 < THE_D2_MAGNITUDE_THRESHOLD) - { - return true; - } - if (aNV1 * aNV2 < gp::Resolution()) - { - return false; - } - - F = aCPMag / (aNV1 * aNV2); - - // Derivative of |V1xV2|/(|V1|*|V2|) w.r.t. parameter - if (aCPMag < gp::Resolution()) - { - D = aCPV1V3.Magnitude() / (aNV1 * aNV2); - } - else - { - const double aDCrossDU = aCPV1V2.Dot(aCPV1V3) / aCPMag; - D = (aDCrossDU - aCPMag * aV1V2 / (aNV1 * aNV1) - aCPMag * aV2V3 / (aNV2 * aNV2)) - / (aNV1 * aNV2); - } - return true; - } - -private: - const CurveAdaptor* myCurve; -}; - -//! Perform numeric curvature extrema finding on a curve interval. -template -inline void NumericCurvatureExtrema(const CurveAdaptor* theCurve, - const double theUMin, - const double theUMax, - GeomProp::CurveAnalysis& theResult) -{ - const double aEpsH = THE_EPSILON_SCALE * (theUMax - theUMin); - - FuncCurExt aFunc(theCurve, aEpsH); - - MathRoot::MultipleConfig aConfig; - aConfig.NbSamples = THE_EXTREMA_NB_SAMPLES; - aConfig.XTolerance = aEpsH; - aConfig.FTolerance = aEpsH; - - MathRoot::MultipleResult aRoots = - MathRoot::FindAllRootsWithDerivative(aFunc, theUMin, theUMax, aConfig); - - if (aRoots.IsDone()) - { - for (int j = 0; j < aRoots.NbRoots(); ++j) - { - double aParam = aRoots[j]; - // Refine the solution. - MathUtils::Config aBrentCfg; - aBrentCfg.XTolerance = Precision::PConfusion(); - aBrentCfg.FTolerance = Precision::PConfusion(); - MathUtils::ScalarResult aBrent = - MathRoot::Brent(aFunc, aParam - aEpsH, aParam + aEpsH, aBrentCfg); - if (aBrent.IsDone() && aBrent.Root.has_value()) - { - aParam = *aBrent.Root; - } - const bool aIsMin = aFunc.IsMinKC(aParam); - const GeomProp::CIType aType = - aIsMin ? GeomProp::CIType::MinCurvature : GeomProp::CIType::MaxCurvature; - theResult.Points.Append({aParam, aType}); - } - } - else - { - theResult.IsDone = false; - } -} - -//! Perform numeric inflection finding on a curve interval. -template -inline void NumericInflections(const CurveAdaptor* theCurve, - const double theUMin, - const double theUMax, - GeomProp::CurveAnalysis& theResult) -{ - FuncCurNul aFunc(theCurve); - - MathRoot::MultipleConfig aConfig; - aConfig.NbSamples = THE_INFLECTION_NB_SAMPLES; - aConfig.XTolerance = THE_INFLECTION_TOLERANCE; - aConfig.FTolerance = THE_INFLECTION_TOLERANCE; - - MathRoot::MultipleResult aRoots = MathRoot::FindAllRoots(aFunc, theUMin, theUMax, aConfig); - - if (aRoots.IsDone()) - { - for (int j = 0; j < aRoots.NbRoots(); ++j) - { - theResult.Points.Append({aRoots[j], GeomProp::CIType::Inflection}); - } - } - else - { - theResult.IsDone = false; - } -} - -//! Remove duplicate points that may appear at shared interval boundaries. -inline void RemoveDuplicatePoints(GeomProp::CurveAnalysis& theResult, const double theTol) -{ - const int aNbPts = theResult.Points.Size(); - if (aNbPts <= 1) - { - return; - } - - bool aHasDuplicates = false; - for (int i = 1; i < aNbPts && !aHasDuplicates; ++i) - { - for (int j = 0; j < i; ++j) - { - if (std::abs(theResult.Points[i].Parameter - theResult.Points[j].Parameter) < theTol) - { - aHasDuplicates = true; - break; - } - } - } - if (!aHasDuplicates) - { - return; - } - - NCollection_DynamicArray aFiltered; - aFiltered.Append(theResult.Points[0]); - for (int i = 1; i < aNbPts; ++i) - { - bool aIsDuplicate = false; - for (int j = static_cast(aFiltered.Size()) - 1; j >= 0; --j) - { - if (std::abs(theResult.Points[i].Parameter - aFiltered[j].Parameter) < theTol) - { - aIsDuplicate = true; - break; - } - } - if (!aIsDuplicate) - { - aFiltered.Append(theResult.Points[i]); - } - } - - theResult.Points = std::move(aFiltered); -} - -template -inline GeomProp::CurveAnalysis FindWholeRange( - const CurveType* theCurve, - void (*theFunc)(const CurveType*, double, double, GeomProp::CurveAnalysis&)) -{ - GeomProp::CurveAnalysis aResult; - aResult.IsDone = true; - - if (theCurve == nullptr) - { - aResult.IsDone = false; - return aResult; - } - - theFunc(theCurve, theCurve->FirstParameter(), theCurve->LastParameter(), aResult); - return aResult; -} - -//! Evaluate tangent at a point on a 3D curve with sign correction for null D1. -//! Works with both Adaptor3d_Curve and Geom_Curve. -template -inline GeomProp::TangentResult EvaluateTangent(const CurveType* theCurve, - const double theParam, - const double theTol) -{ - if (theCurve == nullptr) - { - return {{}, false}; - } - - gp_Pnt aP; - gp_Vec aD1, aD2, aD3; - theCurve->D3(theParam, aP, aD1, aD2, aD3); - - if (aD1.SquareMagnitude() > theTol * theTol) - { - return {gp_Dir(aD1), true}; - } - - constexpr double THE_DIV_FACTOR = 1.e-3; - constexpr double THE_MIN_STEP = 1.e-7; - const double anUFirst = theCurve->FirstParameter(); - const double anULast = theCurve->LastParameter(); - double aDu = 0.0; - if (anULast < RealLast() && anUFirst > RealFirst()) - aDu = anULast - anUFirst; - const double aDelta = std::max(aDu * THE_DIV_FACTOR, THE_MIN_STEP); - const double aU = (theParam - anUFirst < aDelta) ? theParam + aDelta : theParam - aDelta; - - gp_Pnt aP1, aP2; - theCurve->D0(std::min(theParam, aU), aP1); - theCurve->D0(std::max(theParam, aU), aP2); - return GeomProp::ComputeTangent(aD1, aD2, aD3, theTol, aP1, aP2); -} - -//! Evaluate curvature at a point on a 3D curve. -//! Works with both Adaptor3d_Curve and Geom_Curve. -template -inline GeomProp::CurvatureResult EvaluateCurvature(const CurveType* theCurve, - const double theParam, - const double theTol) -{ - if (theCurve == nullptr) - { - return {0.0, false, false}; - } - - gp_Pnt aP; - gp_Vec aD1, aD2; - theCurve->D2(theParam, aP, aD1, aD2); - return GeomProp::ComputeCurvature(aD1, aD2, theTol); -} - -//! Evaluate normal at a point on a 3D curve. -//! Works with both Adaptor3d_Curve and Geom_Curve. -template -inline GeomProp::NormalResult EvaluateNormal(const CurveType* theCurve, - const double theParam, - const double theTol) -{ - if (theCurve == nullptr) - { - return {{}, false}; - } - - gp_Pnt aP; - gp_Vec aD1, aD2; - theCurve->D2(theParam, aP, aD1, aD2); - return GeomProp::ComputeNormal(aD1, aD2, theTol); -} - -//! Evaluate centre of curvature at a point on a 3D curve. -//! Works with both Adaptor3d_Curve and Geom_Curve. -template -inline GeomProp::CentreResult EvaluateCentreOfCurvature(const CurveType* theCurve, - const double theParam, - const double theTol) -{ - if (theCurve == nullptr) - { - return {{}, false}; - } - - gp_Pnt aP; - gp_Vec aD1, aD2; - theCurve->D2(theParam, aP, aD1, aD2); - return GeomProp::ComputeCentreOfCurvature(aP, aD1, aD2, theTol); -} - -//! Find curvature extrema on the full curve domain. -inline GeomProp::CurveAnalysis FindCurvatureExtrema(const Adaptor3d_Curve* theCurve) -{ - return FindWholeRange(theCurve, NumericCurvatureExtrema); -} - -//! Find inflections on the full curve domain. -inline GeomProp::CurveAnalysis FindInflections(const Adaptor3d_Curve* theCurve) -{ - return FindWholeRange(theCurve, NumericInflections); -} - -//! Find curvature extrema on a Geom_Curve over a given domain. -inline GeomProp::CurveAnalysis FindCurvatureExtrema( - const Geom_Curve* theCurve, - const std::optional& theDomain) -{ - GeomProp::CurveAnalysis aResult; - aResult.IsDone = true; - if (theCurve == nullptr) - { - aResult.IsDone = false; - return aResult; - } - const double aFirst = theDomain.has_value() ? theDomain->First : theCurve->FirstParameter(); - const double aLast = theDomain.has_value() ? theDomain->Last : theCurve->LastParameter(); - NumericCurvatureExtrema(theCurve, aFirst, aLast, aResult); - return aResult; -} - -//! Find inflections on a Geom_Curve over a given domain. -inline GeomProp::CurveAnalysis FindInflections( - const Geom_Curve* theCurve, - const std::optional& theDomain) -{ - GeomProp::CurveAnalysis aResult; - aResult.IsDone = true; - if (theCurve == nullptr) - { - aResult.IsDone = false; - return aResult; - } - const double aFirst = theDomain.has_value() ? theDomain->First : theCurve->FirstParameter(); - const double aLast = theDomain.has_value() ? theDomain->Last : theCurve->LastParameter(); - NumericInflections(theCurve, aFirst, aLast, aResult); - return aResult; -} - -//! Find curvature extrema with span-by-span subdivision for low-continuity curves. -inline GeomProp::CurveAnalysis FindCurvatureExtremaBySpans(const GeomAdaptor_Curve* theCurve, - const GeomAbs_Shape theContinuity) -{ - GeomProp::CurveAnalysis aResult; - aResult.IsDone = true; - - if (theCurve == nullptr) - { - aResult.IsDone = false; - return aResult; - } - - if (theCurve->Continuity() >= theContinuity) - { - NumericCurvatureExtrema(theCurve, - theCurve->FirstParameter(), - theCurve->LastParameter(), - aResult); - } - else - { - const int aNbInt = theCurve->NbIntervals(theContinuity); - NCollection_Array1 aParams(1, aNbInt + 1); - theCurve->Intervals(aParams, theContinuity); - for (int i = 1; i <= aNbInt; ++i) - { - NumericCurvatureExtrema(theCurve, aParams(i), aParams(i + 1), aResult); - } - const double aEpsH = - THE_EPSILON_SCALE * (theCurve->LastParameter() - theCurve->FirstParameter()); - RemoveDuplicatePoints(aResult, aEpsH); - } - - return aResult; -} - -//! Find inflections with span-by-span subdivision for low-continuity curves. -inline GeomProp::CurveAnalysis FindInflectionsBySpans(const GeomAdaptor_Curve* theCurve, - const GeomAbs_Shape theContinuity) -{ - GeomProp::CurveAnalysis aResult; - aResult.IsDone = true; - - if (theCurve == nullptr) - { - aResult.IsDone = false; - return aResult; - } - - if (theCurve->Continuity() >= theContinuity) - { - NumericInflections(theCurve, theCurve->FirstParameter(), theCurve->LastParameter(), aResult); - } - else - { - const int aNbInt = theCurve->NbIntervals(theContinuity); - NCollection_Array1 aParams(1, aNbInt + 1); - theCurve->Intervals(aParams, theContinuity); - for (int i = 1; i <= aNbInt; ++i) - { - NumericInflections(theCurve, aParams(i), aParams(i + 1), aResult); - } - RemoveDuplicatePoints(aResult, THE_INFLECTION_TOLERANCE); - } - - return aResult; -} - -//! Populate 3D curve derivative cache at the requested order. -//! Works with both Adaptor3d_Curve and Geom_Curve (they share the same D0/D1/D2/D3 interface). -template -inline void EnsureCurveDerivatives(const CurveType* theCurve, - double theParam, - GeomProp::CurveDerivOrder theNeeded, - GeomProp::CurveDerivOrder theRequested, - GeomProp::CurveCache& theCache) -{ - if (theCache.IsValid(theParam) && theCache.HasOrder(theNeeded)) - { - return; - } - const int aTarget = std::max(static_cast(theRequested), static_cast(theNeeded)); - theCache.Param = theParam; - switch (static_cast(aTarget)) - { - case GeomProp::CurveDerivOrder::Value: { - gp_Pnt aP; - theCurve->D0(theParam, aP); - theCache.Data.emplace(aP); - break; - } - case GeomProp::CurveDerivOrder::Tangent: { - gp_Pnt aP; - gp_Vec aD1; - theCurve->D1(theParam, aP, aD1); - theCache.Data.emplace(Geom_Curve::ResD1{aP, aD1}); - break; - } - case GeomProp::CurveDerivOrder::Curvature: { - gp_Pnt aP; - gp_Vec aD1, aD2; - theCurve->D2(theParam, aP, aD1, aD2); - theCache.Data.emplace(Geom_Curve::ResD2{aP, aD1, aD2}); - break; - } - case GeomProp::CurveDerivOrder::CurvatureDeriv: - default: { - gp_Pnt aP; - gp_Vec aD1, aD2, aD3; - theCurve->D3(theParam, aP, aD1, aD2, aD3); - theCache.Data.emplace(Geom_Curve::ResD3{aP, aD1, aD2, aD3}); - break; - } - } -} - -//! Evaluate tangent at a point on a 3D curve using cached derivatives. -//! Works with both Adaptor3d_Curve and Geom_Curve. -template -inline GeomProp::TangentResult EvaluateTangentCached(const CurveType* theCurve, - double theParam, - double theTol, - GeomProp::CurveDerivOrder theOrder, - GeomProp::CurveCache& theCache) -{ - if (theCurve == nullptr) - { - return {{}, false}; - } - - EnsureCurveDerivatives(theCurve, - theParam, - GeomProp::CurveDerivOrder::Tangent, - theOrder, - theCache); - - gp_Vec aD1; - std::visit( - [&](const auto& theVal) { - using T = std::decay_t; - if constexpr (std::is_same_v || std::is_same_v - || std::is_same_v) - { - aD1 = theVal.D1; - } - }, - theCache.Data); - - if (aD1.SquareMagnitude() > theTol * theTol) - { - return {gp_Dir(aD1), true}; - } - - // Degenerate point - upgrade cache to D3 for sign correction. - // No need to invalidate: EnsureCurveDerivatives re-evaluates when IsValid && !HasOrder. - EnsureCurveDerivatives(theCurve, - theParam, - GeomProp::CurveDerivOrder::CurvatureDeriv, - GeomProp::CurveDerivOrder::CurvatureDeriv, - theCache); - - const auto& aD3Data = std::get(theCache.Data); - - constexpr double THE_DIV_FACTOR = 1.e-3; - constexpr double THE_MIN_STEP = 1.e-7; - const double anUFirst = theCurve->FirstParameter(); - const double anULast = theCurve->LastParameter(); - double aDu = 0.0; - if (anULast < RealLast() && anUFirst > RealFirst()) - aDu = anULast - anUFirst; - const double aDelta = std::max(aDu * THE_DIV_FACTOR, THE_MIN_STEP); - const double aU = (theParam - anUFirst < aDelta) ? theParam + aDelta : theParam - aDelta; - - // Reuse cached point for the endpoint that matches theParam. - gp_Pnt aP1, aP2; - if (theParam <= aU) - { - aP1 = aD3Data.Point; - theCurve->D0(aU, aP2); - } - else - { - theCurve->D0(aU, aP1); - aP2 = aD3Data.Point; - } - return GeomProp::ComputeTangent(aD3Data.D1, aD3Data.D2, aD3Data.D3, theTol, aP1, aP2); -} - -//! Evaluate curvature at a point on a 3D curve using cached derivatives. -//! Works with both Adaptor3d_Curve and Geom_Curve. -template -inline GeomProp::CurvatureResult EvaluateCurvatureCached(const CurveType* theCurve, - double theParam, - double theTol, - GeomProp::CurveDerivOrder theOrder, - GeomProp::CurveCache& theCache) -{ - if (theCurve == nullptr) - { - return {0.0, false, false}; - } - - EnsureCurveDerivatives(theCurve, - theParam, - GeomProp::CurveDerivOrder::Curvature, - theOrder, - theCache); - - return std::visit( - [theTol](const auto& theVal) -> GeomProp::CurvatureResult { - using T = std::decay_t; - if constexpr (std::is_same_v || std::is_same_v) - { - return GeomProp::ComputeCurvature(theVal.D1, theVal.D2, theTol); - } - else - { - return {0.0, false, false}; - } - }, - theCache.Data); -} - -//! Evaluate normal at a point on a 3D curve using cached derivatives. -//! Works with both Adaptor3d_Curve and Geom_Curve. -template -inline GeomProp::NormalResult EvaluateNormalCached(const CurveType* theCurve, - double theParam, - double theTol, - GeomProp::CurveDerivOrder theOrder, - GeomProp::CurveCache& theCache) -{ - if (theCurve == nullptr) - { - return {{}, false}; - } - - EnsureCurveDerivatives(theCurve, - theParam, - GeomProp::CurveDerivOrder::Curvature, - theOrder, - theCache); - - return std::visit( - [theTol](const auto& theVal) -> GeomProp::NormalResult { - using T = std::decay_t; - if constexpr (std::is_same_v || std::is_same_v) - { - return GeomProp::ComputeNormal(theVal.D1, theVal.D2, theTol); - } - else - { - return {{}, false}; - } - }, - theCache.Data); -} - -//! Evaluate centre of curvature at a point on a 3D curve using cached derivatives. -//! Works with both Adaptor3d_Curve and Geom_Curve. -template -inline GeomProp::CentreResult EvaluateCentreOfCurvatureCached(const CurveType* theCurve, - double theParam, - double theTol, - GeomProp::CurveDerivOrder theOrder, - GeomProp::CurveCache& theCache) -{ - if (theCurve == nullptr) - { - return {{}, false}; - } - - EnsureCurveDerivatives(theCurve, - theParam, - GeomProp::CurveDerivOrder::Curvature, - theOrder, - theCache); - - return std::visit( - [theTol](const auto& theVal) -> GeomProp::CentreResult { - using T = std::decay_t; - if constexpr (std::is_same_v || std::is_same_v) - { - return GeomProp::ComputeCentreOfCurvature(theVal.Point, theVal.D1, theVal.D2, theTol); - } - else - { - return {{}, false}; - } - }, - theCache.Data); -} - -} // namespace GeomProp_CurveAnalysisTools - -#endif // GeomProp_CurveAnalysisTools_PHeaderFile diff --git a/src/ModelingData/TKG3d/GeomProp/GeomProp_Cylinder.hxx b/src/ModelingData/TKG3d/GeomProp/GeomProp_Cylinder.hxx deleted file mode 100644 index d4343c607b..0000000000 --- a/src/ModelingData/TKG3d/GeomProp/GeomProp_Cylinder.hxx +++ /dev/null @@ -1,143 +0,0 @@ -// 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. - -#ifndef _GeomProp_Cylinder_HeaderFile -#define _GeomProp_Cylinder_HeaderFile - -#include -#include -#include - -#include - -//! @brief Local differential properties for a cylindrical surface. -//! -//! Analytical implementation with constant principal curvatures: -//! - Min curvature = 0 (along the axis direction) -//! - Max curvature = 1/R (along the circular cross-section) -//! -//! Can be constructed from either a GeomAdaptor_Surface pointer or a occ::handle. -//! When constructed from a handle, no adaptor is created. -class GeomProp_Cylinder -{ -public: - DEFINE_STANDARD_ALLOC - - //! Constructor with adaptor pointer (non-owning). - //! @param theAdaptor the surface adaptor (must not be null) - GeomProp_Cylinder(const GeomAdaptor_Surface* theAdaptor, - GeomProp::SurfaceDerivOrder theOrder = GeomProp::SurfaceDerivOrder::Undefined) - : myAdaptor(theAdaptor) - { - (void)theOrder; - } - - //! Constructor from geometry handle. - //! @param theSurface the 3D cylindrical surface geometry - //! @param theDomain optional parameter domain (for trimmed surfaces) - GeomProp_Cylinder(const occ::handle& theSurface, - const std::optional& theDomain = std::nullopt, - GeomProp::SurfaceDerivOrder theOrder = GeomProp::SurfaceDerivOrder::Undefined) - : myAdaptor(nullptr), - mySurface(theSurface), - myDomain(theDomain) - { - (void)theOrder; - } - - //! Non-copyable and non-movable. - GeomProp_Cylinder(const GeomProp_Cylinder&) = delete; - GeomProp_Cylinder& operator=(const GeomProp_Cylinder&) = delete; - GeomProp_Cylinder(GeomProp_Cylinder&&) = delete; - GeomProp_Cylinder& operator=(GeomProp_Cylinder&&) = delete; - - //! Sets the derivative caching order (no-op for analytical surfaces). - void SetDerivOrder(GeomProp::SurfaceDerivOrder) {} - - //! Returns the derivative caching order (always Undefined for analytical surfaces). - GeomProp::SurfaceDerivOrder DerivOrder() const { return GeomProp::SurfaceDerivOrder::Undefined; } - - //! Returns the adaptor pointer (nullptr when constructed from handle). - const GeomAdaptor_Surface* Adaptor() const { return myAdaptor; } - - //! Returns pointer to underlying geometry, or nullptr if constructed from adaptor. - const Geom_Surface* Geometry() const { return mySurface.get(); } - - //! Compute surface normal at given (U, V) parameter. - //! For a cylinder, the normal is radially outward from the axis. - GeomProp::SurfaceNormalResult Normal(double theU, double theV, double theTol) const - { - gp_Pnt aPnt; - gp_Vec aD1U, aD1V; - if (!mySurface.IsNull()) - { - mySurface->D1(theU, theV, aPnt, aD1U, aD1V); - } - else if (myAdaptor != nullptr) - { - myAdaptor->D1(theU, theV, aPnt, aD1U, aD1V); - } - else - { - return {{}, false}; - } - return GeomProp::ComputeSurfaceNormal(aD1U, aD1V, theTol); - } - - //! Compute principal curvatures using fundamental forms for correct sign convention. - GeomProp::SurfaceCurvatureResult Curvatures(double theU, double theV, double theTol) const - { - gp_Pnt aPnt; - gp_Vec aD1U, aD1V, aD2U, aD2V, aD2UV; - if (!mySurface.IsNull()) - { - mySurface->D2(theU, theV, aPnt, aD1U, aD1V, aD2U, aD2V, aD2UV); - } - else if (myAdaptor != nullptr) - { - myAdaptor->D2(theU, theV, aPnt, aD1U, aD1V, aD2U, aD2V, aD2UV); - } - else - { - return {}; - } - return GeomProp::ComputeSurfaceCurvatures(aD1U, aD1V, aD2U, aD2V, aD2UV, theTol); - } - - //! Compute mean and Gaussian curvatures using fundamental forms for correct sign convention. - GeomProp::MeanGaussianResult MeanGaussian(double theU, double theV, double theTol) const - { - gp_Pnt aPnt; - gp_Vec aD1U, aD1V, aD2U, aD2V, aD2UV; - if (!mySurface.IsNull()) - { - mySurface->D2(theU, theV, aPnt, aD1U, aD1V, aD2U, aD2V, aD2UV); - } - else if (myAdaptor != nullptr) - { - myAdaptor->D2(theU, theV, aPnt, aD1U, aD1V, aD2U, aD2V, aD2UV); - } - else - { - return {}; - } - return GeomProp::ComputeMeanGaussian(aD1U, aD1V, aD2U, aD2V, aD2UV, theTol); - } - -private: - const GeomAdaptor_Surface* myAdaptor; - occ::handle mySurface; //!< Geometry handle (handle path) - std::optional myDomain; //!< Optional parameter domain -}; - -#endif // _GeomProp_Cylinder_HeaderFile diff --git a/src/ModelingData/TKG3d/GeomProp/GeomProp_Ellipse.cxx b/src/ModelingData/TKG3d/GeomProp/GeomProp_Ellipse.cxx deleted file mode 100644 index 6bde1291a3..0000000000 --- a/src/ModelingData/TKG3d/GeomProp/GeomProp_Ellipse.cxx +++ /dev/null @@ -1,163 +0,0 @@ -// 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 - -#include - -#include - -namespace -{ -constexpr int THE_ELLIPSE_NB_EXTREMA = 4; //!< Number of curvature extrema on full ellipse -constexpr double THE_ELLIPSE_PERIOD = 2.0 * M_PI; //!< One full period of ellipse parameter -} // namespace - -//================================================================================================= - -GeomProp::TangentResult GeomProp_Ellipse::Tangent(const double theParam, const double theTol) const -{ - if (myCurve.IsNull() && myAdaptor == nullptr) - { - return {{}, false}; - } - gp_Pnt aPnt; - gp_Vec aD1, aD2, aD3; - if (!myCurve.IsNull()) - { - myCurve->D3(theParam, aPnt, aD1, aD2, aD3); - } - else - { - myAdaptor->D3(theParam, aPnt, aD1, aD2, aD3); - } - return GeomProp::ComputeTangent(aD1, aD2, aD3, theTol); -} - -//================================================================================================= - -GeomProp::CurvatureResult GeomProp_Ellipse::Curvature(const double theParam, - const double theTol) const -{ - if (myCurve.IsNull() && myAdaptor == nullptr) - { - return {0.0, false, false}; - } - gp_Pnt aPnt; - gp_Vec aD1, aD2; - if (!myCurve.IsNull()) - { - myCurve->D2(theParam, aPnt, aD1, aD2); - } - else - { - myAdaptor->D2(theParam, aPnt, aD1, aD2); - } - return GeomProp::ComputeCurvature(aD1, aD2, theTol); -} - -//================================================================================================= - -GeomProp::NormalResult GeomProp_Ellipse::Normal(const double theParam, const double theTol) const -{ - if (myCurve.IsNull() && myAdaptor == nullptr) - { - return {{}, false}; - } - gp_Pnt aPnt; - gp_Vec aD1, aD2; - if (!myCurve.IsNull()) - { - myCurve->D2(theParam, aPnt, aD1, aD2); - } - else - { - myAdaptor->D2(theParam, aPnt, aD1, aD2); - } - return GeomProp::ComputeNormal(aD1, aD2, theTol); -} - -//================================================================================================= - -GeomProp::CentreResult GeomProp_Ellipse::CentreOfCurvature(const double theParam, - const double theTol) const -{ - if (myCurve.IsNull() && myAdaptor == nullptr) - { - return {{}, false}; - } - gp_Pnt aPnt; - gp_Vec aD1, aD2; - if (!myCurve.IsNull()) - { - myCurve->D2(theParam, aPnt, aD1, aD2); - } - else - { - myAdaptor->D2(theParam, aPnt, aD1, aD2); - } - return GeomProp::ComputeCentreOfCurvature(aPnt, aD1, aD2, theTol); -} - -//================================================================================================= - -GeomProp::CurveAnalysis GeomProp_Ellipse::FindCurvatureExtrema() const -{ - GeomProp::CurveAnalysis aResult; - aResult.IsDone = true; - - if (myCurve.IsNull() && myAdaptor == nullptr) - { - aResult.IsDone = false; - return aResult; - } - - double aUFirst, aULast; - if (myDomain.has_value()) - { - aUFirst = myDomain->First; - aULast = myDomain->Last; - } - else if (myAdaptor != nullptr) - { - aUFirst = myAdaptor->FirstParameter(); - aULast = myAdaptor->LastParameter(); - } - else - { - aUFirst = myCurve->FirstParameter(); - aULast = myCurve->LastParameter(); - } - - const double aUFPlus2PI = aUFirst + THE_ELLIPSE_PERIOD; - - // Ellipse curvature extrema at 0, PI/2, PI, 3*PI/2 - // At 0 and PI (major axis endpoints): min radius of curvature -> max |curvature| -> MinCurvature - // At PI/2 and 3*PI/2 (minor axis endpoints): max radius of curvature -> min |curvature| -> - // MaxCurvature - const double aCandidates[] = {0.0, M_PI / 2.0, M_PI, 3.0 * M_PI / 2.0}; - const bool aIsMin[] = {true, false, true, false}; - - for (int i = 0; i < THE_ELLIPSE_NB_EXTREMA; ++i) - { - const double aU = ElCLib::InPeriod(aCandidates[i], aUFirst, aUFPlus2PI); - if (aU >= aUFirst && aU <= aULast) - { - const GeomProp::CIType aType = - aIsMin[i] ? GeomProp::CIType::MinCurvature : GeomProp::CIType::MaxCurvature; - aResult.Points.Append({aU, aType}); - } - } - - return aResult; -} diff --git a/src/ModelingData/TKG3d/GeomProp/GeomProp_Ellipse.hxx b/src/ModelingData/TKG3d/GeomProp/GeomProp_Ellipse.hxx deleted file mode 100644 index 1660f172bd..0000000000 --- a/src/ModelingData/TKG3d/GeomProp/GeomProp_Ellipse.hxx +++ /dev/null @@ -1,104 +0,0 @@ -// 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. - -#ifndef _GeomProp_Ellipse_HeaderFile -#define _GeomProp_Ellipse_HeaderFile - -#include -#include -#include -#include -#include - -#include - -//! @brief Local differential properties for a 3D ellipse. -//! -//! An ellipse has analytically known curvature extrema at the four vertices: -//! - Parameter 0 and PI: endpoints of major axis (min radius of curvature) -//! - Parameter PI/2 and 3*PI/2: endpoints of minor axis (max radius of curvature) -//! -//! Can be constructed from either a GeomAdaptor_Curve pointer or a occ::handle. -//! When constructed from a handle, no adaptor is created. -class GeomProp_Ellipse -{ -public: - DEFINE_STANDARD_ALLOC - - //! Constructor with adaptor pointer (non-owning). - //! @param theAdaptor the 3D curve adaptor (must wrap an ellipse, must not be null) - GeomProp_Ellipse(const GeomAdaptor_Curve* theAdaptor, - GeomProp::CurveDerivOrder theOrder = GeomProp::CurveDerivOrder::Undefined) - : myAdaptor(theAdaptor) - { - (void)theOrder; - } - - //! Constructor from geometry handle. - //! @param theCurve the 3D ellipse geometry - //! @param theDomain optional parameter domain (for trimmed curves) - GeomProp_Ellipse(const occ::handle& theCurve, - const std::optional& theDomain = std::nullopt, - GeomProp::CurveDerivOrder theOrder = GeomProp::CurveDerivOrder::Undefined) - : myAdaptor(nullptr), - myCurve(theCurve), - myDomain(theDomain) - { - (void)theOrder; - } - - //! Non-copyable and non-movable. - GeomProp_Ellipse(const GeomProp_Ellipse&) = delete; - GeomProp_Ellipse& operator=(const GeomProp_Ellipse&) = delete; - GeomProp_Ellipse(GeomProp_Ellipse&&) = delete; - GeomProp_Ellipse& operator=(GeomProp_Ellipse&&) = delete; - - //! Sets the derivative caching order (no-op for analytical curves). - void SetDerivOrder(GeomProp::CurveDerivOrder) {} - - //! Returns the derivative caching order (always Undefined for analytical curves). - GeomProp::CurveDerivOrder DerivOrder() const { return GeomProp::CurveDerivOrder::Undefined; } - - //! Returns the adaptor pointer (nullptr when constructed from handle). - const GeomAdaptor_Curve* Adaptor() const { return myAdaptor; } - - //! Returns pointer to underlying geometry, or nullptr if constructed from adaptor. - const Geom_Curve* Geometry() const { return myCurve.get(); } - - //! Compute tangent at given parameter. - Standard_EXPORT GeomProp::TangentResult Tangent(double theParam, double theTol) const; - - //! Compute curvature at given parameter. - Standard_EXPORT GeomProp::CurvatureResult Curvature(double theParam, double theTol) const; - - //! Compute normal at given parameter. - Standard_EXPORT GeomProp::NormalResult Normal(double theParam, double theTol) const; - - //! Compute centre of curvature at given parameter. - Standard_EXPORT GeomProp::CentreResult CentreOfCurvature(double theParam, double theTol) const; - - //! Find curvature extrema on the ellipse. - //! Extrema occur analytically at 0, PI/2, PI, and 3*PI/2, filtered to [FirstParam, LastParam]. - Standard_EXPORT GeomProp::CurveAnalysis FindCurvatureExtrema() const; - - //! Find inflection points on the ellipse. - //! An ellipse has no inflection points. - GeomProp::CurveAnalysis FindInflections() const { return {{}, true}; } - -private: - const GeomAdaptor_Curve* myAdaptor; //!< Non-owning adaptor pointer (adaptor path) - occ::handle myCurve; //!< Geometry handle (handle path) - std::optional myDomain; //!< Optional parameter domain -}; - -#endif // _GeomProp_Ellipse_HeaderFile diff --git a/src/ModelingData/TKG3d/GeomProp/GeomProp_Hyperbola.cxx b/src/ModelingData/TKG3d/GeomProp/GeomProp_Hyperbola.cxx deleted file mode 100644 index 30ea9b372f..0000000000 --- a/src/ModelingData/TKG3d/GeomProp/GeomProp_Hyperbola.cxx +++ /dev/null @@ -1,140 +0,0 @@ -// 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 - -//================================================================================================= - -GeomProp::TangentResult GeomProp_Hyperbola::Tangent(const double theParam, - const double theTol) const -{ - if (myCurve.IsNull() && myAdaptor == nullptr) - { - return {{}, false}; - } - gp_Pnt aPnt; - gp_Vec aD1, aD2, aD3; - if (!myCurve.IsNull()) - { - myCurve->D3(theParam, aPnt, aD1, aD2, aD3); - } - else - { - myAdaptor->D3(theParam, aPnt, aD1, aD2, aD3); - } - return GeomProp::ComputeTangent(aD1, aD2, aD3, theTol); -} - -//================================================================================================= - -GeomProp::CurvatureResult GeomProp_Hyperbola::Curvature(const double theParam, - const double theTol) const -{ - if (myCurve.IsNull() && myAdaptor == nullptr) - { - return {0.0, false, false}; - } - gp_Pnt aPnt; - gp_Vec aD1, aD2; - if (!myCurve.IsNull()) - { - myCurve->D2(theParam, aPnt, aD1, aD2); - } - else - { - myAdaptor->D2(theParam, aPnt, aD1, aD2); - } - return GeomProp::ComputeCurvature(aD1, aD2, theTol); -} - -//================================================================================================= - -GeomProp::NormalResult GeomProp_Hyperbola::Normal(const double theParam, const double theTol) const -{ - if (myCurve.IsNull() && myAdaptor == nullptr) - { - return {{}, false}; - } - gp_Pnt aPnt; - gp_Vec aD1, aD2; - if (!myCurve.IsNull()) - { - myCurve->D2(theParam, aPnt, aD1, aD2); - } - else - { - myAdaptor->D2(theParam, aPnt, aD1, aD2); - } - return GeomProp::ComputeNormal(aD1, aD2, theTol); -} - -//================================================================================================= - -GeomProp::CentreResult GeomProp_Hyperbola::CentreOfCurvature(const double theParam, - const double theTol) const -{ - if (myCurve.IsNull() && myAdaptor == nullptr) - { - return {{}, false}; - } - gp_Pnt aPnt; - gp_Vec aD1, aD2; - if (!myCurve.IsNull()) - { - myCurve->D2(theParam, aPnt, aD1, aD2); - } - else - { - myAdaptor->D2(theParam, aPnt, aD1, aD2); - } - return GeomProp::ComputeCentreOfCurvature(aPnt, aD1, aD2, theTol); -} - -//================================================================================================= - -GeomProp::CurveAnalysis GeomProp_Hyperbola::FindCurvatureExtrema() const -{ - GeomProp::CurveAnalysis aResult; - aResult.IsDone = true; - - if (myCurve.IsNull() && myAdaptor == nullptr) - { - aResult.IsDone = false; - return aResult; - } - - double aUFirst, aULast; - if (myDomain.has_value()) - { - aUFirst = myDomain->First; - aULast = myDomain->Last; - } - else if (myAdaptor != nullptr) - { - aUFirst = myAdaptor->FirstParameter(); - aULast = myAdaptor->LastParameter(); - } - else - { - aUFirst = myCurve->FirstParameter(); - aULast = myCurve->LastParameter(); - } - - // Hyperbola has maximum |curvature| at parameter 0 (vertex). - if (aUFirst <= 0.0 && aULast >= 0.0) - { - aResult.Points.Append({0.0, GeomProp::CIType::MinCurvature}); - } - - return aResult; -} diff --git a/src/ModelingData/TKG3d/GeomProp/GeomProp_Hyperbola.hxx b/src/ModelingData/TKG3d/GeomProp/GeomProp_Hyperbola.hxx deleted file mode 100644 index fa26561589..0000000000 --- a/src/ModelingData/TKG3d/GeomProp/GeomProp_Hyperbola.hxx +++ /dev/null @@ -1,103 +0,0 @@ -// 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. - -#ifndef _GeomProp_Hyperbola_HeaderFile -#define _GeomProp_Hyperbola_HeaderFile - -#include -#include -#include -#include -#include - -#include - -//! @brief Local differential properties for a 3D hyperbola. -//! -//! A hyperbola has a single curvature extremum (maximum |curvature|) at parameter 0 -//! (the vertex). No inflection points exist. -//! -//! Can be constructed from either a GeomAdaptor_Curve pointer or a occ::handle. -//! When constructed from a handle, no adaptor is created. -class GeomProp_Hyperbola -{ -public: - DEFINE_STANDARD_ALLOC - - //! Constructor with adaptor pointer (non-owning). - //! @param theAdaptor the 3D curve adaptor (must wrap a hyperbola, must not be null) - GeomProp_Hyperbola(const GeomAdaptor_Curve* theAdaptor, - GeomProp::CurveDerivOrder theOrder = GeomProp::CurveDerivOrder::Undefined) - : myAdaptor(theAdaptor) - { - (void)theOrder; - } - - //! Constructor from geometry handle. - //! @param theCurve the 3D hyperbola geometry - //! @param theDomain optional parameter domain (for trimmed curves) - GeomProp_Hyperbola(const occ::handle& theCurve, - const std::optional& theDomain = std::nullopt, - GeomProp::CurveDerivOrder theOrder = GeomProp::CurveDerivOrder::Undefined) - : myAdaptor(nullptr), - myCurve(theCurve), - myDomain(theDomain) - { - (void)theOrder; - } - - //! Non-copyable and non-movable. - GeomProp_Hyperbola(const GeomProp_Hyperbola&) = delete; - GeomProp_Hyperbola& operator=(const GeomProp_Hyperbola&) = delete; - GeomProp_Hyperbola(GeomProp_Hyperbola&&) = delete; - GeomProp_Hyperbola& operator=(GeomProp_Hyperbola&&) = delete; - - //! Sets the derivative caching order (no-op for analytical curves). - void SetDerivOrder(GeomProp::CurveDerivOrder) {} - - //! Returns the derivative caching order (always Undefined for analytical curves). - GeomProp::CurveDerivOrder DerivOrder() const { return GeomProp::CurveDerivOrder::Undefined; } - - //! Returns the adaptor pointer (nullptr when constructed from handle). - const GeomAdaptor_Curve* Adaptor() const { return myAdaptor; } - - //! Returns pointer to underlying geometry, or nullptr if constructed from adaptor. - const Geom_Curve* Geometry() const { return myCurve.get(); } - - //! Compute tangent at given parameter. - Standard_EXPORT GeomProp::TangentResult Tangent(double theParam, double theTol) const; - - //! Compute curvature at given parameter. - Standard_EXPORT GeomProp::CurvatureResult Curvature(double theParam, double theTol) const; - - //! Compute normal at given parameter. - Standard_EXPORT GeomProp::NormalResult Normal(double theParam, double theTol) const; - - //! Compute centre of curvature at given parameter. - Standard_EXPORT GeomProp::CentreResult CentreOfCurvature(double theParam, double theTol) const; - - //! Find curvature extrema on the hyperbola. - //! Single extremum at parameter 0 (the vertex), if within parameter range. - Standard_EXPORT GeomProp::CurveAnalysis FindCurvatureExtrema() const; - - //! Find inflection points on the hyperbola. - //! A hyperbola has no inflection points. - GeomProp::CurveAnalysis FindInflections() const { return {{}, true}; } - -private: - const GeomAdaptor_Curve* myAdaptor; //!< Non-owning adaptor pointer (adaptor path) - occ::handle myCurve; //!< Geometry handle (handle path) - std::optional myDomain; //!< Optional parameter domain -}; - -#endif // _GeomProp_Hyperbola_HeaderFile diff --git a/src/ModelingData/TKG3d/GeomProp/GeomProp_Line.hxx b/src/ModelingData/TKG3d/GeomProp/GeomProp_Line.hxx deleted file mode 100644 index 4552e88dcf..0000000000 --- a/src/ModelingData/TKG3d/GeomProp/GeomProp_Line.hxx +++ /dev/null @@ -1,140 +0,0 @@ -// 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. - -#ifndef _GeomProp_Line_HeaderFile -#define _GeomProp_Line_HeaderFile - -#include -#include -#include -#include - -#include - -//! @brief Local differential properties for a 3D line. -//! -//! A line has constant tangent, zero curvature, undefined normal and centre. -//! No curvature extrema or inflection points exist. -//! -//! Can be constructed from either a GeomAdaptor_Curve pointer or a occ::handle. -//! When constructed from a handle, no adaptor is created. -class GeomProp_Line -{ -public: - DEFINE_STANDARD_ALLOC - - //! Constructor with adaptor pointer (non-owning). - //! @param theAdaptor the 3D curve adaptor (must wrap a line, must not be null) - GeomProp_Line(const GeomAdaptor_Curve* theAdaptor, - GeomProp::CurveDerivOrder theOrder = GeomProp::CurveDerivOrder::Undefined) - : myAdaptor(theAdaptor), - myCurve(theAdaptor->Curve()) - { - (void)theOrder; - } - - //! Constructor from geometry handle. - //! @param theCurve the 3D line geometry (must be a Geom_Line or downcastable to it) - //! @param theDomain optional parameter domain (unused for line) - GeomProp_Line(const occ::handle& theCurve, - const std::optional& theDomain = std::nullopt, - GeomProp::CurveDerivOrder theOrder = GeomProp::CurveDerivOrder::Undefined) - : myAdaptor(nullptr), - myCurve(theCurve) - { - (void)theDomain; - (void)theOrder; - } - - //! Non-copyable and non-movable. - GeomProp_Line(const GeomProp_Line&) = delete; - GeomProp_Line& operator=(const GeomProp_Line&) = delete; - GeomProp_Line(GeomProp_Line&&) = delete; - GeomProp_Line& operator=(GeomProp_Line&&) = delete; - - //! Sets the derivative caching order (no-op for analytical curves). - void SetDerivOrder(GeomProp::CurveDerivOrder) {} - - //! Returns the derivative caching order (always Undefined for analytical curves). - GeomProp::CurveDerivOrder DerivOrder() const { return GeomProp::CurveDerivOrder::Undefined; } - - //! Returns the adaptor pointer (nullptr when constructed from handle). - const GeomAdaptor_Curve* Adaptor() const { return myAdaptor; } - - //! Returns pointer to underlying geometry, or nullptr if constructed from adaptor. - const Geom_Curve* Geometry() const { return myCurve.get(); } - - //! Compute tangent at given parameter. - //! For a line, the tangent is always the line direction. - //! @param[in] theParam curve parameter (unused) - //! @param[in] theTol tolerance (unused) - //! @return tangent result (always defined) - GeomProp::TangentResult Tangent(double theParam, double theTol) const - { - (void)theParam; - (void)theTol; - return {occ::down_cast(myCurve)->Position().Direction(), true}; - } - - //! Compute curvature at given parameter. - //! For a line, curvature is always zero. - //! @param[in] theParam curve parameter (unused) - //! @param[in] theTol tolerance (unused) - //! @return curvature result (always zero) - GeomProp::CurvatureResult Curvature(double theParam, double theTol) const - { - (void)theParam; - (void)theTol; - return {0.0, true, false}; - } - - //! Compute normal at given parameter. - //! For a line, the normal is undefined (zero curvature). - //! @param[in] theParam curve parameter (unused) - //! @param[in] theTol tolerance (unused) - //! @return normal result (always undefined) - GeomProp::NormalResult Normal(double theParam, double theTol) const - { - (void)theParam; - (void)theTol; - return {{}, false}; - } - - //! Compute centre of curvature at given parameter. - //! For a line, the centre is undefined (zero curvature). - //! @param[in] theParam curve parameter (unused) - //! @param[in] theTol tolerance (unused) - //! @return centre result (always undefined) - GeomProp::CentreResult CentreOfCurvature(double theParam, double theTol) const - { - (void)theParam; - (void)theTol; - return {{}, false}; - } - - //! Find curvature extrema on the line. - //! A line has no curvature extrema. - //! @return empty analysis (always done) - GeomProp::CurveAnalysis FindCurvatureExtrema() const { return {{}, true}; } - - //! Find inflection points on the line. - //! A line has no inflection points. - //! @return empty analysis (always done) - GeomProp::CurveAnalysis FindInflections() const { return {{}, true}; } - -private: - const GeomAdaptor_Curve* myAdaptor = nullptr; //!< Non-owning adaptor pointer (adaptor path) - occ::handle myCurve; //!< Geometry handle (handle path) -}; - -#endif // _GeomProp_Line_HeaderFile diff --git a/src/ModelingData/TKG3d/GeomProp/GeomProp_OffsetCurve.cxx b/src/ModelingData/TKG3d/GeomProp/GeomProp_OffsetCurve.cxx deleted file mode 100644 index a7245ce7a4..0000000000 --- a/src/ModelingData/TKG3d/GeomProp/GeomProp_OffsetCurve.cxx +++ /dev/null @@ -1,123 +0,0 @@ -// 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 -#include - -//================================================================================================= - -GeomProp::TangentResult GeomProp_OffsetCurve::Tangent(const double theParam, - const double theTol) const -{ - if (!myCurve.IsNull()) - { - return GeomProp_CurveAnalysisTools::EvaluateTangentCached(myCurve.get(), - theParam, - theTol, - myRequestedOrder, - myCache); - } - return GeomProp_CurveAnalysisTools::EvaluateTangentCached(myAdaptor, - theParam, - theTol, - myRequestedOrder, - myCache); -} - -//================================================================================================= - -GeomProp::CurvatureResult GeomProp_OffsetCurve::Curvature(const double theParam, - const double theTol) const -{ - if (!myCurve.IsNull()) - { - return GeomProp_CurveAnalysisTools::EvaluateCurvatureCached(myCurve.get(), - theParam, - theTol, - myRequestedOrder, - myCache); - } - return GeomProp_CurveAnalysisTools::EvaluateCurvatureCached(myAdaptor, - theParam, - theTol, - myRequestedOrder, - myCache); -} - -//================================================================================================= - -GeomProp::NormalResult GeomProp_OffsetCurve::Normal(const double theParam, - const double theTol) const -{ - if (!myCurve.IsNull()) - { - return GeomProp_CurveAnalysisTools::EvaluateNormalCached(myCurve.get(), - theParam, - theTol, - myRequestedOrder, - myCache); - } - return GeomProp_CurveAnalysisTools::EvaluateNormalCached(myAdaptor, - theParam, - theTol, - myRequestedOrder, - myCache); -} - -//================================================================================================= - -GeomProp::CentreResult GeomProp_OffsetCurve::CentreOfCurvature(const double theParam, - const double theTol) const -{ - if (!myCurve.IsNull()) - { - return GeomProp_CurveAnalysisTools::EvaluateCentreOfCurvatureCached(myCurve.get(), - theParam, - theTol, - myRequestedOrder, - myCache); - } - return GeomProp_CurveAnalysisTools::EvaluateCentreOfCurvatureCached(myAdaptor, - theParam, - theTol, - myRequestedOrder, - myCache); -} - -//================================================================================================= - -GeomProp::CurveAnalysis GeomProp_OffsetCurve::FindCurvatureExtrema() const -{ - if (!myCurve.IsNull()) - { - const double aFirst = myDomain.has_value() ? myDomain->First : myCurve->FirstParameter(); - const double aLast = myDomain.has_value() ? myDomain->Last : myCurve->LastParameter(); - GeomAdaptor_Curve anAdaptor(myCurve, aFirst, aLast); - return GeomProp_CurveAnalysisTools::FindCurvatureExtrema(&anAdaptor); - } - return GeomProp_CurveAnalysisTools::FindCurvatureExtrema(myAdaptor); -} - -//================================================================================================= - -GeomProp::CurveAnalysis GeomProp_OffsetCurve::FindInflections() const -{ - if (!myCurve.IsNull()) - { - const double aFirst = myDomain.has_value() ? myDomain->First : myCurve->FirstParameter(); - const double aLast = myDomain.has_value() ? myDomain->Last : myCurve->LastParameter(); - GeomAdaptor_Curve anAdaptor(myCurve, aFirst, aLast); - return GeomProp_CurveAnalysisTools::FindInflections(&anAdaptor); - } - return GeomProp_CurveAnalysisTools::FindInflections(myAdaptor); -} diff --git a/src/ModelingData/TKG3d/GeomProp/GeomProp_OffsetCurve.hxx b/src/ModelingData/TKG3d/GeomProp/GeomProp_OffsetCurve.hxx deleted file mode 100644 index 5e5d3b7566..0000000000 --- a/src/ModelingData/TKG3d/GeomProp/GeomProp_OffsetCurve.hxx +++ /dev/null @@ -1,104 +0,0 @@ -// 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. - -#ifndef _GeomProp_OffsetCurve_HeaderFile -#define _GeomProp_OffsetCurve_HeaderFile - -#include -#include -#include -#include -#include - -#include - -//! @brief Local differential properties for a 3D offset curve. -//! -//! Uses numeric root-finding for curvature extrema and inflection points. -//! Local properties are computed from the offset curve's own D1/D2/D3. -//! -//! Can be constructed from either a GeomAdaptor_Curve pointer or a occ::handle. -//! When constructed from a handle, no adaptor is created; for complex methods -//! (FindCurvatureExtrema, FindInflections) a stack-local adaptor is created on demand. -class GeomProp_OffsetCurve -{ -public: - DEFINE_STANDARD_ALLOC - - //! Constructor with adaptor pointer (non-owning). - //! @param theAdaptor the 3D curve adaptor (must wrap an offset curve, must not be null) - GeomProp_OffsetCurve(const GeomAdaptor_Curve* theAdaptor, - GeomProp::CurveDerivOrder theOrder = GeomProp::CurveDerivOrder::Curvature) - : myAdaptor(theAdaptor), - myRequestedOrder(theOrder) - { - } - - //! Constructor from geometry handle. - //! @param theCurve the 3D offset curve geometry - //! @param theDomain optional parameter domain (for trimmed curves) - GeomProp_OffsetCurve(const occ::handle& theCurve, - const std::optional& theDomain = std::nullopt, - GeomProp::CurveDerivOrder theOrder = GeomProp::CurveDerivOrder::Curvature) - : myAdaptor(nullptr), - myRequestedOrder(theOrder), - myCurve(theCurve), - myDomain(theDomain) - { - } - - //! Non-copyable and non-movable. - GeomProp_OffsetCurve(const GeomProp_OffsetCurve&) = delete; - GeomProp_OffsetCurve& operator=(const GeomProp_OffsetCurve&) = delete; - GeomProp_OffsetCurve(GeomProp_OffsetCurve&&) = delete; - GeomProp_OffsetCurve& operator=(GeomProp_OffsetCurve&&) = delete; - - //! Sets the derivative caching order. - void SetDerivOrder(GeomProp::CurveDerivOrder theOrder) { myRequestedOrder = theOrder; } - - //! Returns the derivative caching order. - GeomProp::CurveDerivOrder DerivOrder() const { return myRequestedOrder; } - - //! Returns the adaptor pointer (nullptr when constructed from handle). - const GeomAdaptor_Curve* Adaptor() const { return myAdaptor; } - - //! Returns pointer to underlying geometry, or nullptr if constructed from adaptor. - const Geom_Curve* Geometry() const { return myCurve.get(); } - - //! Compute tangent at given parameter. - Standard_EXPORT GeomProp::TangentResult Tangent(double theParam, double theTol) const; - - //! Compute curvature at given parameter. - Standard_EXPORT GeomProp::CurvatureResult Curvature(double theParam, double theTol) const; - - //! Compute normal at given parameter. - Standard_EXPORT GeomProp::NormalResult Normal(double theParam, double theTol) const; - - //! Compute centre of curvature at given parameter. - Standard_EXPORT GeomProp::CentreResult CentreOfCurvature(double theParam, double theTol) const; - - //! Find curvature extrema using numeric root-finding. - Standard_EXPORT GeomProp::CurveAnalysis FindCurvatureExtrema() const; - - //! Find inflection points using numeric root-finding. - Standard_EXPORT GeomProp::CurveAnalysis FindInflections() const; - -private: - const GeomAdaptor_Curve* myAdaptor; - GeomProp::CurveDerivOrder myRequestedOrder; - mutable GeomProp::CurveCache myCache; - occ::handle myCurve; //!< Geometry handle (handle path) - std::optional myDomain; //!< Optional parameter domain -}; - -#endif // _GeomProp_OffsetCurve_HeaderFile diff --git a/src/ModelingData/TKG3d/GeomProp/GeomProp_OffsetSurface.cxx b/src/ModelingData/TKG3d/GeomProp/GeomProp_OffsetSurface.cxx deleted file mode 100644 index 6d68390315..0000000000 --- a/src/ModelingData/TKG3d/GeomProp/GeomProp_OffsetSurface.cxx +++ /dev/null @@ -1,84 +0,0 @@ -// 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 -#include - -//================================================================================================= - -GeomProp::SurfaceNormalResult GeomProp_OffsetSurface::Normal(const double theU, - const double theV, - const double theTol) const -{ - if (!mySurface.IsNull()) - { - return GeomProp_SurfaceAnalysisTools::EvaluateNormalCached(mySurface.get(), - theU, - theV, - theTol, - myRequestedOrder, - myCache); - } - return GeomProp_SurfaceAnalysisTools::EvaluateNormalCached(myAdaptor, - theU, - theV, - theTol, - myRequestedOrder, - myCache); -} - -//================================================================================================= - -GeomProp::SurfaceCurvatureResult GeomProp_OffsetSurface::Curvatures(const double theU, - const double theV, - const double theTol) const -{ - if (!mySurface.IsNull()) - { - return GeomProp_SurfaceAnalysisTools::EvaluateCurvaturesCached(mySurface.get(), - theU, - theV, - theTol, - myRequestedOrder, - myCache); - } - return GeomProp_SurfaceAnalysisTools::EvaluateCurvaturesCached(myAdaptor, - theU, - theV, - theTol, - myRequestedOrder, - myCache); -} - -//================================================================================================= - -GeomProp::MeanGaussianResult GeomProp_OffsetSurface::MeanGaussian(const double theU, - const double theV, - const double theTol) const -{ - if (!mySurface.IsNull()) - { - return GeomProp_SurfaceAnalysisTools::EvaluateMeanGaussianCached(mySurface.get(), - theU, - theV, - theTol, - myRequestedOrder, - myCache); - } - return GeomProp_SurfaceAnalysisTools::EvaluateMeanGaussianCached(myAdaptor, - theU, - theV, - theTol, - myRequestedOrder, - myCache); -} diff --git a/src/ModelingData/TKG3d/GeomProp/GeomProp_OffsetSurface.hxx b/src/ModelingData/TKG3d/GeomProp/GeomProp_OffsetSurface.hxx deleted file mode 100644 index 4a4d772a8f..0000000000 --- a/src/ModelingData/TKG3d/GeomProp/GeomProp_OffsetSurface.hxx +++ /dev/null @@ -1,100 +0,0 @@ -// 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. - -#ifndef _GeomProp_OffsetSurface_HeaderFile -#define _GeomProp_OffsetSurface_HeaderFile - -#include -#include -#include -#include - -#include - -//! @brief Local differential properties for an offset surface. -//! -//! Uses numeric evaluation from surface derivatives. -//! -//! Can be constructed from either a GeomAdaptor_Surface pointer or a occ::handle. -//! When constructed from a handle, no adaptor is created. -class GeomProp_OffsetSurface -{ -public: - DEFINE_STANDARD_ALLOC - - //! Constructor with adaptor pointer (non-owning). - //! @param theAdaptor the surface adaptor (must not be null) - GeomProp_OffsetSurface( - const GeomAdaptor_Surface* theAdaptor, - GeomProp::SurfaceDerivOrder theOrder = GeomProp::SurfaceDerivOrder::Curvature) - : myAdaptor(theAdaptor), - myRequestedOrder(theOrder) - { - } - - //! Constructor from geometry handle. - //! @param theSurface the 3D offset surface geometry - //! @param theDomain optional parameter domain (for trimmed surfaces) - GeomProp_OffsetSurface( - const occ::handle& theSurface, - const std::optional& theDomain = std::nullopt, - GeomProp::SurfaceDerivOrder theOrder = GeomProp::SurfaceDerivOrder::Curvature) - : myAdaptor(nullptr), - myRequestedOrder(theOrder), - mySurface(theSurface), - myDomain(theDomain) - { - } - - //! Non-copyable and non-movable. - GeomProp_OffsetSurface(const GeomProp_OffsetSurface&) = delete; - GeomProp_OffsetSurface& operator=(const GeomProp_OffsetSurface&) = delete; - GeomProp_OffsetSurface(GeomProp_OffsetSurface&&) = delete; - GeomProp_OffsetSurface& operator=(GeomProp_OffsetSurface&&) = delete; - - //! Sets the derivative caching order. - void SetDerivOrder(GeomProp::SurfaceDerivOrder theOrder) { myRequestedOrder = theOrder; } - - //! Returns the derivative caching order. - GeomProp::SurfaceDerivOrder DerivOrder() const { return myRequestedOrder; } - - //! Returns the adaptor pointer (nullptr when constructed from handle). - const GeomAdaptor_Surface* Adaptor() const { return myAdaptor; } - - //! Returns pointer to underlying geometry, or nullptr if constructed from adaptor. - const Geom_Surface* Geometry() const { return mySurface.get(); } - - //! Compute surface normal at given parameter. - Standard_EXPORT GeomProp::SurfaceNormalResult Normal(double theU, - double theV, - double theTol) const; - - //! Compute principal curvatures at given parameter. - Standard_EXPORT GeomProp::SurfaceCurvatureResult Curvatures(double theU, - double theV, - double theTol) const; - - //! Compute mean and Gaussian curvatures at given parameter. - Standard_EXPORT GeomProp::MeanGaussianResult MeanGaussian(double theU, - double theV, - double theTol) const; - -private: - const GeomAdaptor_Surface* myAdaptor; - GeomProp::SurfaceDerivOrder myRequestedOrder; - mutable GeomProp::SurfaceCache myCache; - occ::handle mySurface; //!< Geometry handle (handle path) - std::optional myDomain; //!< Optional parameter domain -}; - -#endif // _GeomProp_OffsetSurface_HeaderFile diff --git a/src/ModelingData/TKG3d/GeomProp/GeomProp_OtherCurve.cxx b/src/ModelingData/TKG3d/GeomProp/GeomProp_OtherCurve.cxx deleted file mode 100644 index 4ed88f85b3..0000000000 --- a/src/ModelingData/TKG3d/GeomProp/GeomProp_OtherCurve.cxx +++ /dev/null @@ -1,122 +0,0 @@ -// 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 -#include - -//================================================================================================= - -GeomProp::TangentResult GeomProp_OtherCurve::Tangent(const double theParam, - const double theTol) const -{ - if (!myCurve.IsNull()) - { - return GeomProp_CurveAnalysisTools::EvaluateTangentCached(myCurve.get(), - theParam, - theTol, - myRequestedOrder, - myCache); - } - return GeomProp_CurveAnalysisTools::EvaluateTangentCached(myAdaptor, - theParam, - theTol, - myRequestedOrder, - myCache); -} - -//================================================================================================= - -GeomProp::CurvatureResult GeomProp_OtherCurve::Curvature(const double theParam, - const double theTol) const -{ - if (!myCurve.IsNull()) - { - return GeomProp_CurveAnalysisTools::EvaluateCurvatureCached(myCurve.get(), - theParam, - theTol, - myRequestedOrder, - myCache); - } - return GeomProp_CurveAnalysisTools::EvaluateCurvatureCached(myAdaptor, - theParam, - theTol, - myRequestedOrder, - myCache); -} - -//================================================================================================= - -GeomProp::NormalResult GeomProp_OtherCurve::Normal(const double theParam, const double theTol) const -{ - if (!myCurve.IsNull()) - { - return GeomProp_CurveAnalysisTools::EvaluateNormalCached(myCurve.get(), - theParam, - theTol, - myRequestedOrder, - myCache); - } - return GeomProp_CurveAnalysisTools::EvaluateNormalCached(myAdaptor, - theParam, - theTol, - myRequestedOrder, - myCache); -} - -//================================================================================================= - -GeomProp::CentreResult GeomProp_OtherCurve::CentreOfCurvature(const double theParam, - const double theTol) const -{ - if (!myCurve.IsNull()) - { - return GeomProp_CurveAnalysisTools::EvaluateCentreOfCurvatureCached(myCurve.get(), - theParam, - theTol, - myRequestedOrder, - myCache); - } - return GeomProp_CurveAnalysisTools::EvaluateCentreOfCurvatureCached(myAdaptor, - theParam, - theTol, - myRequestedOrder, - myCache); -} - -//================================================================================================= - -GeomProp::CurveAnalysis GeomProp_OtherCurve::FindCurvatureExtrema() const -{ - if (!myCurve.IsNull()) - { - const double aFirst = myDomain.has_value() ? myDomain->First : myCurve->FirstParameter(); - const double aLast = myDomain.has_value() ? myDomain->Last : myCurve->LastParameter(); - GeomAdaptor_Curve anAdaptor(myCurve, aFirst, aLast); - return GeomProp_CurveAnalysisTools::FindCurvatureExtrema(&anAdaptor); - } - return GeomProp_CurveAnalysisTools::FindCurvatureExtrema(myAdaptor); -} - -//================================================================================================= - -GeomProp::CurveAnalysis GeomProp_OtherCurve::FindInflections() const -{ - if (!myCurve.IsNull()) - { - const double aFirst = myDomain.has_value() ? myDomain->First : myCurve->FirstParameter(); - const double aLast = myDomain.has_value() ? myDomain->Last : myCurve->LastParameter(); - GeomAdaptor_Curve anAdaptor(myCurve, aFirst, aLast); - return GeomProp_CurveAnalysisTools::FindInflections(&anAdaptor); - } - return GeomProp_CurveAnalysisTools::FindInflections(myAdaptor); -} diff --git a/src/ModelingData/TKG3d/GeomProp/GeomProp_OtherCurve.hxx b/src/ModelingData/TKG3d/GeomProp/GeomProp_OtherCurve.hxx deleted file mode 100644 index d8341afa44..0000000000 --- a/src/ModelingData/TKG3d/GeomProp/GeomProp_OtherCurve.hxx +++ /dev/null @@ -1,104 +0,0 @@ -// 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. - -#ifndef _GeomProp_OtherCurve_HeaderFile -#define _GeomProp_OtherCurve_HeaderFile - -#include -#include -#include -#include -#include - -#include - -//! @brief Fallback local differential properties for any 3D curve type. -//! -//! Uses adaptor D1/D2/D3 methods for property computation -//! and numeric root-finding for curvature extrema and inflection points. -//! -//! Can be constructed from an Adaptor3d_Curve pointer -//! or a occ::handle. When constructed from a handle, no adaptor is created; -//! for complex methods a stack-local adaptor is created on demand. -class GeomProp_OtherCurve -{ -public: - DEFINE_STANDARD_ALLOC - - //! Constructor with Adaptor3d_Curve pointer (non-owning). - //! @param theAdaptor the 3D curve adaptor (must not be null) - GeomProp_OtherCurve(const Adaptor3d_Curve* theAdaptor, - GeomProp::CurveDerivOrder theOrder = GeomProp::CurveDerivOrder::Curvature) - : myAdaptor(theAdaptor), - myRequestedOrder(theOrder) - { - } - - //! Constructor from geometry handle. - //! @param theCurve the 3D curve geometry - //! @param theDomain optional parameter domain (for trimmed curves) - GeomProp_OtherCurve(const occ::handle& theCurve, - const std::optional& theDomain = std::nullopt, - GeomProp::CurveDerivOrder theOrder = GeomProp::CurveDerivOrder::Curvature) - : myAdaptor(nullptr), - myRequestedOrder(theOrder), - myCurve(theCurve), - myDomain(theDomain) - { - } - - //! Non-copyable and non-movable. - GeomProp_OtherCurve(const GeomProp_OtherCurve&) = delete; - GeomProp_OtherCurve& operator=(const GeomProp_OtherCurve&) = delete; - GeomProp_OtherCurve(GeomProp_OtherCurve&&) = delete; - GeomProp_OtherCurve& operator=(GeomProp_OtherCurve&&) = delete; - - //! Sets the derivative caching order. - void SetDerivOrder(GeomProp::CurveDerivOrder theOrder) { myRequestedOrder = theOrder; } - - //! Returns the derivative caching order. - GeomProp::CurveDerivOrder DerivOrder() const { return myRequestedOrder; } - - //! Returns the adaptor pointer (nullptr when constructed from handle). - const Adaptor3d_Curve* Adaptor() const { return myAdaptor; } - - //! Returns pointer to underlying geometry, or nullptr if constructed from adaptor. - const Geom_Curve* Geometry() const { return myCurve.get(); } - - //! Compute tangent at given parameter. - Standard_EXPORT GeomProp::TangentResult Tangent(double theParam, double theTol) const; - - //! Compute curvature at given parameter. - Standard_EXPORT GeomProp::CurvatureResult Curvature(double theParam, double theTol) const; - - //! Compute normal at given parameter. - Standard_EXPORT GeomProp::NormalResult Normal(double theParam, double theTol) const; - - //! Compute centre of curvature at given parameter. - Standard_EXPORT GeomProp::CentreResult CentreOfCurvature(double theParam, double theTol) const; - - //! Find curvature extrema using numeric root-finding. - Standard_EXPORT GeomProp::CurveAnalysis FindCurvatureExtrema() const; - - //! Find inflection points using numeric root-finding. - Standard_EXPORT GeomProp::CurveAnalysis FindInflections() const; - -private: - const Adaptor3d_Curve* myAdaptor; - GeomProp::CurveDerivOrder myRequestedOrder; - mutable GeomProp::CurveCache myCache; - occ::handle myCurve; //!< Geometry handle (handle path) - std::optional myDomain; //!< Optional parameter domain -}; - -#endif // _GeomProp_OtherCurve_HeaderFile diff --git a/src/ModelingData/TKG3d/GeomProp/GeomProp_OtherSurface.cxx b/src/ModelingData/TKG3d/GeomProp/GeomProp_OtherSurface.cxx deleted file mode 100644 index 986665f3ab..0000000000 --- a/src/ModelingData/TKG3d/GeomProp/GeomProp_OtherSurface.cxx +++ /dev/null @@ -1,84 +0,0 @@ -// 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 -#include - -//================================================================================================= - -GeomProp::SurfaceNormalResult GeomProp_OtherSurface::Normal(const double theU, - const double theV, - const double theTol) const -{ - if (!mySurface.IsNull()) - { - return GeomProp_SurfaceAnalysisTools::EvaluateNormalCached(mySurface.get(), - theU, - theV, - theTol, - myRequestedOrder, - myCache); - } - return GeomProp_SurfaceAnalysisTools::EvaluateNormalCached(myAdaptor, - theU, - theV, - theTol, - myRequestedOrder, - myCache); -} - -//================================================================================================= - -GeomProp::SurfaceCurvatureResult GeomProp_OtherSurface::Curvatures(const double theU, - const double theV, - const double theTol) const -{ - if (!mySurface.IsNull()) - { - return GeomProp_SurfaceAnalysisTools::EvaluateCurvaturesCached(mySurface.get(), - theU, - theV, - theTol, - myRequestedOrder, - myCache); - } - return GeomProp_SurfaceAnalysisTools::EvaluateCurvaturesCached(myAdaptor, - theU, - theV, - theTol, - myRequestedOrder, - myCache); -} - -//================================================================================================= - -GeomProp::MeanGaussianResult GeomProp_OtherSurface::MeanGaussian(const double theU, - const double theV, - const double theTol) const -{ - if (!mySurface.IsNull()) - { - return GeomProp_SurfaceAnalysisTools::EvaluateMeanGaussianCached(mySurface.get(), - theU, - theV, - theTol, - myRequestedOrder, - myCache); - } - return GeomProp_SurfaceAnalysisTools::EvaluateMeanGaussianCached(myAdaptor, - theU, - theV, - theTol, - myRequestedOrder, - myCache); -} diff --git a/src/ModelingData/TKG3d/GeomProp/GeomProp_OtherSurface.hxx b/src/ModelingData/TKG3d/GeomProp/GeomProp_OtherSurface.hxx deleted file mode 100644 index 7b06392460..0000000000 --- a/src/ModelingData/TKG3d/GeomProp/GeomProp_OtherSurface.hxx +++ /dev/null @@ -1,100 +0,0 @@ -// 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. - -#ifndef _GeomProp_OtherSurface_HeaderFile -#define _GeomProp_OtherSurface_HeaderFile - -#include -#include -#include -#include - -#include - -//! @brief Fallback local differential properties for any surface type. -//! -//! Uses adaptor D1/D2 methods or Geom_Surface D1/D2 for property computation. -//! -//! Can be constructed from an Adaptor3d_Surface pointer -//! or a occ::handle. When constructed from a handle, no adaptor is created. -class GeomProp_OtherSurface -{ -public: - DEFINE_STANDARD_ALLOC - - //! Constructor with adaptor pointer (non-owning). - //! @param theAdaptor the surface adaptor (must not be null) - GeomProp_OtherSurface( - const Adaptor3d_Surface* theAdaptor, - GeomProp::SurfaceDerivOrder theOrder = GeomProp::SurfaceDerivOrder::Curvature) - : myAdaptor(theAdaptor), - myRequestedOrder(theOrder) - { - } - - //! Constructor from geometry handle. - //! @param theSurface the 3D surface geometry - //! @param theDomain optional parameter domain (for trimmed surfaces) - GeomProp_OtherSurface( - const occ::handle& theSurface, - const std::optional& theDomain = std::nullopt, - GeomProp::SurfaceDerivOrder theOrder = GeomProp::SurfaceDerivOrder::Curvature) - : myAdaptor(nullptr), - myRequestedOrder(theOrder), - mySurface(theSurface), - myDomain(theDomain) - { - } - - //! Non-copyable and non-movable. - GeomProp_OtherSurface(const GeomProp_OtherSurface&) = delete; - GeomProp_OtherSurface& operator=(const GeomProp_OtherSurface&) = delete; - GeomProp_OtherSurface(GeomProp_OtherSurface&&) = delete; - GeomProp_OtherSurface& operator=(GeomProp_OtherSurface&&) = delete; - - //! Sets the derivative caching order. - void SetDerivOrder(GeomProp::SurfaceDerivOrder theOrder) { myRequestedOrder = theOrder; } - - //! Returns the derivative caching order. - GeomProp::SurfaceDerivOrder DerivOrder() const { return myRequestedOrder; } - - //! Returns the adaptor pointer (nullptr when constructed from handle). - const Adaptor3d_Surface* Adaptor() const { return myAdaptor; } - - //! Returns pointer to underlying geometry, or nullptr if constructed from adaptor. - const Geom_Surface* Geometry() const { return mySurface.get(); } - - //! Compute surface normal at given parameter. - Standard_EXPORT GeomProp::SurfaceNormalResult Normal(double theU, - double theV, - double theTol) const; - - //! Compute principal curvatures at given parameter. - Standard_EXPORT GeomProp::SurfaceCurvatureResult Curvatures(double theU, - double theV, - double theTol) const; - - //! Compute mean and Gaussian curvatures at given parameter. - Standard_EXPORT GeomProp::MeanGaussianResult MeanGaussian(double theU, - double theV, - double theTol) const; - -private: - const Adaptor3d_Surface* myAdaptor; - GeomProp::SurfaceDerivOrder myRequestedOrder; - mutable GeomProp::SurfaceCache myCache; - occ::handle mySurface; //!< Geometry handle (handle path) - std::optional myDomain; //!< Optional parameter domain -}; - -#endif // _GeomProp_OtherSurface_HeaderFile diff --git a/src/ModelingData/TKG3d/GeomProp/GeomProp_Parabola.cxx b/src/ModelingData/TKG3d/GeomProp/GeomProp_Parabola.cxx deleted file mode 100644 index 0c4fbafd44..0000000000 --- a/src/ModelingData/TKG3d/GeomProp/GeomProp_Parabola.cxx +++ /dev/null @@ -1,139 +0,0 @@ -// 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 - -//================================================================================================= - -GeomProp::TangentResult GeomProp_Parabola::Tangent(const double theParam, const double theTol) const -{ - if (myCurve.IsNull() && myAdaptor == nullptr) - { - return {{}, false}; - } - gp_Pnt aPnt; - gp_Vec aD1, aD2, aD3; - if (!myCurve.IsNull()) - { - myCurve->D3(theParam, aPnt, aD1, aD2, aD3); - } - else - { - myAdaptor->D3(theParam, aPnt, aD1, aD2, aD3); - } - return GeomProp::ComputeTangent(aD1, aD2, aD3, theTol); -} - -//================================================================================================= - -GeomProp::CurvatureResult GeomProp_Parabola::Curvature(const double theParam, - const double theTol) const -{ - if (myCurve.IsNull() && myAdaptor == nullptr) - { - return {0.0, false, false}; - } - gp_Pnt aPnt; - gp_Vec aD1, aD2; - if (!myCurve.IsNull()) - { - myCurve->D2(theParam, aPnt, aD1, aD2); - } - else - { - myAdaptor->D2(theParam, aPnt, aD1, aD2); - } - return GeomProp::ComputeCurvature(aD1, aD2, theTol); -} - -//================================================================================================= - -GeomProp::NormalResult GeomProp_Parabola::Normal(const double theParam, const double theTol) const -{ - if (myCurve.IsNull() && myAdaptor == nullptr) - { - return {{}, false}; - } - gp_Pnt aPnt; - gp_Vec aD1, aD2; - if (!myCurve.IsNull()) - { - myCurve->D2(theParam, aPnt, aD1, aD2); - } - else - { - myAdaptor->D2(theParam, aPnt, aD1, aD2); - } - return GeomProp::ComputeNormal(aD1, aD2, theTol); -} - -//================================================================================================= - -GeomProp::CentreResult GeomProp_Parabola::CentreOfCurvature(const double theParam, - const double theTol) const -{ - if (myCurve.IsNull() && myAdaptor == nullptr) - { - return {{}, false}; - } - gp_Pnt aPnt; - gp_Vec aD1, aD2; - if (!myCurve.IsNull()) - { - myCurve->D2(theParam, aPnt, aD1, aD2); - } - else - { - myAdaptor->D2(theParam, aPnt, aD1, aD2); - } - return GeomProp::ComputeCentreOfCurvature(aPnt, aD1, aD2, theTol); -} - -//================================================================================================= - -GeomProp::CurveAnalysis GeomProp_Parabola::FindCurvatureExtrema() const -{ - GeomProp::CurveAnalysis aResult; - aResult.IsDone = true; - - if (myCurve.IsNull() && myAdaptor == nullptr) - { - aResult.IsDone = false; - return aResult; - } - - double aUFirst, aULast; - if (myDomain.has_value()) - { - aUFirst = myDomain->First; - aULast = myDomain->Last; - } - else if (myAdaptor != nullptr) - { - aUFirst = myAdaptor->FirstParameter(); - aULast = myAdaptor->LastParameter(); - } - else - { - aUFirst = myCurve->FirstParameter(); - aULast = myCurve->LastParameter(); - } - - // Parabola has maximum |curvature| at parameter 0 (vertex). - if (aUFirst <= 0.0 && aULast >= 0.0) - { - aResult.Points.Append({0.0, GeomProp::CIType::MinCurvature}); - } - - return aResult; -} diff --git a/src/ModelingData/TKG3d/GeomProp/GeomProp_Parabola.hxx b/src/ModelingData/TKG3d/GeomProp/GeomProp_Parabola.hxx deleted file mode 100644 index 9502ec0218..0000000000 --- a/src/ModelingData/TKG3d/GeomProp/GeomProp_Parabola.hxx +++ /dev/null @@ -1,103 +0,0 @@ -// 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. - -#ifndef _GeomProp_Parabola_HeaderFile -#define _GeomProp_Parabola_HeaderFile - -#include -#include -#include -#include -#include - -#include - -//! @brief Local differential properties for a 3D parabola. -//! -//! A parabola has a single curvature extremum (maximum |curvature|) at parameter 0 -//! (the vertex). No inflection points exist. -//! -//! Can be constructed from either a GeomAdaptor_Curve pointer or a occ::handle. -//! When constructed from a handle, no adaptor is created. -class GeomProp_Parabola -{ -public: - DEFINE_STANDARD_ALLOC - - //! Constructor with adaptor pointer (non-owning). - //! @param theAdaptor the 3D curve adaptor (must wrap a parabola, must not be null) - GeomProp_Parabola(const GeomAdaptor_Curve* theAdaptor, - GeomProp::CurveDerivOrder theOrder = GeomProp::CurveDerivOrder::Undefined) - : myAdaptor(theAdaptor) - { - (void)theOrder; - } - - //! Constructor from geometry handle. - //! @param theCurve the 3D parabola geometry - //! @param theDomain optional parameter domain (for trimmed curves) - GeomProp_Parabola(const occ::handle& theCurve, - const std::optional& theDomain = std::nullopt, - GeomProp::CurveDerivOrder theOrder = GeomProp::CurveDerivOrder::Undefined) - : myAdaptor(nullptr), - myCurve(theCurve), - myDomain(theDomain) - { - (void)theOrder; - } - - //! Non-copyable and non-movable. - GeomProp_Parabola(const GeomProp_Parabola&) = delete; - GeomProp_Parabola& operator=(const GeomProp_Parabola&) = delete; - GeomProp_Parabola(GeomProp_Parabola&&) = delete; - GeomProp_Parabola& operator=(GeomProp_Parabola&&) = delete; - - //! Sets the derivative caching order (no-op for analytical curves). - void SetDerivOrder(GeomProp::CurveDerivOrder) {} - - //! Returns the derivative caching order (always Undefined for analytical curves). - GeomProp::CurveDerivOrder DerivOrder() const { return GeomProp::CurveDerivOrder::Undefined; } - - //! Returns the adaptor pointer (nullptr when constructed from handle). - const GeomAdaptor_Curve* Adaptor() const { return myAdaptor; } - - //! Returns pointer to underlying geometry, or nullptr if constructed from adaptor. - const Geom_Curve* Geometry() const { return myCurve.get(); } - - //! Compute tangent at given parameter. - Standard_EXPORT GeomProp::TangentResult Tangent(double theParam, double theTol) const; - - //! Compute curvature at given parameter. - Standard_EXPORT GeomProp::CurvatureResult Curvature(double theParam, double theTol) const; - - //! Compute normal at given parameter. - Standard_EXPORT GeomProp::NormalResult Normal(double theParam, double theTol) const; - - //! Compute centre of curvature at given parameter. - Standard_EXPORT GeomProp::CentreResult CentreOfCurvature(double theParam, double theTol) const; - - //! Find curvature extrema on the parabola. - //! Single extremum at parameter 0 (the vertex), if within parameter range. - Standard_EXPORT GeomProp::CurveAnalysis FindCurvatureExtrema() const; - - //! Find inflection points on the parabola. - //! A parabola has no inflection points. - GeomProp::CurveAnalysis FindInflections() const { return {{}, true}; } - -private: - const GeomAdaptor_Curve* myAdaptor; //!< Non-owning adaptor pointer (adaptor path) - occ::handle myCurve; //!< Geometry handle (handle path) - std::optional myDomain; //!< Optional parameter domain -}; - -#endif // _GeomProp_Parabola_HeaderFile diff --git a/src/ModelingData/TKG3d/GeomProp/GeomProp_Plane.hxx b/src/ModelingData/TKG3d/GeomProp/GeomProp_Plane.hxx deleted file mode 100644 index ab031fd1e3..0000000000 --- a/src/ModelingData/TKG3d/GeomProp/GeomProp_Plane.hxx +++ /dev/null @@ -1,137 +0,0 @@ -// 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. - -#ifndef _GeomProp_Plane_HeaderFile -#define _GeomProp_Plane_HeaderFile - -#include -#include -#include -#include - -#include - -//! @brief Local differential properties for a plane surface. -//! -//! Trivial implementation: constant normal, zero curvatures everywhere. -//! All properties are computed analytically without numerical evaluation. -//! -//! Can be constructed from either a GeomAdaptor_Surface pointer or a occ::handle. -//! When constructed from a handle, no adaptor is created. -class GeomProp_Plane -{ -public: - DEFINE_STANDARD_ALLOC - - //! Constructor with adaptor pointer (non-owning). - //! @param theAdaptor the surface adaptor (must not be null) - GeomProp_Plane(const GeomAdaptor_Surface* theAdaptor, - GeomProp::SurfaceDerivOrder theOrder = GeomProp::SurfaceDerivOrder::Undefined) - : myAdaptor(theAdaptor), - myPosition(theAdaptor->Plane().Position()) - { - (void)theOrder; - } - - //! Constructor from geometry handle. - //! @param theSurface the 3D plane geometry - //! @param theDomain optional parameter domain (unused for plane) - GeomProp_Plane(const occ::handle& theSurface, - const std::optional& theDomain = std::nullopt, - GeomProp::SurfaceDerivOrder theOrder = GeomProp::SurfaceDerivOrder::Undefined) - : myAdaptor(nullptr), - mySurface(theSurface), - myPosition(occ::down_cast(theSurface)->Pln().Position()), - myDomain(theDomain) - { - (void)theOrder; - } - - //! Non-copyable and non-movable. - GeomProp_Plane(const GeomProp_Plane&) = delete; - GeomProp_Plane& operator=(const GeomProp_Plane&) = delete; - GeomProp_Plane(GeomProp_Plane&&) = delete; - GeomProp_Plane& operator=(GeomProp_Plane&&) = delete; - - //! Sets the derivative caching order (no-op for analytical surfaces). - void SetDerivOrder(GeomProp::SurfaceDerivOrder) {} - - //! Returns the derivative caching order (always Undefined for analytical surfaces). - GeomProp::SurfaceDerivOrder DerivOrder() const { return GeomProp::SurfaceDerivOrder::Undefined; } - - //! Returns the adaptor pointer (nullptr when constructed from handle). - const GeomAdaptor_Surface* Adaptor() const { return myAdaptor; } - - //! Returns pointer to underlying geometry, or nullptr if constructed from adaptor. - const Geom_Surface* Geometry() const { return mySurface.get(); } - - //! Compute surface normal. Constant for a plane. - //! Uses D1U x D1V cross product to ensure correct sign for flipped planes. - GeomProp::SurfaceNormalResult Normal(double theU, double theV, double theTol) const - { - gp_Pnt aPnt; - gp_Vec aD1U, aD1V; - if (!mySurface.IsNull()) - { - mySurface->D1(theU, theV, aPnt, aD1U, aD1V); - } - else if (myAdaptor != nullptr) - { - myAdaptor->D1(theU, theV, aPnt, aD1U, aD1V); - } - else - { - return {{}, false}; - } - return GeomProp::ComputeSurfaceNormal(aD1U, aD1V, theTol); - } - - //! Compute principal curvatures. Both are zero for a plane. - GeomProp::SurfaceCurvatureResult Curvatures(double /*theU*/, - double /*theV*/, - double /*theTol*/) const - { - if (mySurface.IsNull() && myAdaptor == nullptr) - { - return {}; - } - GeomProp::SurfaceCurvatureResult aResult; - aResult.MinCurvature = 0.0; - aResult.MaxCurvature = 0.0; - aResult.MinDirection = myPosition.XDirection(); - aResult.MaxDirection = myPosition.YDirection(); - aResult.IsDefined = true; - aResult.IsUmbilic = true; - return aResult; - } - - //! Compute mean and Gaussian curvatures. Both are zero for a plane. - GeomProp::MeanGaussianResult MeanGaussian(double /*theU*/, - double /*theV*/, - double /*theTol*/) const - { - if (mySurface.IsNull() && myAdaptor == nullptr) - { - return {}; - } - return {0.0, 0.0, true}; - } - -private: - const GeomAdaptor_Surface* myAdaptor; - occ::handle mySurface; //!< Geometry handle (handle path) - gp_Ax3 myPosition; //!< Cached plane position - std::optional myDomain; //!< Optional parameter domain -}; - -#endif // _GeomProp_Plane_HeaderFile diff --git a/src/ModelingData/TKG3d/GeomProp/GeomProp_Sphere.hxx b/src/ModelingData/TKG3d/GeomProp/GeomProp_Sphere.hxx deleted file mode 100644 index 75cf0782d1..0000000000 --- a/src/ModelingData/TKG3d/GeomProp/GeomProp_Sphere.hxx +++ /dev/null @@ -1,142 +0,0 @@ -// 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. - -#ifndef _GeomProp_Sphere_HeaderFile -#define _GeomProp_Sphere_HeaderFile - -#include -#include -#include - -#include - -//! @brief Local differential properties for a spherical surface. -//! -//! Analytical implementation: constant curvature 1/R, umbilic everywhere. -//! Both principal curvatures equal 1/R. -//! -//! Can be constructed from either a GeomAdaptor_Surface pointer or a occ::handle. -//! When constructed from a handle, no adaptor is created. -class GeomProp_Sphere -{ -public: - DEFINE_STANDARD_ALLOC - - //! Constructor with adaptor pointer (non-owning). - //! @param theAdaptor the surface adaptor (must not be null) - GeomProp_Sphere(const GeomAdaptor_Surface* theAdaptor, - GeomProp::SurfaceDerivOrder theOrder = GeomProp::SurfaceDerivOrder::Undefined) - : myAdaptor(theAdaptor) - { - (void)theOrder; - } - - //! Constructor from geometry handle. - //! @param theSurface the 3D spherical surface geometry - //! @param theDomain optional parameter domain (for trimmed surfaces) - GeomProp_Sphere(const occ::handle& theSurface, - const std::optional& theDomain = std::nullopt, - GeomProp::SurfaceDerivOrder theOrder = GeomProp::SurfaceDerivOrder::Undefined) - : myAdaptor(nullptr), - mySurface(theSurface), - myDomain(theDomain) - { - (void)theOrder; - } - - //! Non-copyable and non-movable. - GeomProp_Sphere(const GeomProp_Sphere&) = delete; - GeomProp_Sphere& operator=(const GeomProp_Sphere&) = delete; - GeomProp_Sphere(GeomProp_Sphere&&) = delete; - GeomProp_Sphere& operator=(GeomProp_Sphere&&) = delete; - - //! Sets the derivative caching order (no-op for analytical surfaces). - void SetDerivOrder(GeomProp::SurfaceDerivOrder) {} - - //! Returns the derivative caching order (always Undefined for analytical surfaces). - GeomProp::SurfaceDerivOrder DerivOrder() const { return GeomProp::SurfaceDerivOrder::Undefined; } - - //! Returns the adaptor pointer (nullptr when constructed from handle). - const GeomAdaptor_Surface* Adaptor() const { return myAdaptor; } - - //! Returns pointer to underlying geometry, or nullptr if constructed from adaptor. - const Geom_Surface* Geometry() const { return mySurface.get(); } - - //! Compute surface normal at given (U, V) parameter. - //! For a sphere, the normal is radially outward from the center. - GeomProp::SurfaceNormalResult Normal(double theU, double theV, double theTol) const - { - gp_Pnt aPnt; - gp_Vec aD1U, aD1V; - if (!mySurface.IsNull()) - { - mySurface->D1(theU, theV, aPnt, aD1U, aD1V); - } - else if (myAdaptor != nullptr) - { - myAdaptor->D1(theU, theV, aPnt, aD1U, aD1V); - } - else - { - return {{}, false}; - } - return GeomProp::ComputeSurfaceNormal(aD1U, aD1V, theTol); - } - - //! Compute principal curvatures using fundamental forms for correct sign convention. - GeomProp::SurfaceCurvatureResult Curvatures(double theU, double theV, double theTol) const - { - gp_Pnt aPnt; - gp_Vec aD1U, aD1V, aD2U, aD2V, aD2UV; - if (!mySurface.IsNull()) - { - mySurface->D2(theU, theV, aPnt, aD1U, aD1V, aD2U, aD2V, aD2UV); - } - else if (myAdaptor != nullptr) - { - myAdaptor->D2(theU, theV, aPnt, aD1U, aD1V, aD2U, aD2V, aD2UV); - } - else - { - return {}; - } - return GeomProp::ComputeSurfaceCurvatures(aD1U, aD1V, aD2U, aD2V, aD2UV, theTol); - } - - //! Compute mean and Gaussian curvatures using fundamental forms for correct sign convention. - GeomProp::MeanGaussianResult MeanGaussian(double theU, double theV, double theTol) const - { - gp_Pnt aPnt; - gp_Vec aD1U, aD1V, aD2U, aD2V, aD2UV; - if (!mySurface.IsNull()) - { - mySurface->D2(theU, theV, aPnt, aD1U, aD1V, aD2U, aD2V, aD2UV); - } - else if (myAdaptor != nullptr) - { - myAdaptor->D2(theU, theV, aPnt, aD1U, aD1V, aD2U, aD2V, aD2UV); - } - else - { - return {}; - } - return GeomProp::ComputeMeanGaussian(aD1U, aD1V, aD2U, aD2V, aD2UV, theTol); - } - -private: - const GeomAdaptor_Surface* myAdaptor; - occ::handle mySurface; //!< Geometry handle (handle path) - std::optional myDomain; //!< Optional parameter domain -}; - -#endif // _GeomProp_Sphere_HeaderFile diff --git a/src/ModelingData/TKG3d/GeomProp/GeomProp_Surface.cxx b/src/ModelingData/TKG3d/GeomProp/GeomProp_Surface.cxx deleted file mode 100644 index 9c3394b5b9..0000000000 --- a/src/ModelingData/TKG3d/GeomProp/GeomProp_Surface.cxx +++ /dev/null @@ -1,329 +0,0 @@ -// 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 - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -//================================================================================================= - -GeomProp_Surface::GeomProp_Surface(const Adaptor3d_Surface& theSurface, - const GeomProp::SurfaceDerivOrder theOrder) - : myEvaluator(std::monostate{}), - mySurfaceType(GeomAbs_OtherSurface) -{ - initialization(theSurface, theOrder); -} - -//================================================================================================= - -GeomProp_Surface::GeomProp_Surface(const occ::handle& theSurface, - const GeomProp::SurfaceDerivOrder theOrder) - : myEvaluator(std::monostate{}), - mySurfaceType(GeomAbs_OtherSurface) -{ - initialization(theSurface, theOrder); -} - -//================================================================================================= - -void GeomProp_Surface::initialization(const Adaptor3d_Surface& theSurface, - const GeomProp::SurfaceDerivOrder theOrder) -{ - if (theSurface.IsKind(STANDARD_TYPE(GeomAdaptor_TransformedSurface))) - { - // Extract the transformed adaptor (carries both geometry and domain) and re-initialize. - const GeomAdaptor_TransformedSurface& aTransformed = - static_cast(theSurface); - initialization(aTransformed.AdaptorSurfaceTransformed(), theOrder); - return; - } - - if (theSurface.IsKind(STANDARD_TYPE(GeomAdaptor_Surface))) - { - const GeomAdaptor_Surface& aGeomAdaptor = static_cast(theSurface); - if (!aGeomAdaptor.Surface().IsNull()) - { - // Dispatch specialized evaluators directly from the GeomAdaptor. - myOwnedAdaptor.Nullify(); - mySurfaceType = aGeomAdaptor.GetType(); - switch (mySurfaceType) - { - case GeomAbs_Plane: - myEvaluator.emplace(&aGeomAdaptor, theOrder); - break; - case GeomAbs_Cylinder: - myEvaluator.emplace(&aGeomAdaptor, theOrder); - break; - case GeomAbs_Cone: - myEvaluator.emplace(&aGeomAdaptor, theOrder); - break; - case GeomAbs_Sphere: - myEvaluator.emplace(&aGeomAdaptor, theOrder); - break; - case GeomAbs_Torus: - myEvaluator.emplace(&aGeomAdaptor, theOrder); - break; - case GeomAbs_BezierSurface: - myEvaluator.emplace(&aGeomAdaptor, theOrder); - break; - case GeomAbs_BSplineSurface: - myEvaluator.emplace(&aGeomAdaptor, theOrder); - break; - case GeomAbs_SurfaceOfRevolution: - myEvaluator.emplace(&aGeomAdaptor, theOrder); - break; - case GeomAbs_SurfaceOfExtrusion: - myEvaluator.emplace(&aGeomAdaptor, theOrder); - break; - case GeomAbs_OffsetSurface: - myEvaluator.emplace(&aGeomAdaptor, theOrder); - break; - default: - myEvaluator.emplace(&theSurface, theOrder); - break; - } - return; - } - } - - // Non-Geom adaptor or empty surface handle: use OtherSurface with adaptor pointer. - myOwnedAdaptor.Nullify(); - mySurfaceType = theSurface.GetType(); - myEvaluator.emplace(&theSurface, theOrder); -} - -//================================================================================================= - -void GeomProp_Surface::initialization(const occ::handle& theSurface, - const GeomProp::SurfaceDerivOrder theOrder) -{ - if (theSurface.IsNull()) - { - myOwnedAdaptor.Nullify(); - myEvaluator.emplace(); - mySurfaceType = GeomAbs_OtherSurface; - return; - } - - // No adaptor creation for the handle path. - myOwnedAdaptor.Nullify(); - - // Unwrap RectangularTrimmedSurface to basis surface + optional SurfaceDomain. - occ::handle aBasis = theSurface; - std::optional aDomain; - if (aBasis->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface))) - { - double aU1, aU2, aV1, aV2; - occ::down_cast(aBasis)->Bounds(aU1, aU2, aV1, aV2); - aDomain = GeomProp::SurfaceDomain{aU1, aU2, aV1, aV2}; - aBasis = occ::down_cast(aBasis)->BasisSurface(); - } - - // Type detection using DynamicType() - extracted once to avoid repeated virtual calls. - const occ::handle& aType = aBasis->DynamicType(); - if (aType == STANDARD_TYPE(Geom_Plane)) - { - mySurfaceType = GeomAbs_Plane; - myEvaluator.emplace(aBasis, aDomain, theOrder); - } - else if (aType == STANDARD_TYPE(Geom_CylindricalSurface)) - { - mySurfaceType = GeomAbs_Cylinder; - myEvaluator.emplace(aBasis, aDomain, theOrder); - } - else if (aType == STANDARD_TYPE(Geom_ConicalSurface)) - { - mySurfaceType = GeomAbs_Cone; - myEvaluator.emplace(aBasis, aDomain, theOrder); - } - else if (aType == STANDARD_TYPE(Geom_SphericalSurface)) - { - mySurfaceType = GeomAbs_Sphere; - myEvaluator.emplace(aBasis, aDomain, theOrder); - } - else if (aType == STANDARD_TYPE(Geom_ToroidalSurface)) - { - mySurfaceType = GeomAbs_Torus; - myEvaluator.emplace(aBasis, aDomain, theOrder); - } - else if (aType == STANDARD_TYPE(Geom_BezierSurface)) - { - mySurfaceType = GeomAbs_BezierSurface; - myEvaluator.emplace(aBasis, aDomain, theOrder); - } - else if (aType == STANDARD_TYPE(Geom_BSplineSurface)) - { - mySurfaceType = GeomAbs_BSplineSurface; - myEvaluator.emplace(aBasis, aDomain, theOrder); - } - else if (aType == STANDARD_TYPE(Geom_SurfaceOfRevolution)) - { - mySurfaceType = GeomAbs_SurfaceOfRevolution; - myEvaluator.emplace(aBasis, aDomain, theOrder); - } - else if (aType == STANDARD_TYPE(Geom_SurfaceOfLinearExtrusion)) - { - mySurfaceType = GeomAbs_SurfaceOfExtrusion; - myEvaluator.emplace(aBasis, aDomain, theOrder); - } - else if (aType == STANDARD_TYPE(Geom_OffsetSurface)) - { - mySurfaceType = GeomAbs_OffsetSurface; - myEvaluator.emplace(aBasis, aDomain, theOrder); - } - else - { - mySurfaceType = GeomAbs_OtherSurface; - myEvaluator.emplace(aBasis, aDomain, theOrder); - } -} - -//================================================================================================= - -void GeomProp_Surface::SetDerivOrder(const GeomProp::SurfaceDerivOrder theOrder) -{ - std::visit( - [theOrder](auto& theEval) { - using T = std::decay_t; - if constexpr (!std::is_same_v) - { - theEval.SetDerivOrder(theOrder); - } - }, - myEvaluator); -} - -//================================================================================================= - -GeomProp::SurfaceDerivOrder GeomProp_Surface::DerivOrder() const -{ - return std::visit( - [](const auto& theEval) -> GeomProp::SurfaceDerivOrder { - using T = std::decay_t; - if constexpr (std::is_same_v) - { - return GeomProp::SurfaceDerivOrder::Undefined; - } - else - { - return theEval.DerivOrder(); - } - }, - myEvaluator); -} - -//================================================================================================= - -const Adaptor3d_Surface* GeomProp_Surface::Adaptor() const -{ - if (!myOwnedAdaptor.IsNull()) - { - return myOwnedAdaptor.get(); - } - return nullptr; -} - -//================================================================================================= - -const Geom_Surface* GeomProp_Surface::Geometry() const -{ - return std::visit( - [](const auto& theEval) -> const Geom_Surface* { - using T = std::decay_t; - if constexpr (std::is_same_v) - { - return nullptr; - } - else - { - return theEval.Geometry(); - } - }, - myEvaluator); -} - -//================================================================================================= - -GeomProp::SurfaceNormalResult GeomProp_Surface::Normal(const double theU, - const double theV, - const double theTol) const -{ - return std::visit( - [theU, theV, theTol](const auto& theEval) -> GeomProp::SurfaceNormalResult { - using T = std::decay_t; - if constexpr (std::is_same_v) - { - return {{}, false}; - } - else - { - return theEval.Normal(theU, theV, theTol); - } - }, - myEvaluator); -} - -//================================================================================================= - -GeomProp::SurfaceCurvatureResult GeomProp_Surface::Curvatures(const double theU, - const double theV, - const double theTol) const -{ - return std::visit( - [theU, theV, theTol](const auto& theEval) -> GeomProp::SurfaceCurvatureResult { - using T = std::decay_t; - if constexpr (std::is_same_v) - { - return {}; - } - else - { - return theEval.Curvatures(theU, theV, theTol); - } - }, - myEvaluator); -} - -//================================================================================================= - -GeomProp::MeanGaussianResult GeomProp_Surface::MeanGaussian(const double theU, - const double theV, - const double theTol) const -{ - return std::visit( - [theU, theV, theTol](const auto& theEval) -> GeomProp::MeanGaussianResult { - using T = std::decay_t; - if constexpr (std::is_same_v) - { - return {}; - } - else - { - return theEval.MeanGaussian(theU, theV, theTol); - } - }, - myEvaluator); -} diff --git a/src/ModelingData/TKG3d/GeomProp/GeomProp_Surface.hxx b/src/ModelingData/TKG3d/GeomProp/GeomProp_Surface.hxx deleted file mode 100644 index b717901760..0000000000 --- a/src/ModelingData/TKG3d/GeomProp/GeomProp_Surface.hxx +++ /dev/null @@ -1,171 +0,0 @@ -// 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. - -#ifndef _GeomProp_Surface_HeaderFile -#define _GeomProp_Surface_HeaderFile - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -//! @brief Unified local differential property evaluator for any 3D surface. -//! -//! Uses std::variant for compile-time type safety and zero heap allocation -//! for the evaluator itself. Automatically detects surface type from -//! Adaptor3d_Surface or Geom_Surface and dispatches to the appropriate -//! specialized evaluator. -//! -//! Supported surface types with optimized evaluation: -//! - Plane: Trivial (constant normal, zero curvatures) -//! - Cylinder: Constant principal curvatures (0 and 1/R) -//! - Cone: Analytical curvatures (vary along meridian) -//! - Sphere: Constant curvature 1/R, umbilic -//! - Torus: Analytical curvatures (vary along meridian) -//! - BezierSurface: Numeric from derivatives -//! - BSplineSurface: Numeric from derivatives -//! - SurfaceOfRevolution: Numeric from derivatives -//! - SurfaceOfExtrusion: Numeric from derivatives -//! - OffsetSurface: Numeric from derivatives -//! - Other: Fallback using adaptor derivatives -//! -//! Usage: -//! @code -//! GeomProp_Surface aProp(myGeomSurface); -//! GeomProp::SurfaceCurvatureResult aCurv = aProp.Curvatures(0.5, 0.5, Precision::Confusion()); -//! if (aCurv.IsDefined) -//! { -//! double aMinK = aCurv.MinCurvature; -//! double aMaxK = aCurv.MaxCurvature; -//! } -//! @endcode -class GeomProp_Surface -{ -public: - DEFINE_STANDARD_ALLOC - - //! Variant type holding all possible 3D surface property evaluators. - using EvaluatorVariant = std::variant; - - //! Construct from 3D adaptor reference (auto-detects surface type). - //! For GeomAdaptor_Surface, extracts underlying Geom_Surface for optimized evaluation. - //! @param[in] theSurface 3D surface adaptor reference - //! @param[in] theOrder derivative caching order - Standard_EXPORT GeomProp_Surface( - const Adaptor3d_Surface& theSurface, - GeomProp::SurfaceDerivOrder theOrder = GeomProp::SurfaceDerivOrder::Curvature); - - //! Construct from geometry handle (auto-detects surface type). - //! @param[in] theSurface 3D geometry to evaluate - //! @param[in] theOrder derivative caching order - Standard_EXPORT GeomProp_Surface( - const occ::handle& theSurface, - GeomProp::SurfaceDerivOrder theOrder = GeomProp::SurfaceDerivOrder::Curvature); - - //! Non-copyable and non-movable. - GeomProp_Surface(const GeomProp_Surface&) = delete; - GeomProp_Surface& operator=(const GeomProp_Surface&) = delete; - GeomProp_Surface(GeomProp_Surface&&) = delete; - GeomProp_Surface& operator=(GeomProp_Surface&&) = delete; - - //! Returns the detected surface type. - GeomAbs_SurfaceType GetType() const { return mySurfaceType; } - - //! Sets the derivative caching order for the active evaluator. - //! Only effective for non-analytical surface types. - Standard_EXPORT void SetDerivOrder(GeomProp::SurfaceDerivOrder theOrder); - - //! Returns the derivative caching order of the active evaluator. - Standard_EXPORT GeomProp::SurfaceDerivOrder DerivOrder() const; - - //! Returns the stored adaptor pointer, or null if not initialized. - Standard_EXPORT const Adaptor3d_Surface* Adaptor() const; - - //! Returns pointer to underlying geometry, or nullptr if not available. - //! When constructed from a handle, trimmed surfaces are unwrapped to their basis surface. - Standard_EXPORT const Geom_Surface* Geometry() const; - - //! Compute surface normal at given (U, V) parameter. - //! @param[in] theU U parameter on the surface - //! @param[in] theV V parameter on the surface - //! @param[in] theTol linear tolerance - //! @return surface normal result with validity flag - Standard_EXPORT GeomProp::SurfaceNormalResult Normal(double theU, - double theV, - double theTol) const; - - //! Compute principal curvatures at given (U, V) parameter. - //! @param[in] theU U parameter on the surface - //! @param[in] theV V parameter on the surface - //! @param[in] theTol linear tolerance - //! @return curvature result with principal curvatures and directions - Standard_EXPORT GeomProp::SurfaceCurvatureResult Curvatures(double theU, - double theV, - double theTol) const; - - //! Compute mean and Gaussian curvatures at given (U, V) parameter. - //! @param[in] theU U parameter on the surface - //! @param[in] theV V parameter on the surface - //! @param[in] theTol linear tolerance - //! @return mean and Gaussian curvature result - Standard_EXPORT GeomProp::MeanGaussianResult MeanGaussian(double theU, - double theV, - double theTol) const; - -protected: - //! Initialize from 3D adaptor reference (auto-detects surface type). - //! @param[in] theSurface 3D surface adaptor reference - //! @param[in] theOrder derivative caching order - Standard_EXPORT void initialization(const Adaptor3d_Surface& theSurface, - GeomProp::SurfaceDerivOrder theOrder); - - //! Initialize from geometry handle (auto-detects surface type). - //! @param[in] theSurface 3D geometry to evaluate - //! @param[in] theOrder derivative caching order - Standard_EXPORT void initialization(const occ::handle& theSurface, - GeomProp::SurfaceDerivOrder theOrder); - -private: - occ::handle myOwnedAdaptor; //!< Owned adaptor when lifetime must be managed. - EvaluatorVariant myEvaluator; - GeomAbs_SurfaceType mySurfaceType; -}; - -#endif // _GeomProp_Surface_HeaderFile diff --git a/src/ModelingData/TKG3d/GeomProp/GeomProp_SurfaceAnalysisTools.pxx b/src/ModelingData/TKG3d/GeomProp/GeomProp_SurfaceAnalysisTools.pxx deleted file mode 100644 index 8a6bf6dd9e..0000000000 --- a/src/ModelingData/TKG3d/GeomProp/GeomProp_SurfaceAnalysisTools.pxx +++ /dev/null @@ -1,181 +0,0 @@ -// 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. - -#ifndef GeomProp_SurfaceAnalysisTools_PHeaderFile -#define GeomProp_SurfaceAnalysisTools_PHeaderFile - -#include -#include -#include - -#include -#include -#include - -namespace GeomProp_SurfaceAnalysisTools -{ - -//! Populate surface derivative cache at the requested order. -//! Works with both Adaptor3d_Surface* and Geom_Surface*. -template -inline void EnsureSurfaceDerivatives(const SurfaceType* theSurface, - double theU, - double theV, - GeomProp::SurfaceDerivOrder theNeeded, - GeomProp::SurfaceDerivOrder theRequested, - GeomProp::SurfaceCache& theCache) -{ - if (theCache.IsValid(theU, theV) && theCache.HasOrder(theNeeded)) - { - return; - } - const int aTarget = std::max(static_cast(theRequested), static_cast(theNeeded)); - theCache.ParamU = theU; - theCache.ParamV = theV; - if (aTarget >= static_cast(GeomProp::SurfaceDerivOrder::Curvature)) - { - gp_Pnt aPnt; - gp_Vec aD1U, aD1V, aD2U, aD2V, aD2UV; - theSurface->D2(theU, theV, aPnt, aD1U, aD1V, aD2U, aD2V, aD2UV); - theCache.Data.emplace( - Geom_Surface::ResD2{aPnt, aD1U, aD1V, aD2U, aD2V, aD2UV}); - } - else - { - gp_Pnt aPnt; - gp_Vec aD1U, aD1V; - theSurface->D1(theU, theV, aPnt, aD1U, aD1V); - theCache.Data.emplace(Geom_Surface::ResD1{aPnt, aD1U, aD1V}); - } -} - -//! Evaluate surface normal using cached derivatives. -//! Works with both Adaptor3d_Surface* and Geom_Surface*. -template -inline GeomProp::SurfaceNormalResult EvaluateNormalCached(const SurfaceType* theSurface, - double theU, - double theV, - double theTol, - GeomProp::SurfaceDerivOrder theOrder, - GeomProp::SurfaceCache& theCache) -{ - if (theSurface == nullptr) - { - return {{}, false}; - } - EnsureSurfaceDerivatives(theSurface, - theU, - theV, - GeomProp::SurfaceDerivOrder::Normal, - theOrder, - theCache); - return std::visit( - [theTol](const auto& theVal) -> GeomProp::SurfaceNormalResult { - using T = std::decay_t; - if constexpr (std::is_same_v - || std::is_same_v) - { - return GeomProp::ComputeSurfaceNormal(theVal.D1U, theVal.D1V, theTol); - } - else - { - return {{}, false}; - } - }, - theCache.Data); -} - -//! Evaluate principal curvatures using cached derivatives. -//! Works with both Adaptor3d_Surface* and Geom_Surface*. -template -inline GeomProp::SurfaceCurvatureResult EvaluateCurvaturesCached( - const SurfaceType* theSurface, - double theU, - double theV, - double theTol, - GeomProp::SurfaceDerivOrder theOrder, - GeomProp::SurfaceCache& theCache) -{ - if (theSurface == nullptr) - { - return {}; - } - EnsureSurfaceDerivatives(theSurface, - theU, - theV, - GeomProp::SurfaceDerivOrder::Curvature, - theOrder, - theCache); - return std::visit( - [theTol](const auto& theVal) -> GeomProp::SurfaceCurvatureResult { - using T = std::decay_t; - if constexpr (std::is_same_v) - { - return GeomProp::ComputeSurfaceCurvatures(theVal.D1U, - theVal.D1V, - theVal.D2U, - theVal.D2V, - theVal.D2UV, - theTol); - } - else - { - return {}; - } - }, - theCache.Data); -} - -//! Evaluate mean and Gaussian curvatures using cached derivatives. -//! Works with both Adaptor3d_Surface* and Geom_Surface*. -template -inline GeomProp::MeanGaussianResult EvaluateMeanGaussianCached(const SurfaceType* theSurface, - double theU, - double theV, - double theTol, - GeomProp::SurfaceDerivOrder theOrder, - GeomProp::SurfaceCache& theCache) -{ - if (theSurface == nullptr) - { - return {}; - } - EnsureSurfaceDerivatives(theSurface, - theU, - theV, - GeomProp::SurfaceDerivOrder::Curvature, - theOrder, - theCache); - return std::visit( - [theTol](const auto& theVal) -> GeomProp::MeanGaussianResult { - using T = std::decay_t; - if constexpr (std::is_same_v) - { - return GeomProp::ComputeMeanGaussian(theVal.D1U, - theVal.D1V, - theVal.D2U, - theVal.D2V, - theVal.D2UV, - theTol); - } - else - { - return {}; - } - }, - theCache.Data); -} - -} // namespace GeomProp_SurfaceAnalysisTools - -#endif // GeomProp_SurfaceAnalysisTools_PHeaderFile diff --git a/src/ModelingData/TKG3d/GeomProp/GeomProp_SurfaceOfExtrusion.cxx b/src/ModelingData/TKG3d/GeomProp/GeomProp_SurfaceOfExtrusion.cxx deleted file mode 100644 index 73e596a8c0..0000000000 --- a/src/ModelingData/TKG3d/GeomProp/GeomProp_SurfaceOfExtrusion.cxx +++ /dev/null @@ -1,84 +0,0 @@ -// 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 -#include - -//================================================================================================= - -GeomProp::SurfaceNormalResult GeomProp_SurfaceOfExtrusion::Normal(const double theU, - const double theV, - const double theTol) const -{ - if (!mySurface.IsNull()) - { - return GeomProp_SurfaceAnalysisTools::EvaluateNormalCached(mySurface.get(), - theU, - theV, - theTol, - myRequestedOrder, - myCache); - } - return GeomProp_SurfaceAnalysisTools::EvaluateNormalCached(myAdaptor, - theU, - theV, - theTol, - myRequestedOrder, - myCache); -} - -//================================================================================================= - -GeomProp::SurfaceCurvatureResult GeomProp_SurfaceOfExtrusion::Curvatures(const double theU, - const double theV, - const double theTol) const -{ - if (!mySurface.IsNull()) - { - return GeomProp_SurfaceAnalysisTools::EvaluateCurvaturesCached(mySurface.get(), - theU, - theV, - theTol, - myRequestedOrder, - myCache); - } - return GeomProp_SurfaceAnalysisTools::EvaluateCurvaturesCached(myAdaptor, - theU, - theV, - theTol, - myRequestedOrder, - myCache); -} - -//================================================================================================= - -GeomProp::MeanGaussianResult GeomProp_SurfaceOfExtrusion::MeanGaussian(const double theU, - const double theV, - const double theTol) const -{ - if (!mySurface.IsNull()) - { - return GeomProp_SurfaceAnalysisTools::EvaluateMeanGaussianCached(mySurface.get(), - theU, - theV, - theTol, - myRequestedOrder, - myCache); - } - return GeomProp_SurfaceAnalysisTools::EvaluateMeanGaussianCached(myAdaptor, - theU, - theV, - theTol, - myRequestedOrder, - myCache); -} diff --git a/src/ModelingData/TKG3d/GeomProp/GeomProp_SurfaceOfExtrusion.hxx b/src/ModelingData/TKG3d/GeomProp/GeomProp_SurfaceOfExtrusion.hxx deleted file mode 100644 index 826aca16c8..0000000000 --- a/src/ModelingData/TKG3d/GeomProp/GeomProp_SurfaceOfExtrusion.hxx +++ /dev/null @@ -1,100 +0,0 @@ -// 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. - -#ifndef _GeomProp_SurfaceOfExtrusion_HeaderFile -#define _GeomProp_SurfaceOfExtrusion_HeaderFile - -#include -#include -#include -#include - -#include - -//! @brief Local differential properties for a surface of extrusion. -//! -//! Uses numeric evaluation from surface derivatives. -//! -//! Can be constructed from either a GeomAdaptor_Surface pointer or a occ::handle. -//! When constructed from a handle, no adaptor is created. -class GeomProp_SurfaceOfExtrusion -{ -public: - DEFINE_STANDARD_ALLOC - - //! Constructor with adaptor pointer (non-owning). - //! @param theAdaptor the surface adaptor (must not be null) - GeomProp_SurfaceOfExtrusion( - const GeomAdaptor_Surface* theAdaptor, - GeomProp::SurfaceDerivOrder theOrder = GeomProp::SurfaceDerivOrder::Curvature) - : myAdaptor(theAdaptor), - myRequestedOrder(theOrder) - { - } - - //! Constructor from geometry handle. - //! @param theSurface the 3D surface of extrusion geometry - //! @param theDomain optional parameter domain (for trimmed surfaces) - GeomProp_SurfaceOfExtrusion( - const occ::handle& theSurface, - const std::optional& theDomain = std::nullopt, - GeomProp::SurfaceDerivOrder theOrder = GeomProp::SurfaceDerivOrder::Curvature) - : myAdaptor(nullptr), - myRequestedOrder(theOrder), - mySurface(theSurface), - myDomain(theDomain) - { - } - - //! Non-copyable and non-movable. - GeomProp_SurfaceOfExtrusion(const GeomProp_SurfaceOfExtrusion&) = delete; - GeomProp_SurfaceOfExtrusion& operator=(const GeomProp_SurfaceOfExtrusion&) = delete; - GeomProp_SurfaceOfExtrusion(GeomProp_SurfaceOfExtrusion&&) = delete; - GeomProp_SurfaceOfExtrusion& operator=(GeomProp_SurfaceOfExtrusion&&) = delete; - - //! Sets the derivative caching order. - void SetDerivOrder(GeomProp::SurfaceDerivOrder theOrder) { myRequestedOrder = theOrder; } - - //! Returns the derivative caching order. - GeomProp::SurfaceDerivOrder DerivOrder() const { return myRequestedOrder; } - - //! Returns the adaptor pointer (nullptr when constructed from handle). - const GeomAdaptor_Surface* Adaptor() const { return myAdaptor; } - - //! Returns pointer to underlying geometry, or nullptr if constructed from adaptor. - const Geom_Surface* Geometry() const { return mySurface.get(); } - - //! Compute surface normal at given parameter. - Standard_EXPORT GeomProp::SurfaceNormalResult Normal(double theU, - double theV, - double theTol) const; - - //! Compute principal curvatures at given parameter. - Standard_EXPORT GeomProp::SurfaceCurvatureResult Curvatures(double theU, - double theV, - double theTol) const; - - //! Compute mean and Gaussian curvatures at given parameter. - Standard_EXPORT GeomProp::MeanGaussianResult MeanGaussian(double theU, - double theV, - double theTol) const; - -private: - const GeomAdaptor_Surface* myAdaptor; - GeomProp::SurfaceDerivOrder myRequestedOrder; - mutable GeomProp::SurfaceCache myCache; - occ::handle mySurface; //!< Geometry handle (handle path) - std::optional myDomain; //!< Optional parameter domain -}; - -#endif // _GeomProp_SurfaceOfExtrusion_HeaderFile diff --git a/src/ModelingData/TKG3d/GeomProp/GeomProp_SurfaceOfRevolution.cxx b/src/ModelingData/TKG3d/GeomProp/GeomProp_SurfaceOfRevolution.cxx deleted file mode 100644 index 32010191ed..0000000000 --- a/src/ModelingData/TKG3d/GeomProp/GeomProp_SurfaceOfRevolution.cxx +++ /dev/null @@ -1,84 +0,0 @@ -// 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 -#include - -//================================================================================================= - -GeomProp::SurfaceNormalResult GeomProp_SurfaceOfRevolution::Normal(const double theU, - const double theV, - const double theTol) const -{ - if (!mySurface.IsNull()) - { - return GeomProp_SurfaceAnalysisTools::EvaluateNormalCached(mySurface.get(), - theU, - theV, - theTol, - myRequestedOrder, - myCache); - } - return GeomProp_SurfaceAnalysisTools::EvaluateNormalCached(myAdaptor, - theU, - theV, - theTol, - myRequestedOrder, - myCache); -} - -//================================================================================================= - -GeomProp::SurfaceCurvatureResult GeomProp_SurfaceOfRevolution::Curvatures(const double theU, - const double theV, - const double theTol) const -{ - if (!mySurface.IsNull()) - { - return GeomProp_SurfaceAnalysisTools::EvaluateCurvaturesCached(mySurface.get(), - theU, - theV, - theTol, - myRequestedOrder, - myCache); - } - return GeomProp_SurfaceAnalysisTools::EvaluateCurvaturesCached(myAdaptor, - theU, - theV, - theTol, - myRequestedOrder, - myCache); -} - -//================================================================================================= - -GeomProp::MeanGaussianResult GeomProp_SurfaceOfRevolution::MeanGaussian(const double theU, - const double theV, - const double theTol) const -{ - if (!mySurface.IsNull()) - { - return GeomProp_SurfaceAnalysisTools::EvaluateMeanGaussianCached(mySurface.get(), - theU, - theV, - theTol, - myRequestedOrder, - myCache); - } - return GeomProp_SurfaceAnalysisTools::EvaluateMeanGaussianCached(myAdaptor, - theU, - theV, - theTol, - myRequestedOrder, - myCache); -} diff --git a/src/ModelingData/TKG3d/GeomProp/GeomProp_SurfaceOfRevolution.hxx b/src/ModelingData/TKG3d/GeomProp/GeomProp_SurfaceOfRevolution.hxx deleted file mode 100644 index a8bf2496ad..0000000000 --- a/src/ModelingData/TKG3d/GeomProp/GeomProp_SurfaceOfRevolution.hxx +++ /dev/null @@ -1,100 +0,0 @@ -// 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. - -#ifndef _GeomProp_SurfaceOfRevolution_HeaderFile -#define _GeomProp_SurfaceOfRevolution_HeaderFile - -#include -#include -#include -#include - -#include - -//! @brief Local differential properties for a surface of revolution. -//! -//! Uses numeric evaluation from surface derivatives. -//! -//! Can be constructed from either a GeomAdaptor_Surface pointer or a occ::handle. -//! When constructed from a handle, no adaptor is created. -class GeomProp_SurfaceOfRevolution -{ -public: - DEFINE_STANDARD_ALLOC - - //! Constructor with adaptor pointer (non-owning). - //! @param theAdaptor the surface adaptor (must not be null) - GeomProp_SurfaceOfRevolution( - const GeomAdaptor_Surface* theAdaptor, - GeomProp::SurfaceDerivOrder theOrder = GeomProp::SurfaceDerivOrder::Curvature) - : myAdaptor(theAdaptor), - myRequestedOrder(theOrder) - { - } - - //! Constructor from geometry handle. - //! @param theSurface the 3D surface of revolution geometry - //! @param theDomain optional parameter domain (for trimmed surfaces) - GeomProp_SurfaceOfRevolution( - const occ::handle& theSurface, - const std::optional& theDomain = std::nullopt, - GeomProp::SurfaceDerivOrder theOrder = GeomProp::SurfaceDerivOrder::Curvature) - : myAdaptor(nullptr), - myRequestedOrder(theOrder), - mySurface(theSurface), - myDomain(theDomain) - { - } - - //! Non-copyable and non-movable. - GeomProp_SurfaceOfRevolution(const GeomProp_SurfaceOfRevolution&) = delete; - GeomProp_SurfaceOfRevolution& operator=(const GeomProp_SurfaceOfRevolution&) = delete; - GeomProp_SurfaceOfRevolution(GeomProp_SurfaceOfRevolution&&) = delete; - GeomProp_SurfaceOfRevolution& operator=(GeomProp_SurfaceOfRevolution&&) = delete; - - //! Sets the derivative caching order. - void SetDerivOrder(GeomProp::SurfaceDerivOrder theOrder) { myRequestedOrder = theOrder; } - - //! Returns the derivative caching order. - GeomProp::SurfaceDerivOrder DerivOrder() const { return myRequestedOrder; } - - //! Returns the adaptor pointer (nullptr when constructed from handle). - const GeomAdaptor_Surface* Adaptor() const { return myAdaptor; } - - //! Returns pointer to underlying geometry, or nullptr if constructed from adaptor. - const Geom_Surface* Geometry() const { return mySurface.get(); } - - //! Compute surface normal at given parameter. - Standard_EXPORT GeomProp::SurfaceNormalResult Normal(double theU, - double theV, - double theTol) const; - - //! Compute principal curvatures at given parameter. - Standard_EXPORT GeomProp::SurfaceCurvatureResult Curvatures(double theU, - double theV, - double theTol) const; - - //! Compute mean and Gaussian curvatures at given parameter. - Standard_EXPORT GeomProp::MeanGaussianResult MeanGaussian(double theU, - double theV, - double theTol) const; - -private: - const GeomAdaptor_Surface* myAdaptor; - GeomProp::SurfaceDerivOrder myRequestedOrder; - mutable GeomProp::SurfaceCache myCache; - occ::handle mySurface; //!< Geometry handle (handle path) - std::optional myDomain; //!< Optional parameter domain -}; - -#endif // _GeomProp_SurfaceOfRevolution_HeaderFile diff --git a/src/ModelingData/TKG3d/GeomProp/GeomProp_Torus.cxx b/src/ModelingData/TKG3d/GeomProp/GeomProp_Torus.cxx deleted file mode 100644 index 0154eef094..0000000000 --- a/src/ModelingData/TKG3d/GeomProp/GeomProp_Torus.cxx +++ /dev/null @@ -1,83 +0,0 @@ -// 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 - -//================================================================================================= - -GeomProp::SurfaceNormalResult GeomProp_Torus::Normal(const double theU, - const double theV, - const double theTol) const -{ - gp_Pnt aPnt; - gp_Vec aD1U, aD1V; - if (!mySurface.IsNull()) - { - mySurface->D1(theU, theV, aPnt, aD1U, aD1V); - } - else if (myAdaptor != nullptr) - { - myAdaptor->D1(theU, theV, aPnt, aD1U, aD1V); - } - else - { - return {{}, false}; - } - return GeomProp::ComputeSurfaceNormal(aD1U, aD1V, theTol); -} - -//================================================================================================= - -GeomProp::SurfaceCurvatureResult GeomProp_Torus::Curvatures(const double theU, - const double theV, - const double theTol) const -{ - gp_Pnt aPnt; - gp_Vec aD1U, aD1V, aD2U, aD2V, aD2UV; - if (!mySurface.IsNull()) - { - mySurface->D2(theU, theV, aPnt, aD1U, aD1V, aD2U, aD2V, aD2UV); - } - else if (myAdaptor != nullptr) - { - myAdaptor->D2(theU, theV, aPnt, aD1U, aD1V, aD2U, aD2V, aD2UV); - } - else - { - return {}; - } - return GeomProp::ComputeSurfaceCurvatures(aD1U, aD1V, aD2U, aD2V, aD2UV, theTol); -} - -//================================================================================================= - -GeomProp::MeanGaussianResult GeomProp_Torus::MeanGaussian(const double theU, - const double theV, - const double theTol) const -{ - gp_Pnt aPnt; - gp_Vec aD1U, aD1V, aD2U, aD2V, aD2UV; - if (!mySurface.IsNull()) - { - mySurface->D2(theU, theV, aPnt, aD1U, aD1V, aD2U, aD2V, aD2UV); - } - else if (myAdaptor != nullptr) - { - myAdaptor->D2(theU, theV, aPnt, aD1U, aD1V, aD2U, aD2V, aD2UV); - } - else - { - return {}; - } - return GeomProp::ComputeMeanGaussian(aD1U, aD1V, aD2U, aD2V, aD2UV, theTol); -} diff --git a/src/ModelingData/TKG3d/GeomProp/GeomProp_Torus.hxx b/src/ModelingData/TKG3d/GeomProp/GeomProp_Torus.hxx deleted file mode 100644 index dad57ab983..0000000000 --- a/src/ModelingData/TKG3d/GeomProp/GeomProp_Torus.hxx +++ /dev/null @@ -1,99 +0,0 @@ -// 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. - -#ifndef _GeomProp_Torus_HeaderFile -#define _GeomProp_Torus_HeaderFile - -#include -#include -#include -#include - -#include - -//! @brief Local differential properties for a toroidal surface. -//! -//! Uses analytical formulas. Curvature varies along the meridian (V direction): -//! - k1 = 1/r (constant, along the minor circle direction) -//! - k2 = cos(V) / (R + r*cos(V)) (varies, along the major circle direction) -//! where R is the major radius and r is the minor radius. -//! -//! Can be constructed from either a GeomAdaptor_Surface pointer or a occ::handle. -//! When constructed from a handle, no adaptor is created. -class GeomProp_Torus -{ -public: - DEFINE_STANDARD_ALLOC - - //! Constructor with adaptor pointer (non-owning). - //! @param theAdaptor the surface adaptor (must not be null) - GeomProp_Torus(const GeomAdaptor_Surface* theAdaptor, - GeomProp::SurfaceDerivOrder theOrder = GeomProp::SurfaceDerivOrder::Undefined) - : myAdaptor(theAdaptor) - { - (void)theOrder; - } - - //! Constructor from geometry handle. - //! @param theSurface the 3D toroidal surface geometry - //! @param theDomain optional parameter domain (for trimmed surfaces) - GeomProp_Torus(const occ::handle& theSurface, - const std::optional& theDomain = std::nullopt, - GeomProp::SurfaceDerivOrder theOrder = GeomProp::SurfaceDerivOrder::Undefined) - : myAdaptor(nullptr), - mySurface(theSurface), - myDomain(theDomain) - { - (void)theOrder; - } - - //! Non-copyable and non-movable. - GeomProp_Torus(const GeomProp_Torus&) = delete; - GeomProp_Torus& operator=(const GeomProp_Torus&) = delete; - GeomProp_Torus(GeomProp_Torus&&) = delete; - GeomProp_Torus& operator=(GeomProp_Torus&&) = delete; - - //! Sets the derivative caching order (no-op for analytical surfaces). - void SetDerivOrder(GeomProp::SurfaceDerivOrder) {} - - //! Returns the derivative caching order (always Undefined for analytical surfaces). - GeomProp::SurfaceDerivOrder DerivOrder() const { return GeomProp::SurfaceDerivOrder::Undefined; } - - //! Returns the adaptor pointer (nullptr when constructed from handle). - const GeomAdaptor_Surface* Adaptor() const { return myAdaptor; } - - //! Returns pointer to underlying geometry, or nullptr if constructed from adaptor. - const Geom_Surface* Geometry() const { return mySurface.get(); } - - //! Compute surface normal at given parameter. - Standard_EXPORT GeomProp::SurfaceNormalResult Normal(double theU, - double theV, - double theTol) const; - - //! Compute principal curvatures at given parameter. - Standard_EXPORT GeomProp::SurfaceCurvatureResult Curvatures(double theU, - double theV, - double theTol) const; - - //! Compute mean and Gaussian curvatures at given parameter. - Standard_EXPORT GeomProp::MeanGaussianResult MeanGaussian(double theU, - double theV, - double theTol) const; - -private: - const GeomAdaptor_Surface* myAdaptor; - occ::handle mySurface; //!< Geometry handle (handle path) - std::optional myDomain; //!< Optional parameter domain -}; - -#endif // _GeomProp_Torus_HeaderFile diff --git a/src/ModelingData/TKG3d/PACKAGES.cmake b/src/ModelingData/TKG3d/PACKAGES.cmake index 42dfc77f2f..537e911b71 100644 --- a/src/ModelingData/TKG3d/PACKAGES.cmake +++ b/src/ModelingData/TKG3d/PACKAGES.cmake @@ -11,5 +11,4 @@ set(OCCT_TKG3d_LIST_OF_PACKAGES GProp GeomHash GeomEval - GeomProp )