mirror of
https://github.com/Open-Cascade-SAS/OCCT.git
synced 2026-09-06 04:37:55 +08:00
Modeling Data - Add GeomProp package for modern 3D curve and surface differential properties (#1115)
Add new GeomProp package to TKG3d following the same C++17 std::variant-dispatched pattern as Geom2dProp (TKG2d) for computing local differential properties of 3D curves and surfaces without exceptions. New package GeomProp (TKG3d) provides: - GeomProp: Result structs (TangentResult, CurvatureResult, NormalResult, CentreResult, CurveAnalysis for curves; SurfaceNormalResult, SurfaceCurvatureResult, MeanGaussianResult for surfaces) and geometry-agnostic free functions for property computation from derivatives. - GeomProp_Curve: Unified variant dispatcher that auto-detects curve type from Geom_Curve or Adaptor3d_Curve and delegates to specialized evaluators. Owns the GeomAdaptor_Curve handle and passes non-owning raw pointers to per-geometry classes. - GeomProp_Surface: Unified variant dispatcher that auto-detects surface type from Geom_Surface or Adaptor3d_Surface and delegates to specialized evaluators. Owns the GeomAdaptor_Surface handle with non-owning raw pointers. - Per-geometry curve evaluators (9 types matching GeomAbs_CurveType): Line (header-only), Circle (header-only), Ellipse, Hyperbola, Parabola, BezierCurve, BSplineCurve, OffsetCurve, OtherCurve. - Per-geometry surface evaluators (11 types matching GeomAbs_SurfaceType): Plane (header-only), Cylinder (header-only), Sphere (header-only), Cone, Torus, BezierSurface, BSplineSurface, SurfaceOfRevolution, SurfaceOfExtrusion, OffsetSurface, OtherSurface. - Surface curvatures computed via first/second fundamental forms with correct sign convention consistent with surface normal orientation. Principal directions derived from the shape operator (Weingarten map). 48 GTests covering free functions, curve/surface dispatchers, cross-validation against GeomLProp_CLProps (8 curve types) and GeomLProp_SLProps (6 surface types).
This commit is contained in:
@@ -44,4 +44,7 @@ set(OCCT_TKG3d_GTests_FILES
|
||||
GeomGridEval_Torus_Test.cxx
|
||||
GeomHash_CurveHasher_Test.cxx
|
||||
GeomHash_SurfaceHasher_Test.cxx
|
||||
GeomProp_Test.cxx
|
||||
GeomProp_VsCLProps_Test.cxx
|
||||
GeomProp_VsSLProps_Test.cxx
|
||||
)
|
||||
|
||||
@@ -0,0 +1,523 @@
|
||||
// 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 <Geom_BezierCurve.hxx>
|
||||
#include <Geom_BSplineCurve.hxx>
|
||||
#include <Geom_BSplineSurface.hxx>
|
||||
#include <Geom_Circle.hxx>
|
||||
#include <Geom_ConicalSurface.hxx>
|
||||
#include <Geom_CylindricalSurface.hxx>
|
||||
#include <Geom_Ellipse.hxx>
|
||||
#include <Geom_Hyperbola.hxx>
|
||||
#include <Geom_Line.hxx>
|
||||
#include <Geom_OffsetCurve.hxx>
|
||||
#include <Geom_Parabola.hxx>
|
||||
#include <Geom_Plane.hxx>
|
||||
#include <Geom_SphericalSurface.hxx>
|
||||
#include <Geom_ToroidalSurface.hxx>
|
||||
#include <Geom_TrimmedCurve.hxx>
|
||||
#include <GeomProp.hxx>
|
||||
#include <GeomProp_Curve.hxx>
|
||||
#include <GeomProp_Surface.hxx>
|
||||
#include <gp_Ax2.hxx>
|
||||
#include <gp_Ax3.hxx>
|
||||
#include <gp_Circ.hxx>
|
||||
#include <gp_Dir.hxx>
|
||||
#include <gp_Elips.hxx>
|
||||
#include <gp_Hypr.hxx>
|
||||
#include <gp_Lin.hxx>
|
||||
#include <gp_Parab.hxx>
|
||||
#include <gp_Pnt.hxx>
|
||||
#include <gp_Vec.hxx>
|
||||
#include <NCollection_Array1.hxx>
|
||||
#include <Precision.hxx>
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
// ============================================================================
|
||||
// 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, UninitializedState)
|
||||
{
|
||||
GeomProp_Curve aProp;
|
||||
EXPECT_FALSE(aProp.IsInitialized());
|
||||
}
|
||||
|
||||
TEST(GeomPropCurveTest, InitializeFromNullHandle)
|
||||
{
|
||||
GeomProp_Curve aProp;
|
||||
occ::handle<Geom_Curve> aNullCurve;
|
||||
aProp.Initialize(aNullCurve);
|
||||
EXPECT_FALSE(aProp.IsInitialized());
|
||||
}
|
||||
|
||||
TEST(GeomPropCurveTest, Line_ZeroCurvature)
|
||||
{
|
||||
occ::handle<Geom_Line> aLine = new Geom_Line(gp_Pnt(0, 0, 0), gp_Dir(1, 0, 0));
|
||||
GeomProp_Curve aProp;
|
||||
aProp.Initialize(aLine);
|
||||
ASSERT_TRUE(aProp.IsInitialized());
|
||||
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<Geom_Circle> aCircle = new Geom_Circle(aCirc);
|
||||
|
||||
GeomProp_Curve aProp;
|
||||
aProp.Initialize(aCircle);
|
||||
ASSERT_TRUE(aProp.IsInitialized());
|
||||
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<Geom_Ellipse> anEllipse = new Geom_Ellipse(anElips);
|
||||
|
||||
GeomProp_Curve aProp;
|
||||
aProp.Initialize(anEllipse);
|
||||
ASSERT_TRUE(aProp.IsInitialized());
|
||||
|
||||
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<Geom_Hyperbola> aHyperbola = new Geom_Hyperbola(anHypr);
|
||||
|
||||
GeomProp_Curve aProp;
|
||||
aProp.Initialize(aHyperbola);
|
||||
ASSERT_TRUE(aProp.IsInitialized());
|
||||
|
||||
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<Geom_Parabola> aParabola = new Geom_Parabola(aParab);
|
||||
|
||||
GeomProp_Curve aProp;
|
||||
aProp.Initialize(aParabola);
|
||||
ASSERT_TRUE(aProp.IsInitialized());
|
||||
|
||||
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<Geom_Circle> aCircle = new Geom_Circle(aCirc);
|
||||
|
||||
GeomProp_Curve aProp;
|
||||
aProp.Initialize(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<Geom_Circle> aCircle = new Geom_Circle(aCirc);
|
||||
|
||||
GeomProp_Curve aProp;
|
||||
aProp.Initialize(aCircle);
|
||||
const GeomProp::CurveAnalysis aResult = aProp.FindInflections();
|
||||
ASSERT_TRUE(aResult.IsDone);
|
||||
EXPECT_EQ(aResult.Points.Length(), 0);
|
||||
}
|
||||
|
||||
TEST(GeomPropCurveTest, BezierCurve_Inflections)
|
||||
{
|
||||
NCollection_Array1<gp_Pnt> 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<Geom_BezierCurve> aBezier = new Geom_BezierCurve(aPoles);
|
||||
|
||||
GeomProp_Curve aProp;
|
||||
aProp.Initialize(aBezier);
|
||||
ASSERT_TRUE(aProp.IsInitialized());
|
||||
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<Geom_Line> aLine = new Geom_Line(gp_Pnt(0, 0, 0), gp_Dir(0, 1, 0));
|
||||
GeomProp_Curve aProp;
|
||||
aProp.Initialize(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<Geom_Circle> aCircle = new Geom_Circle(aCirc);
|
||||
|
||||
GeomProp_Curve aProp;
|
||||
aProp.Initialize(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<Geom_Circle> aCircle = new Geom_Circle(aCirc);
|
||||
|
||||
GeomProp_Curve aProp;
|
||||
aProp.Initialize(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, UninitializedState)
|
||||
{
|
||||
GeomProp_Surface aProp;
|
||||
EXPECT_FALSE(aProp.IsInitialized());
|
||||
}
|
||||
|
||||
TEST(GeomPropSurfaceTest, InitializeFromNullHandle)
|
||||
{
|
||||
GeomProp_Surface aProp;
|
||||
occ::handle<Geom_Surface> aNullSurf;
|
||||
aProp.Initialize(aNullSurf);
|
||||
EXPECT_FALSE(aProp.IsInitialized());
|
||||
}
|
||||
|
||||
TEST(GeomPropSurfaceTest, Plane_ZeroCurvatures)
|
||||
{
|
||||
occ::handle<Geom_Plane> aPlane = new Geom_Plane(gp_Ax3());
|
||||
|
||||
GeomProp_Surface aProp;
|
||||
aProp.Initialize(aPlane);
|
||||
ASSERT_TRUE(aProp.IsInitialized());
|
||||
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<Geom_Plane> aPlane = new Geom_Plane(gp_Ax3());
|
||||
|
||||
GeomProp_Surface aProp;
|
||||
aProp.Initialize(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<Geom_Plane> aPlane = new Geom_Plane(gp_Ax3());
|
||||
|
||||
GeomProp_Surface aProp;
|
||||
aProp.Initialize(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<Geom_SphericalSurface> aSphere = new Geom_SphericalSurface(gp_Ax3(), aRadius);
|
||||
|
||||
GeomProp_Surface aProp;
|
||||
aProp.Initialize(aSphere);
|
||||
ASSERT_TRUE(aProp.IsInitialized());
|
||||
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<Geom_SphericalSurface> aSphere = new Geom_SphericalSurface(gp_Ax3(), aRadius);
|
||||
|
||||
GeomProp_Surface aProp;
|
||||
aProp.Initialize(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<Geom_CylindricalSurface> aCyl = new Geom_CylindricalSurface(gp_Ax3(), aRadius);
|
||||
|
||||
GeomProp_Surface aProp;
|
||||
aProp.Initialize(aCyl);
|
||||
ASSERT_TRUE(aProp.IsInitialized());
|
||||
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<Geom_CylindricalSurface> aCyl = new Geom_CylindricalSurface(gp_Ax3(), aRadius);
|
||||
|
||||
GeomProp_Surface aProp;
|
||||
aProp.Initialize(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<Geom_ConicalSurface> aCone = new Geom_ConicalSurface(anAx3, M_PI / 6.0, 5.0);
|
||||
|
||||
GeomProp_Surface aProp;
|
||||
aProp.Initialize(aCone);
|
||||
ASSERT_TRUE(aProp.IsInitialized());
|
||||
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<Geom_ToroidalSurface> aTorus = new Geom_ToroidalSurface(gp_Ax3(), aMajor, aMinor);
|
||||
|
||||
GeomProp_Surface aProp;
|
||||
aProp.Initialize(aTorus);
|
||||
ASSERT_TRUE(aProp.IsInitialized());
|
||||
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
|
||||
}
|
||||
@@ -0,0 +1,248 @@
|
||||
// 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 <Geom_BezierCurve.hxx>
|
||||
#include <Geom_BSplineCurve.hxx>
|
||||
#include <Geom_Circle.hxx>
|
||||
#include <Geom_Ellipse.hxx>
|
||||
#include <Geom_Hyperbola.hxx>
|
||||
#include <Geom_Line.hxx>
|
||||
#include <Geom_OffsetCurve.hxx>
|
||||
#include <Geom_Parabola.hxx>
|
||||
#include <GeomLProp_CLProps.hxx>
|
||||
#include <GeomProp.hxx>
|
||||
#include <GeomProp_Curve.hxx>
|
||||
#include <gp_Ax2.hxx>
|
||||
#include <gp_Circ.hxx>
|
||||
#include <gp_Dir.hxx>
|
||||
#include <gp_Elips.hxx>
|
||||
#include <gp_Hypr.hxx>
|
||||
#include <gp_Parab.hxx>
|
||||
#include <NCollection_Array1.hxx>
|
||||
#include <Precision.hxx>
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
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<Geom_Curve>& theCurve, const double theParam)
|
||||
{
|
||||
GeomProp_Curve aProp;
|
||||
aProp.Initialize(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<Geom_Curve>& theCurve, const double theParam)
|
||||
{
|
||||
GeomProp_Curve aProp;
|
||||
aProp.Initialize(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<Geom_Curve>& theCurve, const double theParam)
|
||||
{
|
||||
GeomProp_Curve aProp;
|
||||
aProp.Initialize(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<Geom_Curve>& theCurve, const double theParam)
|
||||
{
|
||||
GeomProp_Curve aProp;
|
||||
aProp.Initialize(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<Geom_Curve>& 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<Geom_Line> 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<Geom_Circle> 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<Geom_Ellipse> 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<Geom_Hyperbola> 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<Geom_Parabola> aParabola = new Geom_Parabola(aParab);
|
||||
compareAll(aParabola, -5.0, 5.0);
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Bezier
|
||||
// ============================================================================
|
||||
|
||||
TEST(GeomProp_VsCLPropsTest, BezierCubic)
|
||||
{
|
||||
NCollection_Array1<gp_Pnt> 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<Geom_BezierCurve> aBezier = new Geom_BezierCurve(aPoles);
|
||||
compareAll(aBezier, 0.0, 1.0);
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// BSpline
|
||||
// ============================================================================
|
||||
|
||||
TEST(GeomProp_VsCLPropsTest, BSplineCubic)
|
||||
{
|
||||
NCollection_Array1<gp_Pnt> 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<double> aKnots(1, 4);
|
||||
aKnots(1) = 0.0;
|
||||
aKnots(2) = 0.33;
|
||||
aKnots(3) = 0.66;
|
||||
aKnots(4) = 1.0;
|
||||
|
||||
NCollection_Array1<int> aMults(1, 4);
|
||||
aMults(1) = 4;
|
||||
aMults(2) = 1;
|
||||
aMults(3) = 1;
|
||||
aMults(4) = 4;
|
||||
|
||||
occ::handle<Geom_BSplineCurve> 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<Geom_Circle> aCircle = new Geom_Circle(aCirc);
|
||||
occ::handle<Geom_OffsetCurve> anOffset = new Geom_OffsetCurve(aCircle, 2.0, gp_Dir(0, 0, 1));
|
||||
compareAll(anOffset, 0.0, 2.0 * M_PI);
|
||||
}
|
||||
@@ -0,0 +1,213 @@
|
||||
// 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 <Geom_BSplineSurface.hxx>
|
||||
#include <NCollection_Array2.hxx>
|
||||
#include <Geom_ConicalSurface.hxx>
|
||||
#include <Geom_CylindricalSurface.hxx>
|
||||
#include <Geom_Plane.hxx>
|
||||
#include <Geom_SphericalSurface.hxx>
|
||||
#include <Geom_ToroidalSurface.hxx>
|
||||
#include <GeomLProp_SLProps.hxx>
|
||||
#include <GeomProp.hxx>
|
||||
#include <GeomProp_Surface.hxx>
|
||||
#include <gp_Ax3.hxx>
|
||||
#include <NCollection_Array1.hxx>
|
||||
#include <Precision.hxx>
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
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<Geom_Surface>& theSurf, const double theU, const double theV)
|
||||
{
|
||||
GeomProp_Surface aProp;
|
||||
aProp.Initialize(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<Geom_Surface>& theSurf,
|
||||
const double theU,
|
||||
const double theV)
|
||||
{
|
||||
GeomProp_Surface aProp;
|
||||
aProp.Initialize(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<Geom_Surface>& theSurf,
|
||||
const double theU,
|
||||
const double theV)
|
||||
{
|
||||
GeomProp_Surface aProp;
|
||||
aProp.Initialize(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<Geom_Surface>& 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<Geom_Plane> aPlane = new Geom_Plane(gp_Ax3());
|
||||
compareAllSurface(aPlane, -5.0, 5.0, -5.0, 5.0);
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Sphere
|
||||
// ============================================================================
|
||||
|
||||
TEST(GeomProp_VsSLPropsTest, Sphere)
|
||||
{
|
||||
occ::handle<Geom_SphericalSurface> 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<Geom_CylindricalSurface> 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<Geom_ConicalSurface> 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<Geom_ToroidalSurface> 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<gp_Pnt> aPoles(1, 4, 1, 4);
|
||||
NCollection_Array1<double> aUKnots(1, 2), aVKnots(1, 2);
|
||||
NCollection_Array1<int> 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<Geom_BSplineSurface> aSurf =
|
||||
new Geom_BSplineSurface(aPoles, aUKnots, aVKnots, aUMults, aVMults, 3, 3);
|
||||
|
||||
compareAllSurface(aSurf, 0.0, 1.0, 0.0, 1.0, 4, 4);
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
# 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_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
|
||||
)
|
||||
@@ -0,0 +1,315 @@
|
||||
// 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.hxx>
|
||||
|
||||
#include <cmath>
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
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::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);
|
||||
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);
|
||||
|
||||
// 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 {};
|
||||
}
|
||||
|
||||
// Mean curvature: H = (EN - 2FM + GL) / (2 * det)
|
||||
const double aH = (aE * aN_ - 2.0 * aF * aM + aG * aL) / (2.0 * aDet);
|
||||
|
||||
// Gaussian curvature: K = (LN - M^2) / det
|
||||
const double aK = (aL * aN_ - aM * aM) / aDet;
|
||||
|
||||
// Principal curvatures from: k^2 - 2Hk + K = 0
|
||||
const double aDiscriminant = aH * aH - aK;
|
||||
|
||||
SurfaceCurvatureResult aResult;
|
||||
aResult.IsDefined = true;
|
||||
|
||||
if (aDiscriminant <= theTol * theTol)
|
||||
{
|
||||
// Umbilic point: both principal curvatures are equal.
|
||||
aResult.MinCurvature = aH;
|
||||
aResult.MaxCurvature = aH;
|
||||
aResult.IsUmbilic = true;
|
||||
// At umbilic points, directions are undefined - use U and V directions.
|
||||
if (theD1U.SquareMagnitude() > theTol * theTol)
|
||||
{
|
||||
aResult.MinDirection = gp_Dir(theD1U);
|
||||
}
|
||||
if (theD1V.SquareMagnitude() > theTol * theTol)
|
||||
{
|
||||
aResult.MaxDirection = gp_Dir(theD1V);
|
||||
}
|
||||
return aResult;
|
||||
}
|
||||
|
||||
const double aSqrtDisc = std::sqrt(std::max(aDiscriminant, 0.0));
|
||||
const double aK1 = aH - aSqrtDisc; // min curvature
|
||||
const double aK2 = aH + aSqrtDisc; // max curvature
|
||||
|
||||
aResult.MinCurvature = aK1;
|
||||
aResult.MaxCurvature = aK2;
|
||||
aResult.IsUmbilic = false;
|
||||
|
||||
// Compute principal directions from the shape operator (Weingarten map).
|
||||
// For each principal curvature k, the principal direction (a, b) satisfies:
|
||||
// (L - kE)*a + (M - kF)*b = 0
|
||||
// (M - kF)*a + (N - kG)*b = 0
|
||||
// We pick the equation with the largest coefficient to avoid division by near-zero.
|
||||
for (int i = 0; i < 2; ++i)
|
||||
{
|
||||
const double aKi = (i == 0) ? aK1 : aK2;
|
||||
const double aCoeffA = aL - aKi * aE;
|
||||
const double aCoeffB = aM - aKi * aF;
|
||||
// TODO: aCoeffC is always equal to aCoeffB (symmetric shape operator matrix).
|
||||
// Consider removing the redundant variable and using aCoeffB directly.
|
||||
const double aCoeffC = aM - aKi * aF;
|
||||
const double aCoeffD = aN_ - aKi * aG;
|
||||
|
||||
gp_Vec aDir;
|
||||
if (std::abs(aCoeffA) > std::abs(aCoeffD))
|
||||
{
|
||||
// From first equation: a*coeff_a + b*coeff_b = 0 => b/a = -coeff_a/coeff_b
|
||||
if (std::abs(aCoeffB) > theTol)
|
||||
{
|
||||
aDir = theD1U * (-aCoeffB) + theD1V * aCoeffA;
|
||||
}
|
||||
else
|
||||
{
|
||||
aDir = theD1V;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// From second equation: a*coeff_c + b*coeff_d = 0 => a/b = -coeff_d/coeff_c
|
||||
if (std::abs(aCoeffC) > theTol)
|
||||
{
|
||||
aDir = theD1U * aCoeffD + theD1V * (-aCoeffC);
|
||||
}
|
||||
else
|
||||
{
|
||||
aDir = theD1U;
|
||||
}
|
||||
}
|
||||
|
||||
if (aDir.SquareMagnitude() > theTol * theTol)
|
||||
{
|
||||
if (i == 0)
|
||||
{
|
||||
aResult.MinDirection = gp_Dir(aDir);
|
||||
}
|
||||
else
|
||||
{
|
||||
aResult.MaxDirection = gp_Dir(aDir);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
@@ -0,0 +1,212 @@
|
||||
// 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 <gp_Dir.hxx>
|
||||
#include <gp_Pnt.hxx>
|
||||
#include <gp_Vec.hxx>
|
||||
#include <NCollection_DynamicArray.hxx>
|
||||
#include <Standard.hxx>
|
||||
|
||||
//! @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
|
||||
{
|
||||
|
||||
// ============================================================================
|
||||
// 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<CurveSpecialPoint> 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
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// Curve free functions
|
||||
// ============================================================================
|
||||
|
||||
//! Compute tangent direction from derivative vectors.
|
||||
//! Tries D1 first; if D1 magnitude^2 <= theTol^2, tries D2, then D3.
|
||||
//! @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 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
|
||||
@@ -0,0 +1,441 @@
|
||||
// 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_BSplineCurve.hxx>
|
||||
|
||||
#include <GeomAbs_Shape.hxx>
|
||||
#include <gp.hxx>
|
||||
#include <MathRoot_Brent.hxx>
|
||||
#include <MathRoot_Multiple.hxx>
|
||||
#include <NCollection_Array1.hxx>
|
||||
#include <Precision.hxx>
|
||||
|
||||
#include <cmath>
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
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
|
||||
class FuncCurExt
|
||||
{
|
||||
public:
|
||||
FuncCurExt(const GeomAdaptor_Curve* 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);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
if (aCPMag < gp::Resolution())
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
bool IsMinKC(const double X) const
|
||||
{
|
||||
gp_Pnt aP;
|
||||
gp_Vec 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).Magnitude() / 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).Magnitude() / aV13n;
|
||||
|
||||
return std::abs(aKC) > std::abs(aKP);
|
||||
}
|
||||
|
||||
private:
|
||||
const GeomAdaptor_Curve* myCurve;
|
||||
double myEpsX;
|
||||
};
|
||||
|
||||
//! Function for finding inflection points: F = |V1 x V2| / (||V1|| * ||V2||) = 0
|
||||
class FuncCurNul
|
||||
{
|
||||
public:
|
||||
FuncCurNul(const GeomAdaptor_Curve* 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);
|
||||
|
||||
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 GeomAdaptor_Curve* myCurve;
|
||||
};
|
||||
|
||||
//! Perform numeric curvature extrema finding on a curve interval.
|
||||
void numericCurvatureExtrema(const GeomAdaptor_Curve* 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];
|
||||
MathUtils::Config aBrentCfg;
|
||||
aBrentCfg.XTolerance = Precision::PConfusion();
|
||||
aBrentCfg.FTolerance = Precision::PConfusion();
|
||||
auto 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.
|
||||
void numericInflections(const GeomAdaptor_Curve* 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.
|
||||
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<GeomProp::CurveSpecialPoint> aFiltered;
|
||||
aFiltered.Append(theResult.Points[0]);
|
||||
for (int i = 1; i < aNbPts; ++i)
|
||||
{
|
||||
bool aIsDuplicate = false;
|
||||
for (int j = static_cast<int>(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);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
GeomProp::TangentResult GeomProp_BSplineCurve::Tangent(const double theParam,
|
||||
const double theTol) const
|
||||
{
|
||||
if (myAdaptor == nullptr)
|
||||
{
|
||||
return {{}, false};
|
||||
}
|
||||
gp_Pnt aPnt;
|
||||
gp_Vec aD1, aD2, aD3;
|
||||
myAdaptor->D3(theParam, aPnt, aD1, aD2, aD3);
|
||||
return GeomProp::ComputeTangent(aD1, aD2, aD3, theTol);
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
GeomProp::CurvatureResult GeomProp_BSplineCurve::Curvature(const double theParam,
|
||||
const double theTol) const
|
||||
{
|
||||
if (myAdaptor == nullptr)
|
||||
{
|
||||
return {0.0, false, false};
|
||||
}
|
||||
gp_Pnt aPnt;
|
||||
gp_Vec aD1, aD2;
|
||||
myAdaptor->D2(theParam, aPnt, aD1, aD2);
|
||||
return GeomProp::ComputeCurvature(aD1, aD2, theTol);
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
GeomProp::NormalResult GeomProp_BSplineCurve::Normal(const double theParam,
|
||||
const double theTol) const
|
||||
{
|
||||
if (myAdaptor == nullptr)
|
||||
{
|
||||
return {{}, false};
|
||||
}
|
||||
gp_Pnt aPnt;
|
||||
gp_Vec aD1, aD2;
|
||||
myAdaptor->D2(theParam, aPnt, aD1, aD2);
|
||||
return GeomProp::ComputeNormal(aD1, aD2, theTol);
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
GeomProp::CentreResult GeomProp_BSplineCurve::CentreOfCurvature(const double theParam,
|
||||
const double theTol) const
|
||||
{
|
||||
if (myAdaptor == nullptr)
|
||||
{
|
||||
return {{}, false};
|
||||
}
|
||||
gp_Pnt aPnt;
|
||||
gp_Vec aD1, aD2;
|
||||
myAdaptor->D2(theParam, aPnt, aD1, aD2);
|
||||
return GeomProp::ComputeCentreOfCurvature(aPnt, aD1, aD2, theTol);
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
GeomProp::CurveAnalysis GeomProp_BSplineCurve::FindCurvatureExtrema() const
|
||||
{
|
||||
GeomProp::CurveAnalysis aResult;
|
||||
aResult.IsDone = true;
|
||||
|
||||
if (myAdaptor == nullptr)
|
||||
{
|
||||
aResult.IsDone = false;
|
||||
return aResult;
|
||||
}
|
||||
|
||||
if (myAdaptor->Continuity() >= GeomAbs_C3)
|
||||
{
|
||||
numericCurvatureExtrema(myAdaptor,
|
||||
myAdaptor->FirstParameter(),
|
||||
myAdaptor->LastParameter(),
|
||||
aResult);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Subdivide into C3 intervals.
|
||||
const int aNbInt = myAdaptor->NbIntervals(GeomAbs_C3);
|
||||
NCollection_Array1<double> aParams(1, aNbInt + 1);
|
||||
myAdaptor->Intervals(aParams, GeomAbs_C3);
|
||||
for (int i = 1; i <= aNbInt; ++i)
|
||||
{
|
||||
numericCurvatureExtrema(myAdaptor, aParams(i), aParams(i + 1), aResult);
|
||||
}
|
||||
const double aEpsH =
|
||||
THE_EPSILON_SCALE * (myAdaptor->LastParameter() - myAdaptor->FirstParameter());
|
||||
removeDuplicatePoints(aResult, aEpsH);
|
||||
}
|
||||
|
||||
return aResult;
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
GeomProp::CurveAnalysis GeomProp_BSplineCurve::FindInflections() const
|
||||
{
|
||||
GeomProp::CurveAnalysis aResult;
|
||||
aResult.IsDone = true;
|
||||
|
||||
if (myAdaptor == nullptr)
|
||||
{
|
||||
aResult.IsDone = false;
|
||||
return aResult;
|
||||
}
|
||||
|
||||
if (myAdaptor->Continuity() >= GeomAbs_C3)
|
||||
{
|
||||
numericInflections(myAdaptor, myAdaptor->FirstParameter(), myAdaptor->LastParameter(), aResult);
|
||||
}
|
||||
else
|
||||
{
|
||||
const int aNbInt = myAdaptor->NbIntervals(GeomAbs_C3);
|
||||
NCollection_Array1<double> aParams(1, aNbInt + 1);
|
||||
myAdaptor->Intervals(aParams, GeomAbs_C3);
|
||||
for (int i = 1; i <= aNbInt; ++i)
|
||||
{
|
||||
numericInflections(myAdaptor, aParams(i), aParams(i + 1), aResult);
|
||||
}
|
||||
removeDuplicatePoints(aResult, THE_INFLECTION_TOLERANCE);
|
||||
}
|
||||
|
||||
return aResult;
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
// 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 <GeomAdaptor_Curve.hxx>
|
||||
#include <GeomProp.hxx>
|
||||
#include <Standard.hxx>
|
||||
#include <Standard_DefineAlloc.hxx>
|
||||
|
||||
//! @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.
|
||||
//!
|
||||
//! @warning The caller must ensure that the adaptor pointer remains valid
|
||||
//! for the entire lifetime of this object. This class does not manage
|
||||
//! the adaptor's lifetime.
|
||||
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)
|
||||
: myAdaptor(theAdaptor)
|
||||
{
|
||||
}
|
||||
|
||||
//! 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;
|
||||
|
||||
//! Returns the adaptor pointer.
|
||||
const GeomAdaptor_Curve* Adaptor() const { return myAdaptor; }
|
||||
|
||||
//! 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;
|
||||
};
|
||||
|
||||
#endif // _GeomProp_BSplineCurve_HeaderFile
|
||||
@@ -0,0 +1,62 @@
|
||||
// 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_BSplineSurface.hxx>
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
GeomProp::SurfaceNormalResult GeomProp_BSplineSurface::Normal(const double theU,
|
||||
const double theV,
|
||||
const double theTol) const
|
||||
{
|
||||
if (myAdaptor == nullptr)
|
||||
{
|
||||
return {{}, false};
|
||||
}
|
||||
gp_Pnt aPnt;
|
||||
gp_Vec aD1U, aD1V;
|
||||
myAdaptor->D1(theU, theV, aPnt, aD1U, aD1V);
|
||||
return GeomProp::ComputeSurfaceNormal(aD1U, aD1V, theTol);
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
GeomProp::SurfaceCurvatureResult GeomProp_BSplineSurface::Curvatures(const double theU,
|
||||
const double theV,
|
||||
const double theTol) const
|
||||
{
|
||||
if (myAdaptor == nullptr)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
gp_Pnt aPnt;
|
||||
gp_Vec aD1U, aD1V, aD2U, aD2V, aD2UV;
|
||||
myAdaptor->D2(theU, theV, aPnt, aD1U, aD1V, aD2U, aD2V, aD2UV);
|
||||
return GeomProp::ComputeSurfaceCurvatures(aD1U, aD1V, aD2U, aD2V, aD2UV, theTol);
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
GeomProp::MeanGaussianResult GeomProp_BSplineSurface::MeanGaussian(const double theU,
|
||||
const double theV,
|
||||
const double theTol) const
|
||||
{
|
||||
if (myAdaptor == nullptr)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
gp_Pnt aPnt;
|
||||
gp_Vec aD1U, aD1V, aD2U, aD2V, aD2UV;
|
||||
myAdaptor->D2(theU, theV, aPnt, aD1U, aD1V, aD2U, aD2V, aD2UV);
|
||||
return GeomProp::ComputeMeanGaussian(aD1U, aD1V, aD2U, aD2V, aD2UV, theTol);
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
// 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 <GeomAdaptor_Surface.hxx>
|
||||
#include <GeomProp.hxx>
|
||||
#include <Standard.hxx>
|
||||
#include <Standard_DefineAlloc.hxx>
|
||||
|
||||
//! @brief Local differential properties for a B-spline surface.
|
||||
//!
|
||||
//! Uses numeric evaluation from adaptor derivatives.
|
||||
//!
|
||||
//! @warning The caller must ensure that the adaptor pointer remains valid
|
||||
//! for the entire lifetime of this object.
|
||||
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)
|
||||
: myAdaptor(theAdaptor)
|
||||
{
|
||||
}
|
||||
|
||||
//! 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;
|
||||
|
||||
//! Returns the adaptor pointer.
|
||||
const GeomAdaptor_Surface* Adaptor() const { return myAdaptor; }
|
||||
|
||||
//! 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;
|
||||
};
|
||||
|
||||
#endif // _GeomProp_BSplineSurface_HeaderFile
|
||||
@@ -0,0 +1,373 @@
|
||||
// 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_BezierCurve.hxx>
|
||||
|
||||
#include <gp.hxx>
|
||||
#include <MathRoot_Brent.hxx>
|
||||
#include <MathRoot_Multiple.hxx>
|
||||
#include <Precision.hxx>
|
||||
|
||||
#include <cmath>
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
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
|
||||
class FuncCurExt
|
||||
{
|
||||
public:
|
||||
FuncCurExt(const GeomAdaptor_Curve* 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 GeomAdaptor_Curve* myCurve;
|
||||
double myEpsX;
|
||||
};
|
||||
|
||||
//! Function for finding inflection points: F = |V1 x V2| / (||V1|| * ||V2||) = 0
|
||||
class FuncCurNul
|
||||
{
|
||||
public:
|
||||
FuncCurNul(const GeomAdaptor_Curve* 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 GeomAdaptor_Curve* myCurve;
|
||||
};
|
||||
|
||||
//! Perform numeric curvature extrema finding on a curve interval.
|
||||
void numericCurvatureExtrema(const GeomAdaptor_Curve* 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();
|
||||
auto 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.
|
||||
void numericInflections(const GeomAdaptor_Curve* 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;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
GeomProp::TangentResult GeomProp_BezierCurve::Tangent(const double theParam,
|
||||
const double theTol) const
|
||||
{
|
||||
if (myAdaptor == nullptr)
|
||||
{
|
||||
return {{}, false};
|
||||
}
|
||||
gp_Pnt aPnt;
|
||||
gp_Vec aD1, aD2, aD3;
|
||||
myAdaptor->D3(theParam, aPnt, aD1, aD2, aD3);
|
||||
return GeomProp::ComputeTangent(aD1, aD2, aD3, theTol);
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
GeomProp::CurvatureResult GeomProp_BezierCurve::Curvature(const double theParam,
|
||||
const double theTol) const
|
||||
{
|
||||
if (myAdaptor == nullptr)
|
||||
{
|
||||
return {0.0, false, false};
|
||||
}
|
||||
gp_Pnt aPnt;
|
||||
gp_Vec aD1, aD2;
|
||||
myAdaptor->D2(theParam, aPnt, aD1, aD2);
|
||||
return GeomProp::ComputeCurvature(aD1, aD2, theTol);
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
GeomProp::NormalResult GeomProp_BezierCurve::Normal(const double theParam,
|
||||
const double theTol) const
|
||||
{
|
||||
if (myAdaptor == nullptr)
|
||||
{
|
||||
return {{}, false};
|
||||
}
|
||||
gp_Pnt aPnt;
|
||||
gp_Vec aD1, aD2;
|
||||
myAdaptor->D2(theParam, aPnt, aD1, aD2);
|
||||
return GeomProp::ComputeNormal(aD1, aD2, theTol);
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
GeomProp::CentreResult GeomProp_BezierCurve::CentreOfCurvature(const double theParam,
|
||||
const double theTol) const
|
||||
{
|
||||
if (myAdaptor == nullptr)
|
||||
{
|
||||
return {{}, false};
|
||||
}
|
||||
gp_Pnt aPnt;
|
||||
gp_Vec aD1, aD2;
|
||||
myAdaptor->D2(theParam, aPnt, aD1, aD2);
|
||||
return GeomProp::ComputeCentreOfCurvature(aPnt, aD1, aD2, theTol);
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
GeomProp::CurveAnalysis GeomProp_BezierCurve::FindCurvatureExtrema() const
|
||||
{
|
||||
GeomProp::CurveAnalysis aResult;
|
||||
aResult.IsDone = true;
|
||||
|
||||
if (myAdaptor == nullptr)
|
||||
{
|
||||
aResult.IsDone = false;
|
||||
return aResult;
|
||||
}
|
||||
|
||||
numericCurvatureExtrema(myAdaptor,
|
||||
myAdaptor->FirstParameter(),
|
||||
myAdaptor->LastParameter(),
|
||||
aResult);
|
||||
return aResult;
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
GeomProp::CurveAnalysis GeomProp_BezierCurve::FindInflections() const
|
||||
{
|
||||
GeomProp::CurveAnalysis aResult;
|
||||
aResult.IsDone = true;
|
||||
|
||||
if (myAdaptor == nullptr)
|
||||
{
|
||||
aResult.IsDone = false;
|
||||
return aResult;
|
||||
}
|
||||
|
||||
numericInflections(myAdaptor, myAdaptor->FirstParameter(), myAdaptor->LastParameter(), aResult);
|
||||
return aResult;
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
// 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 <GeomAdaptor_Curve.hxx>
|
||||
#include <GeomProp.hxx>
|
||||
#include <Standard.hxx>
|
||||
#include <Standard_DefineAlloc.hxx>
|
||||
|
||||
//! @brief Local differential properties for a 3D Bezier curve.
|
||||
//!
|
||||
//! Uses numeric root-finding for curvature extrema and inflection points.
|
||||
//!
|
||||
//! @warning The caller must ensure that the adaptor pointer remains valid
|
||||
//! for the entire lifetime of this object. This class does not manage
|
||||
//! the adaptor's lifetime.
|
||||
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)
|
||||
: myAdaptor(theAdaptor)
|
||||
{
|
||||
}
|
||||
|
||||
//! 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;
|
||||
|
||||
//! Returns the adaptor pointer.
|
||||
const GeomAdaptor_Curve* Adaptor() const { return myAdaptor; }
|
||||
|
||||
//! 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;
|
||||
};
|
||||
|
||||
#endif // _GeomProp_BezierCurve_HeaderFile
|
||||
@@ -0,0 +1,62 @@
|
||||
// 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_BezierSurface.hxx>
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
GeomProp::SurfaceNormalResult GeomProp_BezierSurface::Normal(const double theU,
|
||||
const double theV,
|
||||
const double theTol) const
|
||||
{
|
||||
if (myAdaptor == nullptr)
|
||||
{
|
||||
return {{}, false};
|
||||
}
|
||||
gp_Pnt aPnt;
|
||||
gp_Vec aD1U, aD1V;
|
||||
myAdaptor->D1(theU, theV, aPnt, aD1U, aD1V);
|
||||
return GeomProp::ComputeSurfaceNormal(aD1U, aD1V, theTol);
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
GeomProp::SurfaceCurvatureResult GeomProp_BezierSurface::Curvatures(const double theU,
|
||||
const double theV,
|
||||
const double theTol) const
|
||||
{
|
||||
if (myAdaptor == nullptr)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
gp_Pnt aPnt;
|
||||
gp_Vec aD1U, aD1V, aD2U, aD2V, aD2UV;
|
||||
myAdaptor->D2(theU, theV, aPnt, aD1U, aD1V, aD2U, aD2V, aD2UV);
|
||||
return GeomProp::ComputeSurfaceCurvatures(aD1U, aD1V, aD2U, aD2V, aD2UV, theTol);
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
GeomProp::MeanGaussianResult GeomProp_BezierSurface::MeanGaussian(const double theU,
|
||||
const double theV,
|
||||
const double theTol) const
|
||||
{
|
||||
if (myAdaptor == nullptr)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
gp_Pnt aPnt;
|
||||
gp_Vec aD1U, aD1V, aD2U, aD2V, aD2UV;
|
||||
myAdaptor->D2(theU, theV, aPnt, aD1U, aD1V, aD2U, aD2V, aD2UV);
|
||||
return GeomProp::ComputeMeanGaussian(aD1U, aD1V, aD2U, aD2V, aD2UV, theTol);
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
// 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 <GeomAdaptor_Surface.hxx>
|
||||
#include <GeomProp.hxx>
|
||||
#include <Standard.hxx>
|
||||
#include <Standard_DefineAlloc.hxx>
|
||||
|
||||
//! @brief Local differential properties for a Bezier surface.
|
||||
//!
|
||||
//! Uses numeric evaluation from adaptor derivatives.
|
||||
//!
|
||||
//! @warning The caller must ensure that the adaptor pointer remains valid
|
||||
//! for the entire lifetime of this object.
|
||||
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)
|
||||
: myAdaptor(theAdaptor)
|
||||
{
|
||||
}
|
||||
|
||||
//! 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;
|
||||
|
||||
//! Returns the adaptor pointer.
|
||||
const GeomAdaptor_Surface* Adaptor() const { return myAdaptor; }
|
||||
|
||||
//! 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;
|
||||
};
|
||||
|
||||
#endif // _GeomProp_BezierSurface_HeaderFile
|
||||
@@ -0,0 +1,116 @@
|
||||
// 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 <GeomAdaptor_Curve.hxx>
|
||||
#include <GeomProp.hxx>
|
||||
#include <Standard_DefineAlloc.hxx>
|
||||
|
||||
//! @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.
|
||||
//!
|
||||
//! @warning The caller must ensure that the adaptor pointer remains valid
|
||||
//! for the entire lifetime of this object. This class does not manage
|
||||
//! the adaptor's lifetime.
|
||||
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)
|
||||
: myAdaptor(theAdaptor)
|
||||
{
|
||||
}
|
||||
|
||||
//! 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;
|
||||
|
||||
//! Returns the adaptor pointer.
|
||||
const GeomAdaptor_Curve* Adaptor() const { return myAdaptor; }
|
||||
|
||||
//! 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;
|
||||
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 / myAdaptor->Circle().Radius(), 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;
|
||||
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 {myAdaptor->Circle().Location(), 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;
|
||||
};
|
||||
|
||||
#endif // _GeomProp_Circle_HeaderFile
|
||||
@@ -0,0 +1,62 @@
|
||||
// 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_Cone.hxx>
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
GeomProp::SurfaceNormalResult GeomProp_Cone::Normal(const double theU,
|
||||
const double theV,
|
||||
const double theTol) const
|
||||
{
|
||||
if (myAdaptor == nullptr)
|
||||
{
|
||||
return {{}, false};
|
||||
}
|
||||
gp_Pnt aPnt;
|
||||
gp_Vec aD1U, aD1V;
|
||||
myAdaptor->D1(theU, theV, aPnt, aD1U, aD1V);
|
||||
return GeomProp::ComputeSurfaceNormal(aD1U, aD1V, theTol);
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
GeomProp::SurfaceCurvatureResult GeomProp_Cone::Curvatures(const double theU,
|
||||
const double theV,
|
||||
const double theTol) const
|
||||
{
|
||||
if (myAdaptor == nullptr)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
gp_Pnt aPnt;
|
||||
gp_Vec aD1U, aD1V, aD2U, aD2V, aD2UV;
|
||||
myAdaptor->D2(theU, theV, aPnt, aD1U, aD1V, aD2U, aD2V, aD2UV);
|
||||
return GeomProp::ComputeSurfaceCurvatures(aD1U, aD1V, aD2U, aD2V, aD2UV, theTol);
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
GeomProp::MeanGaussianResult GeomProp_Cone::MeanGaussian(const double theU,
|
||||
const double theV,
|
||||
const double theTol) const
|
||||
{
|
||||
if (myAdaptor == nullptr)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
gp_Pnt aPnt;
|
||||
gp_Vec aD1U, aD1V, aD2U, aD2V, aD2UV;
|
||||
myAdaptor->D2(theU, theV, aPnt, aD1U, aD1V, aD2U, aD2V, aD2UV);
|
||||
return GeomProp::ComputeMeanGaussian(aD1U, aD1V, aD2U, aD2V, aD2UV, theTol);
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
// 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 <GeomAdaptor_Surface.hxx>
|
||||
#include <GeomProp.hxx>
|
||||
#include <Standard.hxx>
|
||||
#include <Standard_DefineAlloc.hxx>
|
||||
|
||||
//! @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.
|
||||
//!
|
||||
//! @warning The caller must ensure that the adaptor pointer remains valid
|
||||
//! for the entire lifetime of this object.
|
||||
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)
|
||||
: myAdaptor(theAdaptor)
|
||||
{
|
||||
}
|
||||
|
||||
//! 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;
|
||||
|
||||
//! Returns the adaptor pointer.
|
||||
const GeomAdaptor_Surface* Adaptor() const { return myAdaptor; }
|
||||
|
||||
//! Compute surface normal at given parameter.
|
||||
//! TODO: At the apex (V = -R/sin(alpha)), D1U degenerates and Normal returns IsDefined=false.
|
||||
//! Could use analytical normal for this special case.
|
||||
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;
|
||||
};
|
||||
|
||||
#endif // _GeomProp_Cone_HeaderFile
|
||||
@@ -0,0 +1,213 @@
|
||||
// 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_Curve.hxx>
|
||||
|
||||
#include <GeomAdaptor_Curve.hxx>
|
||||
#include <Geom_TrimmedCurve.hxx>
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
void GeomProp_Curve::Initialize(const Adaptor3d_Curve& theCurve)
|
||||
{
|
||||
if (theCurve.IsKind(STANDARD_TYPE(GeomAdaptor_Curve)))
|
||||
{
|
||||
const auto& aGeomAdaptor = static_cast<const GeomAdaptor_Curve&>(theCurve);
|
||||
myAdaptor = new GeomAdaptor_Curve(aGeomAdaptor);
|
||||
initFromAdaptor();
|
||||
return;
|
||||
}
|
||||
|
||||
// For non-GeomAdaptor, set uninitialized.
|
||||
myAdaptor.Nullify();
|
||||
myCurveType = theCurve.GetType();
|
||||
myEvaluator.emplace<std::monostate>();
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
void GeomProp_Curve::Initialize(const occ::handle<Geom_Curve>& theCurve)
|
||||
{
|
||||
if (theCurve.IsNull())
|
||||
{
|
||||
myAdaptor.Nullify();
|
||||
myEvaluator.emplace<std::monostate>();
|
||||
myCurveType = GeomAbs_OtherCurve;
|
||||
return;
|
||||
}
|
||||
|
||||
myAdaptor = new GeomAdaptor_Curve(theCurve);
|
||||
initFromAdaptor();
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
void GeomProp_Curve::initFromAdaptor()
|
||||
{
|
||||
myCurveType = myAdaptor->GetType();
|
||||
const GeomAdaptor_Curve* aPtr = myAdaptor.get();
|
||||
|
||||
switch (myCurveType)
|
||||
{
|
||||
case GeomAbs_Line:
|
||||
myEvaluator.emplace<GeomProp_Line>(aPtr);
|
||||
break;
|
||||
case GeomAbs_Circle:
|
||||
myEvaluator.emplace<GeomProp_Circle>(aPtr);
|
||||
break;
|
||||
case GeomAbs_Ellipse:
|
||||
myEvaluator.emplace<GeomProp_Ellipse>(aPtr);
|
||||
break;
|
||||
case GeomAbs_Hyperbola:
|
||||
myEvaluator.emplace<GeomProp_Hyperbola>(aPtr);
|
||||
break;
|
||||
case GeomAbs_Parabola:
|
||||
myEvaluator.emplace<GeomProp_Parabola>(aPtr);
|
||||
break;
|
||||
case GeomAbs_BezierCurve:
|
||||
myEvaluator.emplace<GeomProp_BezierCurve>(aPtr);
|
||||
break;
|
||||
case GeomAbs_BSplineCurve:
|
||||
myEvaluator.emplace<GeomProp_BSplineCurve>(aPtr);
|
||||
break;
|
||||
case GeomAbs_OffsetCurve:
|
||||
myEvaluator.emplace<GeomProp_OffsetCurve>(aPtr);
|
||||
break;
|
||||
default:
|
||||
myEvaluator.emplace<GeomProp_OtherCurve>(aPtr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
bool GeomProp_Curve::IsInitialized() const
|
||||
{
|
||||
return !std::holds_alternative<std::monostate>(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<decltype(theEval)>;
|
||||
if constexpr (std::is_same_v<T, std::monostate>)
|
||||
{
|
||||
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<decltype(theEval)>;
|
||||
if constexpr (std::is_same_v<T, std::monostate>)
|
||||
{
|
||||
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<decltype(theEval)>;
|
||||
if constexpr (std::is_same_v<T, std::monostate>)
|
||||
{
|
||||
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<decltype(theEval)>;
|
||||
if constexpr (std::is_same_v<T, std::monostate>)
|
||||
{
|
||||
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<decltype(theEval)>;
|
||||
if constexpr (std::is_same_v<T, std::monostate>)
|
||||
{
|
||||
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<decltype(theEval)>;
|
||||
if constexpr (std::is_same_v<T, std::monostate>)
|
||||
{
|
||||
return {{}, false};
|
||||
}
|
||||
else
|
||||
{
|
||||
return theEval.FindInflections();
|
||||
}
|
||||
},
|
||||
myEvaluator);
|
||||
}
|
||||
@@ -0,0 +1,152 @@
|
||||
// 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 <Adaptor3d_Curve.hxx>
|
||||
#include <Geom_Curve.hxx>
|
||||
#include <GeomAdaptor_Curve.hxx>
|
||||
#include <GeomAbs_CurveType.hxx>
|
||||
#include <GeomProp.hxx>
|
||||
#include <GeomProp_BezierCurve.hxx>
|
||||
#include <GeomProp_BSplineCurve.hxx>
|
||||
#include <GeomProp_Circle.hxx>
|
||||
#include <GeomProp_Ellipse.hxx>
|
||||
#include <GeomProp_Hyperbola.hxx>
|
||||
#include <GeomProp_Line.hxx>
|
||||
#include <GeomProp_OffsetCurve.hxx>
|
||||
#include <GeomProp_OtherCurve.hxx>
|
||||
#include <GeomProp_Parabola.hxx>
|
||||
#include <Standard.hxx>
|
||||
#include <Standard_DefineAlloc.hxx>
|
||||
|
||||
#include <variant>
|
||||
|
||||
//! @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;
|
||||
//! aProp.Initialize(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<std::monostate,
|
||||
GeomProp_Line,
|
||||
GeomProp_Circle,
|
||||
GeomProp_Ellipse,
|
||||
GeomProp_Hyperbola,
|
||||
GeomProp_Parabola,
|
||||
GeomProp_BezierCurve,
|
||||
GeomProp_BSplineCurve,
|
||||
GeomProp_OffsetCurve,
|
||||
GeomProp_OtherCurve>;
|
||||
|
||||
//! Default constructor - uninitialized state.
|
||||
GeomProp_Curve()
|
||||
: myEvaluator(std::monostate{}),
|
||||
myCurveType(GeomAbs_OtherCurve)
|
||||
{
|
||||
}
|
||||
|
||||
//! 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;
|
||||
|
||||
//! Initialize 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
|
||||
Standard_EXPORT void Initialize(const Adaptor3d_Curve& theCurve);
|
||||
|
||||
//! Initialize from geometry handle (auto-detects curve type).
|
||||
//! @param[in] theCurve 3D geometry to evaluate
|
||||
Standard_EXPORT void Initialize(const occ::handle<Geom_Curve>& theCurve);
|
||||
|
||||
//! Returns true if properly initialized.
|
||||
Standard_EXPORT bool IsInitialized() const;
|
||||
|
||||
//! Returns the detected curve type.
|
||||
GeomAbs_CurveType GetType() const { return myCurveType; }
|
||||
|
||||
//! 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;
|
||||
|
||||
private:
|
||||
//! Initialize from stored adaptor (dispatches to per-geometry evaluator).
|
||||
//! Must be called after myAdaptor is set. Per-geometry evaluators receive
|
||||
//! a non-owning pointer to myAdaptor; their lifetime is managed by the variant.
|
||||
Standard_EXPORT void initFromAdaptor();
|
||||
|
||||
occ::handle<GeomAdaptor_Curve> myAdaptor; //!< Owns the adaptor (ensures lifetime).
|
||||
EvaluatorVariant myEvaluator; //!< Per-geometry evaluator (non-owning pointer to myAdaptor).
|
||||
GeomAbs_CurveType myCurveType;
|
||||
};
|
||||
|
||||
#endif // _GeomProp_Curve_HeaderFile
|
||||
@@ -0,0 +1,96 @@
|
||||
// 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 <GeomAdaptor_Surface.hxx>
|
||||
#include <GeomProp.hxx>
|
||||
#include <Standard_DefineAlloc.hxx>
|
||||
|
||||
//! @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)
|
||||
//!
|
||||
//! @warning The caller must ensure that the adaptor pointer remains valid
|
||||
//! for the entire lifetime of this object.
|
||||
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)
|
||||
: myAdaptor(theAdaptor)
|
||||
{
|
||||
}
|
||||
|
||||
//! 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;
|
||||
|
||||
//! Returns the adaptor pointer.
|
||||
const GeomAdaptor_Surface* Adaptor() const { return myAdaptor; }
|
||||
|
||||
//! Compute surface normal at given (U, V) parameter.
|
||||
//! For a cylinder, the normal is radially outward from the axis.
|
||||
//! TODO: Could use analytical normal (radial direction from axis) for degenerate D1 cases,
|
||||
//! though in practice cylinder D1 never degenerates.
|
||||
GeomProp::SurfaceNormalResult Normal(double theU, double theV, double theTol) const
|
||||
{
|
||||
if (myAdaptor == nullptr)
|
||||
{
|
||||
return {{}, false};
|
||||
}
|
||||
gp_Pnt aPnt;
|
||||
gp_Vec aD1U, aD1V;
|
||||
myAdaptor->D1(theU, theV, aPnt, aD1U, aD1V);
|
||||
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
|
||||
{
|
||||
if (myAdaptor == nullptr)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
gp_Pnt aPnt;
|
||||
gp_Vec aD1U, aD1V, aD2U, aD2V, aD2UV;
|
||||
myAdaptor->D2(theU, theV, aPnt, aD1U, aD1V, aD2U, aD2V, aD2UV);
|
||||
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
|
||||
{
|
||||
if (myAdaptor == nullptr)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
gp_Pnt aPnt;
|
||||
gp_Vec aD1U, aD1V, aD2U, aD2V, aD2UV;
|
||||
myAdaptor->D2(theU, theV, aPnt, aD1U, aD1V, aD2U, aD2V, aD2UV);
|
||||
return GeomProp::ComputeMeanGaussian(aD1U, aD1V, aD2U, aD2V, aD2UV, theTol);
|
||||
}
|
||||
|
||||
private:
|
||||
const GeomAdaptor_Surface* myAdaptor;
|
||||
};
|
||||
|
||||
#endif // _GeomProp_Cylinder_HeaderFile
|
||||
@@ -0,0 +1,120 @@
|
||||
// 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_Ellipse.hxx>
|
||||
|
||||
#include <ElCLib.hxx>
|
||||
|
||||
#include <cmath>
|
||||
|
||||
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 (myAdaptor == nullptr)
|
||||
{
|
||||
return {{}, false};
|
||||
}
|
||||
gp_Pnt aPnt;
|
||||
gp_Vec aD1, aD2, aD3;
|
||||
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 (myAdaptor == nullptr)
|
||||
{
|
||||
return {0.0, false, false};
|
||||
}
|
||||
gp_Pnt aPnt;
|
||||
gp_Vec aD1, aD2;
|
||||
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 (myAdaptor == nullptr)
|
||||
{
|
||||
return {{}, false};
|
||||
}
|
||||
gp_Pnt aPnt;
|
||||
gp_Vec aD1, aD2;
|
||||
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 (myAdaptor == nullptr)
|
||||
{
|
||||
return {{}, false};
|
||||
}
|
||||
gp_Pnt aPnt;
|
||||
gp_Vec aD1, aD2;
|
||||
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 (myAdaptor == nullptr)
|
||||
{
|
||||
aResult.IsDone = false;
|
||||
return aResult;
|
||||
}
|
||||
|
||||
const double aUFirst = myAdaptor->FirstParameter();
|
||||
const double aULast = myAdaptor->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;
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
// 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 <GeomAdaptor_Curve.hxx>
|
||||
#include <GeomProp.hxx>
|
||||
#include <Standard.hxx>
|
||||
#include <Standard_DefineAlloc.hxx>
|
||||
|
||||
//! @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)
|
||||
//!
|
||||
//! @warning The caller must ensure that the adaptor pointer remains valid
|
||||
//! for the entire lifetime of this object. This class does not manage
|
||||
//! the adaptor's lifetime.
|
||||
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)
|
||||
: myAdaptor(theAdaptor)
|
||||
{
|
||||
}
|
||||
|
||||
//! 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;
|
||||
|
||||
//! Returns the adaptor pointer.
|
||||
const GeomAdaptor_Curve* Adaptor() const { return myAdaptor; }
|
||||
|
||||
//! 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;
|
||||
};
|
||||
|
||||
#endif // _GeomProp_Ellipse_HeaderFile
|
||||
@@ -0,0 +1,98 @@
|
||||
// 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_Hyperbola.hxx>
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
GeomProp::TangentResult GeomProp_Hyperbola::Tangent(const double theParam,
|
||||
const double theTol) const
|
||||
{
|
||||
if (myAdaptor == nullptr)
|
||||
{
|
||||
return {{}, false};
|
||||
}
|
||||
gp_Pnt aPnt;
|
||||
gp_Vec aD1, aD2, aD3;
|
||||
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 (myAdaptor == nullptr)
|
||||
{
|
||||
return {0.0, false, false};
|
||||
}
|
||||
gp_Pnt aPnt;
|
||||
gp_Vec aD1, aD2;
|
||||
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 (myAdaptor == nullptr)
|
||||
{
|
||||
return {{}, false};
|
||||
}
|
||||
gp_Pnt aPnt;
|
||||
gp_Vec aD1, aD2;
|
||||
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 (myAdaptor == nullptr)
|
||||
{
|
||||
return {{}, false};
|
||||
}
|
||||
gp_Pnt aPnt;
|
||||
gp_Vec aD1, aD2;
|
||||
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 (myAdaptor == nullptr)
|
||||
{
|
||||
aResult.IsDone = false;
|
||||
return aResult;
|
||||
}
|
||||
|
||||
const double aUFirst = myAdaptor->FirstParameter();
|
||||
const double aULast = myAdaptor->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;
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
// 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 <GeomAdaptor_Curve.hxx>
|
||||
#include <GeomProp.hxx>
|
||||
#include <Standard.hxx>
|
||||
#include <Standard_DefineAlloc.hxx>
|
||||
|
||||
//! @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.
|
||||
//!
|
||||
//! @warning The caller must ensure that the adaptor pointer remains valid
|
||||
//! for the entire lifetime of this object. This class does not manage
|
||||
//! the adaptor's lifetime.
|
||||
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)
|
||||
: myAdaptor(theAdaptor)
|
||||
{
|
||||
}
|
||||
|
||||
//! 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;
|
||||
|
||||
//! Returns the adaptor pointer.
|
||||
const GeomAdaptor_Curve* Adaptor() const { return myAdaptor; }
|
||||
|
||||
//! 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;
|
||||
};
|
||||
|
||||
#endif // _GeomProp_Hyperbola_HeaderFile
|
||||
@@ -0,0 +1,112 @@
|
||||
// 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 <GeomAdaptor_Curve.hxx>
|
||||
#include <GeomProp.hxx>
|
||||
#include <Standard_DefineAlloc.hxx>
|
||||
|
||||
//! @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.
|
||||
//!
|
||||
//! @warning The caller must ensure that the adaptor pointer remains valid
|
||||
//! for the entire lifetime of this object. This class does not manage
|
||||
//! the adaptor's lifetime.
|
||||
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)
|
||||
: myAdaptor(theAdaptor)
|
||||
{
|
||||
}
|
||||
|
||||
//! 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;
|
||||
|
||||
//! Returns the adaptor pointer.
|
||||
const GeomAdaptor_Curve* Adaptor() const { return myAdaptor; }
|
||||
|
||||
//! 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 {myAdaptor->Line().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;
|
||||
};
|
||||
|
||||
#endif // _GeomProp_Line_HeaderFile
|
||||
@@ -0,0 +1,340 @@
|
||||
// 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_OffsetCurve.hxx>
|
||||
|
||||
#include <gp.hxx>
|
||||
#include <MathRoot_Brent.hxx>
|
||||
#include <MathRoot_Multiple.hxx>
|
||||
#include <Precision.hxx>
|
||||
|
||||
#include <cmath>
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
constexpr double THE_CURVATURE_DERIV_COEFF = 3.0;
|
||||
constexpr double THE_DIFF_STEP_DIVISOR = 100.0;
|
||||
constexpr double THE_D2_MAGNITUDE_THRESHOLD = 1.0e-4;
|
||||
constexpr double THE_EPSILON_SCALE = 1.0e-4;
|
||||
constexpr int THE_EXTREMA_NB_SAMPLES = 100;
|
||||
constexpr int THE_INFLECTION_NB_SAMPLES = 30;
|
||||
constexpr double THE_INFLECTION_TOLERANCE = 1.0e-6;
|
||||
|
||||
//! Function for finding curvature extrema on offset curves.
|
||||
class FuncCurExt
|
||||
{
|
||||
public:
|
||||
FuncCurExt(const GeomAdaptor_Curve* 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);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
if (aCPMag < gp::Resolution())
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
bool IsMinKC(const double X) const
|
||||
{
|
||||
gp_Pnt aP;
|
||||
gp_Vec 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).Magnitude() / 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).Magnitude() / aV13n;
|
||||
|
||||
return std::abs(aKC) > std::abs(aKP);
|
||||
}
|
||||
|
||||
private:
|
||||
const GeomAdaptor_Curve* myCurve;
|
||||
double myEpsX;
|
||||
};
|
||||
|
||||
//! Function for finding inflection points on offset curves.
|
||||
class FuncCurNul
|
||||
{
|
||||
public:
|
||||
FuncCurNul(const GeomAdaptor_Curve* 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);
|
||||
|
||||
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 GeomAdaptor_Curve* myCurve;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
GeomProp::TangentResult GeomProp_OffsetCurve::Tangent(const double theParam,
|
||||
const double theTol) const
|
||||
{
|
||||
if (myAdaptor == nullptr)
|
||||
{
|
||||
return {{}, false};
|
||||
}
|
||||
gp_Pnt aPnt;
|
||||
gp_Vec aD1, aD2, aD3;
|
||||
myAdaptor->D3(theParam, aPnt, aD1, aD2, aD3);
|
||||
return GeomProp::ComputeTangent(aD1, aD2, aD3, theTol);
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
GeomProp::CurvatureResult GeomProp_OffsetCurve::Curvature(const double theParam,
|
||||
const double theTol) const
|
||||
{
|
||||
if (myAdaptor == nullptr)
|
||||
{
|
||||
return {0.0, false, false};
|
||||
}
|
||||
gp_Pnt aPnt;
|
||||
gp_Vec aD1, aD2;
|
||||
myAdaptor->D2(theParam, aPnt, aD1, aD2);
|
||||
return GeomProp::ComputeCurvature(aD1, aD2, theTol);
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
GeomProp::NormalResult GeomProp_OffsetCurve::Normal(const double theParam,
|
||||
const double theTol) const
|
||||
{
|
||||
if (myAdaptor == nullptr)
|
||||
{
|
||||
return {{}, false};
|
||||
}
|
||||
gp_Pnt aPnt;
|
||||
gp_Vec aD1, aD2;
|
||||
myAdaptor->D2(theParam, aPnt, aD1, aD2);
|
||||
return GeomProp::ComputeNormal(aD1, aD2, theTol);
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
GeomProp::CentreResult GeomProp_OffsetCurve::CentreOfCurvature(const double theParam,
|
||||
const double theTol) const
|
||||
{
|
||||
if (myAdaptor == nullptr)
|
||||
{
|
||||
return {{}, false};
|
||||
}
|
||||
gp_Pnt aPnt;
|
||||
gp_Vec aD1, aD2;
|
||||
myAdaptor->D2(theParam, aPnt, aD1, aD2);
|
||||
return GeomProp::ComputeCentreOfCurvature(aPnt, aD1, aD2, theTol);
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
GeomProp::CurveAnalysis GeomProp_OffsetCurve::FindCurvatureExtrema() const
|
||||
{
|
||||
GeomProp::CurveAnalysis aResult;
|
||||
aResult.IsDone = true;
|
||||
|
||||
if (myAdaptor == nullptr)
|
||||
{
|
||||
aResult.IsDone = false;
|
||||
return aResult;
|
||||
}
|
||||
|
||||
const double aUMin = myAdaptor->FirstParameter();
|
||||
const double aUMax = myAdaptor->LastParameter();
|
||||
const double aEpsH = THE_EPSILON_SCALE * (aUMax - aUMin);
|
||||
|
||||
FuncCurExt aFunc(myAdaptor, aEpsH);
|
||||
|
||||
MathRoot::MultipleConfig aConfig;
|
||||
aConfig.NbSamples = THE_EXTREMA_NB_SAMPLES;
|
||||
aConfig.XTolerance = aEpsH;
|
||||
aConfig.FTolerance = aEpsH;
|
||||
|
||||
MathRoot::MultipleResult aRoots =
|
||||
MathRoot::FindAllRootsWithDerivative(aFunc, aUMin, aUMax, 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();
|
||||
auto 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;
|
||||
aResult.Points.Append({aParam, aType});
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
aResult.IsDone = false;
|
||||
}
|
||||
|
||||
return aResult;
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
GeomProp::CurveAnalysis GeomProp_OffsetCurve::FindInflections() const
|
||||
{
|
||||
GeomProp::CurveAnalysis aResult;
|
||||
aResult.IsDone = true;
|
||||
|
||||
if (myAdaptor == nullptr)
|
||||
{
|
||||
aResult.IsDone = false;
|
||||
return aResult;
|
||||
}
|
||||
|
||||
FuncCurNul aFunc(myAdaptor);
|
||||
|
||||
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, myAdaptor->FirstParameter(), myAdaptor->LastParameter(), aConfig);
|
||||
|
||||
if (aRoots.IsDone())
|
||||
{
|
||||
for (int j = 0; j < aRoots.NbRoots(); ++j)
|
||||
{
|
||||
aResult.Points.Append({aRoots[j], GeomProp::CIType::Inflection});
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
aResult.IsDone = false;
|
||||
}
|
||||
|
||||
return aResult;
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
// 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 <GeomAdaptor_Curve.hxx>
|
||||
#include <GeomProp.hxx>
|
||||
#include <Standard.hxx>
|
||||
#include <Standard_DefineAlloc.hxx>
|
||||
|
||||
//! @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.
|
||||
//!
|
||||
//! @warning The caller must ensure that the adaptor pointer remains valid
|
||||
//! for the entire lifetime of this object. This class does not manage
|
||||
//! the adaptor's lifetime.
|
||||
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)
|
||||
: myAdaptor(theAdaptor)
|
||||
{
|
||||
}
|
||||
|
||||
//! 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;
|
||||
|
||||
//! Returns the adaptor pointer.
|
||||
const GeomAdaptor_Curve* Adaptor() const { return myAdaptor; }
|
||||
|
||||
//! 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;
|
||||
};
|
||||
|
||||
#endif // _GeomProp_OffsetCurve_HeaderFile
|
||||
@@ -0,0 +1,62 @@
|
||||
// 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_OffsetSurface.hxx>
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
GeomProp::SurfaceNormalResult GeomProp_OffsetSurface::Normal(const double theU,
|
||||
const double theV,
|
||||
const double theTol) const
|
||||
{
|
||||
if (myAdaptor == nullptr)
|
||||
{
|
||||
return {{}, false};
|
||||
}
|
||||
gp_Pnt aPnt;
|
||||
gp_Vec aD1U, aD1V;
|
||||
myAdaptor->D1(theU, theV, aPnt, aD1U, aD1V);
|
||||
return GeomProp::ComputeSurfaceNormal(aD1U, aD1V, theTol);
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
GeomProp::SurfaceCurvatureResult GeomProp_OffsetSurface::Curvatures(const double theU,
|
||||
const double theV,
|
||||
const double theTol) const
|
||||
{
|
||||
if (myAdaptor == nullptr)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
gp_Pnt aPnt;
|
||||
gp_Vec aD1U, aD1V, aD2U, aD2V, aD2UV;
|
||||
myAdaptor->D2(theU, theV, aPnt, aD1U, aD1V, aD2U, aD2V, aD2UV);
|
||||
return GeomProp::ComputeSurfaceCurvatures(aD1U, aD1V, aD2U, aD2V, aD2UV, theTol);
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
GeomProp::MeanGaussianResult GeomProp_OffsetSurface::MeanGaussian(const double theU,
|
||||
const double theV,
|
||||
const double theTol) const
|
||||
{
|
||||
if (myAdaptor == nullptr)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
gp_Pnt aPnt;
|
||||
gp_Vec aD1U, aD1V, aD2U, aD2V, aD2UV;
|
||||
myAdaptor->D2(theU, theV, aPnt, aD1U, aD1V, aD2U, aD2V, aD2UV);
|
||||
return GeomProp::ComputeMeanGaussian(aD1U, aD1V, aD2U, aD2V, aD2UV, theTol);
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
// 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 <GeomAdaptor_Surface.hxx>
|
||||
#include <GeomProp.hxx>
|
||||
#include <Standard.hxx>
|
||||
#include <Standard_DefineAlloc.hxx>
|
||||
|
||||
//! @brief Local differential properties for an offset surface.
|
||||
//!
|
||||
//! Uses numeric evaluation from adaptor derivatives.
|
||||
//!
|
||||
//! @warning The caller must ensure that the adaptor pointer remains valid
|
||||
//! for the entire lifetime of this object.
|
||||
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)
|
||||
: myAdaptor(theAdaptor)
|
||||
{
|
||||
}
|
||||
|
||||
//! 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;
|
||||
|
||||
//! Returns the adaptor pointer.
|
||||
const GeomAdaptor_Surface* Adaptor() const { return myAdaptor; }
|
||||
|
||||
//! 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;
|
||||
};
|
||||
|
||||
#endif // _GeomProp_OffsetSurface_HeaderFile
|
||||
@@ -0,0 +1,339 @@
|
||||
// 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_OtherCurve.hxx>
|
||||
|
||||
#include <gp.hxx>
|
||||
#include <MathRoot_Brent.hxx>
|
||||
#include <MathRoot_Multiple.hxx>
|
||||
#include <Precision.hxx>
|
||||
|
||||
#include <cmath>
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
constexpr double THE_CURVATURE_DERIV_COEFF = 3.0;
|
||||
constexpr double THE_DIFF_STEP_DIVISOR = 100.0;
|
||||
constexpr double THE_D2_MAGNITUDE_THRESHOLD = 1.0e-4;
|
||||
constexpr double THE_EPSILON_SCALE = 1.0e-4;
|
||||
constexpr int THE_EXTREMA_NB_SAMPLES = 100;
|
||||
constexpr int THE_INFLECTION_NB_SAMPLES = 30;
|
||||
constexpr double THE_INFLECTION_TOLERANCE = 1.0e-6;
|
||||
|
||||
//! Function for finding curvature extrema.
|
||||
class FuncCurExt
|
||||
{
|
||||
public:
|
||||
FuncCurExt(const GeomAdaptor_Curve* 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);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
if (aCPMag < gp::Resolution())
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
bool IsMinKC(const double X) const
|
||||
{
|
||||
gp_Pnt aP;
|
||||
gp_Vec 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).Magnitude() / 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).Magnitude() / aV13n;
|
||||
|
||||
return std::abs(aKC) > std::abs(aKP);
|
||||
}
|
||||
|
||||
private:
|
||||
const GeomAdaptor_Curve* myCurve;
|
||||
double myEpsX;
|
||||
};
|
||||
|
||||
//! Function for finding inflection points.
|
||||
class FuncCurNul
|
||||
{
|
||||
public:
|
||||
FuncCurNul(const GeomAdaptor_Curve* 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);
|
||||
|
||||
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 GeomAdaptor_Curve* myCurve;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
GeomProp::TangentResult GeomProp_OtherCurve::Tangent(const double theParam,
|
||||
const double theTol) const
|
||||
{
|
||||
if (myAdaptor == nullptr)
|
||||
{
|
||||
return {{}, false};
|
||||
}
|
||||
gp_Pnt aPnt;
|
||||
gp_Vec aD1, aD2, aD3;
|
||||
myAdaptor->D3(theParam, aPnt, aD1, aD2, aD3);
|
||||
return GeomProp::ComputeTangent(aD1, aD2, aD3, theTol);
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
GeomProp::CurvatureResult GeomProp_OtherCurve::Curvature(const double theParam,
|
||||
const double theTol) const
|
||||
{
|
||||
if (myAdaptor == nullptr)
|
||||
{
|
||||
return {0.0, false, false};
|
||||
}
|
||||
gp_Pnt aPnt;
|
||||
gp_Vec aD1, aD2;
|
||||
myAdaptor->D2(theParam, aPnt, aD1, aD2);
|
||||
return GeomProp::ComputeCurvature(aD1, aD2, theTol);
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
GeomProp::NormalResult GeomProp_OtherCurve::Normal(const double theParam, const double theTol) const
|
||||
{
|
||||
if (myAdaptor == nullptr)
|
||||
{
|
||||
return {{}, false};
|
||||
}
|
||||
gp_Pnt aPnt;
|
||||
gp_Vec aD1, aD2;
|
||||
myAdaptor->D2(theParam, aPnt, aD1, aD2);
|
||||
return GeomProp::ComputeNormal(aD1, aD2, theTol);
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
GeomProp::CentreResult GeomProp_OtherCurve::CentreOfCurvature(const double theParam,
|
||||
const double theTol) const
|
||||
{
|
||||
if (myAdaptor == nullptr)
|
||||
{
|
||||
return {{}, false};
|
||||
}
|
||||
gp_Pnt aPnt;
|
||||
gp_Vec aD1, aD2;
|
||||
myAdaptor->D2(theParam, aPnt, aD1, aD2);
|
||||
return GeomProp::ComputeCentreOfCurvature(aPnt, aD1, aD2, theTol);
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
GeomProp::CurveAnalysis GeomProp_OtherCurve::FindCurvatureExtrema() const
|
||||
{
|
||||
GeomProp::CurveAnalysis aResult;
|
||||
aResult.IsDone = true;
|
||||
|
||||
if (myAdaptor == nullptr)
|
||||
{
|
||||
aResult.IsDone = false;
|
||||
return aResult;
|
||||
}
|
||||
|
||||
const double aUMin = myAdaptor->FirstParameter();
|
||||
const double aUMax = myAdaptor->LastParameter();
|
||||
const double aEpsH = THE_EPSILON_SCALE * (aUMax - aUMin);
|
||||
|
||||
FuncCurExt aFunc(myAdaptor, aEpsH);
|
||||
|
||||
MathRoot::MultipleConfig aConfig;
|
||||
aConfig.NbSamples = THE_EXTREMA_NB_SAMPLES;
|
||||
aConfig.XTolerance = aEpsH;
|
||||
aConfig.FTolerance = aEpsH;
|
||||
|
||||
MathRoot::MultipleResult aRoots =
|
||||
MathRoot::FindAllRootsWithDerivative(aFunc, aUMin, aUMax, 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();
|
||||
auto 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;
|
||||
aResult.Points.Append({aParam, aType});
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
aResult.IsDone = false;
|
||||
}
|
||||
|
||||
return aResult;
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
GeomProp::CurveAnalysis GeomProp_OtherCurve::FindInflections() const
|
||||
{
|
||||
GeomProp::CurveAnalysis aResult;
|
||||
aResult.IsDone = true;
|
||||
|
||||
if (myAdaptor == nullptr)
|
||||
{
|
||||
aResult.IsDone = false;
|
||||
return aResult;
|
||||
}
|
||||
|
||||
FuncCurNul aFunc(myAdaptor);
|
||||
|
||||
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, myAdaptor->FirstParameter(), myAdaptor->LastParameter(), aConfig);
|
||||
|
||||
if (aRoots.IsDone())
|
||||
{
|
||||
for (int j = 0; j < aRoots.NbRoots(); ++j)
|
||||
{
|
||||
aResult.Points.Append({aRoots[j], GeomProp::CIType::Inflection});
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
aResult.IsDone = false;
|
||||
}
|
||||
|
||||
return aResult;
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
// 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 <GeomAdaptor_Curve.hxx>
|
||||
#include <GeomProp.hxx>
|
||||
#include <Standard.hxx>
|
||||
#include <Standard_DefineAlloc.hxx>
|
||||
|
||||
//! @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.
|
||||
//!
|
||||
//! @warning The caller must ensure that the adaptor pointer remains valid
|
||||
//! for the entire lifetime of this object. This class does not manage
|
||||
//! the adaptor's lifetime.
|
||||
class GeomProp_OtherCurve
|
||||
{
|
||||
public:
|
||||
DEFINE_STANDARD_ALLOC
|
||||
|
||||
//! Constructor with adaptor pointer (non-owning).
|
||||
//! @param theAdaptor the 3D curve adaptor (must not be null)
|
||||
GeomProp_OtherCurve(const GeomAdaptor_Curve* theAdaptor)
|
||||
: myAdaptor(theAdaptor)
|
||||
{
|
||||
}
|
||||
|
||||
//! 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;
|
||||
|
||||
//! Returns the adaptor pointer.
|
||||
const GeomAdaptor_Curve* Adaptor() const { return myAdaptor; }
|
||||
|
||||
//! 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;
|
||||
};
|
||||
|
||||
#endif // _GeomProp_OtherCurve_HeaderFile
|
||||
@@ -0,0 +1,62 @@
|
||||
// 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_OtherSurface.hxx>
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
GeomProp::SurfaceNormalResult GeomProp_OtherSurface::Normal(const double theU,
|
||||
const double theV,
|
||||
const double theTol) const
|
||||
{
|
||||
if (myAdaptor == nullptr)
|
||||
{
|
||||
return {{}, false};
|
||||
}
|
||||
gp_Pnt aPnt;
|
||||
gp_Vec aD1U, aD1V;
|
||||
myAdaptor->D1(theU, theV, aPnt, aD1U, aD1V);
|
||||
return GeomProp::ComputeSurfaceNormal(aD1U, aD1V, theTol);
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
GeomProp::SurfaceCurvatureResult GeomProp_OtherSurface::Curvatures(const double theU,
|
||||
const double theV,
|
||||
const double theTol) const
|
||||
{
|
||||
if (myAdaptor == nullptr)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
gp_Pnt aPnt;
|
||||
gp_Vec aD1U, aD1V, aD2U, aD2V, aD2UV;
|
||||
myAdaptor->D2(theU, theV, aPnt, aD1U, aD1V, aD2U, aD2V, aD2UV);
|
||||
return GeomProp::ComputeSurfaceCurvatures(aD1U, aD1V, aD2U, aD2V, aD2UV, theTol);
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
GeomProp::MeanGaussianResult GeomProp_OtherSurface::MeanGaussian(const double theU,
|
||||
const double theV,
|
||||
const double theTol) const
|
||||
{
|
||||
if (myAdaptor == nullptr)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
gp_Pnt aPnt;
|
||||
gp_Vec aD1U, aD1V, aD2U, aD2V, aD2UV;
|
||||
myAdaptor->D2(theU, theV, aPnt, aD1U, aD1V, aD2U, aD2V, aD2UV);
|
||||
return GeomProp::ComputeMeanGaussian(aD1U, aD1V, aD2U, aD2V, aD2UV, theTol);
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
// 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 <GeomAdaptor_Surface.hxx>
|
||||
#include <GeomProp.hxx>
|
||||
#include <Standard.hxx>
|
||||
#include <Standard_DefineAlloc.hxx>
|
||||
|
||||
//! @brief Fallback local differential properties for any surface type.
|
||||
//!
|
||||
//! Uses adaptor D1/D2 methods for property computation.
|
||||
//!
|
||||
//! @warning The caller must ensure that the adaptor pointer remains valid
|
||||
//! for the entire lifetime of this object.
|
||||
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 GeomAdaptor_Surface* theAdaptor)
|
||||
: myAdaptor(theAdaptor)
|
||||
{
|
||||
}
|
||||
|
||||
//! 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;
|
||||
|
||||
//! Returns the adaptor pointer.
|
||||
const GeomAdaptor_Surface* Adaptor() const { return myAdaptor; }
|
||||
|
||||
//! 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;
|
||||
};
|
||||
|
||||
#endif // _GeomProp_OtherSurface_HeaderFile
|
||||
@@ -0,0 +1,97 @@
|
||||
// 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_Parabola.hxx>
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
GeomProp::TangentResult GeomProp_Parabola::Tangent(const double theParam, const double theTol) const
|
||||
{
|
||||
if (myAdaptor == nullptr)
|
||||
{
|
||||
return {{}, false};
|
||||
}
|
||||
gp_Pnt aPnt;
|
||||
gp_Vec aD1, aD2, aD3;
|
||||
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 (myAdaptor == nullptr)
|
||||
{
|
||||
return {0.0, false, false};
|
||||
}
|
||||
gp_Pnt aPnt;
|
||||
gp_Vec aD1, aD2;
|
||||
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 (myAdaptor == nullptr)
|
||||
{
|
||||
return {{}, false};
|
||||
}
|
||||
gp_Pnt aPnt;
|
||||
gp_Vec aD1, aD2;
|
||||
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 (myAdaptor == nullptr)
|
||||
{
|
||||
return {{}, false};
|
||||
}
|
||||
gp_Pnt aPnt;
|
||||
gp_Vec aD1, aD2;
|
||||
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 (myAdaptor == nullptr)
|
||||
{
|
||||
aResult.IsDone = false;
|
||||
return aResult;
|
||||
}
|
||||
|
||||
const double aUFirst = myAdaptor->FirstParameter();
|
||||
const double aULast = myAdaptor->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;
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
// 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 <GeomAdaptor_Curve.hxx>
|
||||
#include <GeomProp.hxx>
|
||||
#include <Standard.hxx>
|
||||
#include <Standard_DefineAlloc.hxx>
|
||||
|
||||
//! @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.
|
||||
//!
|
||||
//! @warning The caller must ensure that the adaptor pointer remains valid
|
||||
//! for the entire lifetime of this object. This class does not manage
|
||||
//! the adaptor's lifetime.
|
||||
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)
|
||||
: myAdaptor(theAdaptor)
|
||||
{
|
||||
}
|
||||
|
||||
//! 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;
|
||||
|
||||
//! Returns the adaptor pointer.
|
||||
const GeomAdaptor_Curve* Adaptor() const { return myAdaptor; }
|
||||
|
||||
//! 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;
|
||||
};
|
||||
|
||||
#endif // _GeomProp_Parabola_HeaderFile
|
||||
@@ -0,0 +1,98 @@
|
||||
// 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 <GeomAdaptor_Surface.hxx>
|
||||
#include <GeomProp.hxx>
|
||||
#include <Standard_DefineAlloc.hxx>
|
||||
|
||||
//! @brief Local differential properties for a plane surface.
|
||||
//!
|
||||
//! Trivial implementation: constant normal, zero curvatures everywhere.
|
||||
//! All properties are computed analytically without numerical evaluation.
|
||||
//!
|
||||
//! @warning The caller must ensure that the adaptor pointer remains valid
|
||||
//! for the entire lifetime of this object.
|
||||
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)
|
||||
: myAdaptor(theAdaptor)
|
||||
{
|
||||
}
|
||||
|
||||
//! 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;
|
||||
|
||||
//! Returns the adaptor pointer.
|
||||
const GeomAdaptor_Surface* Adaptor() const { return myAdaptor; }
|
||||
|
||||
//! 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
|
||||
{
|
||||
if (myAdaptor == nullptr)
|
||||
{
|
||||
return {{}, false};
|
||||
}
|
||||
gp_Pnt aPnt;
|
||||
gp_Vec aD1U, aD1V;
|
||||
myAdaptor->D1(theU, theV, aPnt, aD1U, aD1V);
|
||||
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 (myAdaptor == nullptr)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
GeomProp::SurfaceCurvatureResult aResult;
|
||||
aResult.MinCurvature = 0.0;
|
||||
aResult.MaxCurvature = 0.0;
|
||||
aResult.MinDirection = myAdaptor->Plane().Position().XDirection();
|
||||
aResult.MaxDirection = myAdaptor->Plane().Position().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 (myAdaptor == nullptr)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
return {0.0, 0.0, true};
|
||||
}
|
||||
|
||||
private:
|
||||
const GeomAdaptor_Surface* myAdaptor;
|
||||
};
|
||||
|
||||
#endif // _GeomProp_Plane_HeaderFile
|
||||
@@ -0,0 +1,95 @@
|
||||
// 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 <GeomAdaptor_Surface.hxx>
|
||||
#include <GeomProp.hxx>
|
||||
#include <Standard_DefineAlloc.hxx>
|
||||
|
||||
//! @brief Local differential properties for a spherical surface.
|
||||
//!
|
||||
//! Analytical implementation: constant curvature 1/R, umbilic everywhere.
|
||||
//! Both principal curvatures equal 1/R.
|
||||
//!
|
||||
//! @warning The caller must ensure that the adaptor pointer remains valid
|
||||
//! for the entire lifetime of this object.
|
||||
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)
|
||||
: myAdaptor(theAdaptor)
|
||||
{
|
||||
}
|
||||
|
||||
//! 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;
|
||||
|
||||
//! Returns the adaptor pointer.
|
||||
const GeomAdaptor_Surface* Adaptor() const { return myAdaptor; }
|
||||
|
||||
//! Compute surface normal at given (U, V) parameter.
|
||||
//! For a sphere, the normal is radially outward from the center.
|
||||
//! TODO: At poles (V = +/-PI/2), D1U degenerates and Normal returns IsDefined=false.
|
||||
//! Could use analytical normal (radial direction from center) for these special cases.
|
||||
GeomProp::SurfaceNormalResult Normal(double theU, double theV, double theTol) const
|
||||
{
|
||||
if (myAdaptor == nullptr)
|
||||
{
|
||||
return {{}, false};
|
||||
}
|
||||
gp_Pnt aPnt;
|
||||
gp_Vec aD1U, aD1V;
|
||||
myAdaptor->D1(theU, theV, aPnt, aD1U, aD1V);
|
||||
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
|
||||
{
|
||||
if (myAdaptor == nullptr)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
gp_Pnt aPnt;
|
||||
gp_Vec aD1U, aD1V, aD2U, aD2V, aD2UV;
|
||||
myAdaptor->D2(theU, theV, aPnt, aD1U, aD1V, aD2U, aD2V, aD2UV);
|
||||
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
|
||||
{
|
||||
if (myAdaptor == nullptr)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
gp_Pnt aPnt;
|
||||
gp_Vec aD1U, aD1V, aD2U, aD2V, aD2UV;
|
||||
myAdaptor->D2(theU, theV, aPnt, aD1U, aD1V, aD2U, aD2V, aD2UV);
|
||||
return GeomProp::ComputeMeanGaussian(aD1U, aD1V, aD2U, aD2V, aD2UV, theTol);
|
||||
}
|
||||
|
||||
private:
|
||||
const GeomAdaptor_Surface* myAdaptor;
|
||||
};
|
||||
|
||||
#endif // _GeomProp_Sphere_HeaderFile
|
||||
@@ -0,0 +1,165 @@
|
||||
// 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_Surface.hxx>
|
||||
|
||||
#include <GeomAdaptor_Surface.hxx>
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
void GeomProp_Surface::Initialize(const Adaptor3d_Surface& theSurface)
|
||||
{
|
||||
if (theSurface.IsKind(STANDARD_TYPE(GeomAdaptor_Surface)))
|
||||
{
|
||||
const auto& aGeomAdaptor = static_cast<const GeomAdaptor_Surface&>(theSurface);
|
||||
myAdaptor = new GeomAdaptor_Surface(aGeomAdaptor);
|
||||
initFromAdaptor();
|
||||
return;
|
||||
}
|
||||
|
||||
// For non-GeomAdaptor, set uninitialized.
|
||||
myAdaptor.Nullify();
|
||||
mySurfaceType = theSurface.GetType();
|
||||
myEvaluator.emplace<std::monostate>();
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
void GeomProp_Surface::Initialize(const occ::handle<Geom_Surface>& theSurface)
|
||||
{
|
||||
if (theSurface.IsNull())
|
||||
{
|
||||
myAdaptor.Nullify();
|
||||
myEvaluator.emplace<std::monostate>();
|
||||
mySurfaceType = GeomAbs_OtherSurface;
|
||||
return;
|
||||
}
|
||||
|
||||
myAdaptor = new GeomAdaptor_Surface(theSurface);
|
||||
initFromAdaptor();
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
void GeomProp_Surface::initFromAdaptor()
|
||||
{
|
||||
mySurfaceType = myAdaptor->GetType();
|
||||
const GeomAdaptor_Surface* aPtr = myAdaptor.get();
|
||||
|
||||
switch (mySurfaceType)
|
||||
{
|
||||
case GeomAbs_Plane:
|
||||
myEvaluator.emplace<GeomProp_Plane>(aPtr);
|
||||
break;
|
||||
case GeomAbs_Cylinder:
|
||||
myEvaluator.emplace<GeomProp_Cylinder>(aPtr);
|
||||
break;
|
||||
case GeomAbs_Cone:
|
||||
myEvaluator.emplace<GeomProp_Cone>(aPtr);
|
||||
break;
|
||||
case GeomAbs_Sphere:
|
||||
myEvaluator.emplace<GeomProp_Sphere>(aPtr);
|
||||
break;
|
||||
case GeomAbs_Torus:
|
||||
myEvaluator.emplace<GeomProp_Torus>(aPtr);
|
||||
break;
|
||||
case GeomAbs_BezierSurface:
|
||||
myEvaluator.emplace<GeomProp_BezierSurface>(aPtr);
|
||||
break;
|
||||
case GeomAbs_BSplineSurface:
|
||||
myEvaluator.emplace<GeomProp_BSplineSurface>(aPtr);
|
||||
break;
|
||||
case GeomAbs_SurfaceOfRevolution:
|
||||
myEvaluator.emplace<GeomProp_SurfaceOfRevolution>(aPtr);
|
||||
break;
|
||||
case GeomAbs_SurfaceOfExtrusion:
|
||||
myEvaluator.emplace<GeomProp_SurfaceOfExtrusion>(aPtr);
|
||||
break;
|
||||
case GeomAbs_OffsetSurface:
|
||||
myEvaluator.emplace<GeomProp_OffsetSurface>(aPtr);
|
||||
break;
|
||||
default:
|
||||
myEvaluator.emplace<GeomProp_OtherSurface>(aPtr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
bool GeomProp_Surface::IsInitialized() const
|
||||
{
|
||||
return !std::holds_alternative<std::monostate>(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<decltype(theEval)>;
|
||||
if constexpr (std::is_same_v<T, std::monostate>)
|
||||
{
|
||||
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<decltype(theEval)>;
|
||||
if constexpr (std::is_same_v<T, std::monostate>)
|
||||
{
|
||||
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<decltype(theEval)>;
|
||||
if constexpr (std::is_same_v<T, std::monostate>)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
else
|
||||
{
|
||||
return theEval.MeanGaussian(theU, theV, theTol);
|
||||
}
|
||||
},
|
||||
myEvaluator);
|
||||
}
|
||||
@@ -0,0 +1,154 @@
|
||||
// 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 <Adaptor3d_Surface.hxx>
|
||||
#include <Geom_Surface.hxx>
|
||||
#include <GeomAdaptor_Surface.hxx>
|
||||
#include <GeomAbs_SurfaceType.hxx>
|
||||
#include <GeomProp.hxx>
|
||||
#include <GeomProp_BezierSurface.hxx>
|
||||
#include <GeomProp_BSplineSurface.hxx>
|
||||
#include <GeomProp_Cone.hxx>
|
||||
#include <GeomProp_Cylinder.hxx>
|
||||
#include <GeomProp_OffsetSurface.hxx>
|
||||
#include <GeomProp_OtherSurface.hxx>
|
||||
#include <GeomProp_Plane.hxx>
|
||||
#include <GeomProp_Sphere.hxx>
|
||||
#include <GeomProp_SurfaceOfExtrusion.hxx>
|
||||
#include <GeomProp_SurfaceOfRevolution.hxx>
|
||||
#include <GeomProp_Torus.hxx>
|
||||
#include <Standard.hxx>
|
||||
#include <Standard_DefineAlloc.hxx>
|
||||
|
||||
#include <variant>
|
||||
|
||||
//! @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;
|
||||
//! aProp.Initialize(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<std::monostate,
|
||||
GeomProp_Plane,
|
||||
GeomProp_Cylinder,
|
||||
GeomProp_Cone,
|
||||
GeomProp_Sphere,
|
||||
GeomProp_Torus,
|
||||
GeomProp_BezierSurface,
|
||||
GeomProp_BSplineSurface,
|
||||
GeomProp_SurfaceOfRevolution,
|
||||
GeomProp_SurfaceOfExtrusion,
|
||||
GeomProp_OffsetSurface,
|
||||
GeomProp_OtherSurface>;
|
||||
|
||||
//! Default constructor - uninitialized state.
|
||||
GeomProp_Surface()
|
||||
: myEvaluator(std::monostate{}),
|
||||
mySurfaceType(GeomAbs_OtherSurface)
|
||||
{
|
||||
}
|
||||
|
||||
//! 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;
|
||||
|
||||
//! Initialize 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
|
||||
Standard_EXPORT void Initialize(const Adaptor3d_Surface& theSurface);
|
||||
|
||||
//! Initialize from geometry handle (auto-detects surface type).
|
||||
//! @param[in] theSurface 3D geometry to evaluate
|
||||
Standard_EXPORT void Initialize(const occ::handle<Geom_Surface>& theSurface);
|
||||
|
||||
//! Returns true if properly initialized.
|
||||
Standard_EXPORT bool IsInitialized() const;
|
||||
|
||||
//! Returns the detected surface type.
|
||||
GeomAbs_SurfaceType GetType() const { return mySurfaceType; }
|
||||
|
||||
//! 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;
|
||||
|
||||
private:
|
||||
//! Initialize from stored adaptor (dispatches to per-geometry evaluator).
|
||||
//! Must be called after myAdaptor is set. Per-geometry evaluators receive
|
||||
//! a non-owning pointer to myAdaptor; their lifetime is managed by the variant.
|
||||
Standard_EXPORT void initFromAdaptor();
|
||||
|
||||
occ::handle<GeomAdaptor_Surface> myAdaptor; //!< Owns the adaptor (ensures lifetime).
|
||||
EvaluatorVariant myEvaluator; //!< Per-geometry evaluator (non-owning pointer to myAdaptor).
|
||||
GeomAbs_SurfaceType mySurfaceType;
|
||||
};
|
||||
|
||||
#endif // _GeomProp_Surface_HeaderFile
|
||||
@@ -0,0 +1,62 @@
|
||||
// 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_SurfaceOfExtrusion.hxx>
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
GeomProp::SurfaceNormalResult GeomProp_SurfaceOfExtrusion::Normal(const double theU,
|
||||
const double theV,
|
||||
const double theTol) const
|
||||
{
|
||||
if (myAdaptor == nullptr)
|
||||
{
|
||||
return {{}, false};
|
||||
}
|
||||
gp_Pnt aPnt;
|
||||
gp_Vec aD1U, aD1V;
|
||||
myAdaptor->D1(theU, theV, aPnt, aD1U, aD1V);
|
||||
return GeomProp::ComputeSurfaceNormal(aD1U, aD1V, theTol);
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
GeomProp::SurfaceCurvatureResult GeomProp_SurfaceOfExtrusion::Curvatures(const double theU,
|
||||
const double theV,
|
||||
const double theTol) const
|
||||
{
|
||||
if (myAdaptor == nullptr)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
gp_Pnt aPnt;
|
||||
gp_Vec aD1U, aD1V, aD2U, aD2V, aD2UV;
|
||||
myAdaptor->D2(theU, theV, aPnt, aD1U, aD1V, aD2U, aD2V, aD2UV);
|
||||
return GeomProp::ComputeSurfaceCurvatures(aD1U, aD1V, aD2U, aD2V, aD2UV, theTol);
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
GeomProp::MeanGaussianResult GeomProp_SurfaceOfExtrusion::MeanGaussian(const double theU,
|
||||
const double theV,
|
||||
const double theTol) const
|
||||
{
|
||||
if (myAdaptor == nullptr)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
gp_Pnt aPnt;
|
||||
gp_Vec aD1U, aD1V, aD2U, aD2V, aD2UV;
|
||||
myAdaptor->D2(theU, theV, aPnt, aD1U, aD1V, aD2U, aD2V, aD2UV);
|
||||
return GeomProp::ComputeMeanGaussian(aD1U, aD1V, aD2U, aD2V, aD2UV, theTol);
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
// 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 <GeomAdaptor_Surface.hxx>
|
||||
#include <GeomProp.hxx>
|
||||
#include <Standard.hxx>
|
||||
#include <Standard_DefineAlloc.hxx>
|
||||
|
||||
//! @brief Local differential properties for a surface of extrusion.
|
||||
//!
|
||||
//! Uses numeric evaluation from adaptor derivatives.
|
||||
//!
|
||||
//! @warning The caller must ensure that the adaptor pointer remains valid
|
||||
//! for the entire lifetime of this object.
|
||||
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)
|
||||
: myAdaptor(theAdaptor)
|
||||
{
|
||||
}
|
||||
|
||||
//! 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;
|
||||
|
||||
//! Returns the adaptor pointer.
|
||||
const GeomAdaptor_Surface* Adaptor() const { return myAdaptor; }
|
||||
|
||||
//! 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;
|
||||
};
|
||||
|
||||
#endif // _GeomProp_SurfaceOfExtrusion_HeaderFile
|
||||
@@ -0,0 +1,62 @@
|
||||
// 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_SurfaceOfRevolution.hxx>
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
GeomProp::SurfaceNormalResult GeomProp_SurfaceOfRevolution::Normal(const double theU,
|
||||
const double theV,
|
||||
const double theTol) const
|
||||
{
|
||||
if (myAdaptor == nullptr)
|
||||
{
|
||||
return {{}, false};
|
||||
}
|
||||
gp_Pnt aPnt;
|
||||
gp_Vec aD1U, aD1V;
|
||||
myAdaptor->D1(theU, theV, aPnt, aD1U, aD1V);
|
||||
return GeomProp::ComputeSurfaceNormal(aD1U, aD1V, theTol);
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
GeomProp::SurfaceCurvatureResult GeomProp_SurfaceOfRevolution::Curvatures(const double theU,
|
||||
const double theV,
|
||||
const double theTol) const
|
||||
{
|
||||
if (myAdaptor == nullptr)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
gp_Pnt aPnt;
|
||||
gp_Vec aD1U, aD1V, aD2U, aD2V, aD2UV;
|
||||
myAdaptor->D2(theU, theV, aPnt, aD1U, aD1V, aD2U, aD2V, aD2UV);
|
||||
return GeomProp::ComputeSurfaceCurvatures(aD1U, aD1V, aD2U, aD2V, aD2UV, theTol);
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
GeomProp::MeanGaussianResult GeomProp_SurfaceOfRevolution::MeanGaussian(const double theU,
|
||||
const double theV,
|
||||
const double theTol) const
|
||||
{
|
||||
if (myAdaptor == nullptr)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
gp_Pnt aPnt;
|
||||
gp_Vec aD1U, aD1V, aD2U, aD2V, aD2UV;
|
||||
myAdaptor->D2(theU, theV, aPnt, aD1U, aD1V, aD2U, aD2V, aD2UV);
|
||||
return GeomProp::ComputeMeanGaussian(aD1U, aD1V, aD2U, aD2V, aD2UV, theTol);
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
// 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 <GeomAdaptor_Surface.hxx>
|
||||
#include <GeomProp.hxx>
|
||||
#include <Standard.hxx>
|
||||
#include <Standard_DefineAlloc.hxx>
|
||||
|
||||
//! @brief Local differential properties for a surface of revolution.
|
||||
//!
|
||||
//! Uses numeric evaluation from adaptor derivatives.
|
||||
//!
|
||||
//! @warning The caller must ensure that the adaptor pointer remains valid
|
||||
//! for the entire lifetime of this object.
|
||||
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)
|
||||
: myAdaptor(theAdaptor)
|
||||
{
|
||||
}
|
||||
|
||||
//! 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;
|
||||
|
||||
//! Returns the adaptor pointer.
|
||||
const GeomAdaptor_Surface* Adaptor() const { return myAdaptor; }
|
||||
|
||||
//! 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;
|
||||
};
|
||||
|
||||
#endif // _GeomProp_SurfaceOfRevolution_HeaderFile
|
||||
@@ -0,0 +1,62 @@
|
||||
// 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_Torus.hxx>
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
GeomProp::SurfaceNormalResult GeomProp_Torus::Normal(const double theU,
|
||||
const double theV,
|
||||
const double theTol) const
|
||||
{
|
||||
if (myAdaptor == nullptr)
|
||||
{
|
||||
return {{}, false};
|
||||
}
|
||||
gp_Pnt aPnt;
|
||||
gp_Vec aD1U, aD1V;
|
||||
myAdaptor->D1(theU, theV, aPnt, aD1U, aD1V);
|
||||
return GeomProp::ComputeSurfaceNormal(aD1U, aD1V, theTol);
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
GeomProp::SurfaceCurvatureResult GeomProp_Torus::Curvatures(const double theU,
|
||||
const double theV,
|
||||
const double theTol) const
|
||||
{
|
||||
if (myAdaptor == nullptr)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
gp_Pnt aPnt;
|
||||
gp_Vec aD1U, aD1V, aD2U, aD2V, aD2UV;
|
||||
myAdaptor->D2(theU, theV, aPnt, aD1U, aD1V, aD2U, aD2V, aD2UV);
|
||||
return GeomProp::ComputeSurfaceCurvatures(aD1U, aD1V, aD2U, aD2V, aD2UV, theTol);
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
GeomProp::MeanGaussianResult GeomProp_Torus::MeanGaussian(const double theU,
|
||||
const double theV,
|
||||
const double theTol) const
|
||||
{
|
||||
if (myAdaptor == nullptr)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
gp_Pnt aPnt;
|
||||
gp_Vec aD1U, aD1V, aD2U, aD2V, aD2UV;
|
||||
myAdaptor->D2(theU, theV, aPnt, aD1U, aD1V, aD2U, aD2V, aD2UV);
|
||||
return GeomProp::ComputeMeanGaussian(aD1U, aD1V, aD2U, aD2V, aD2UV, theTol);
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
// 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 <GeomAdaptor_Surface.hxx>
|
||||
#include <GeomProp.hxx>
|
||||
#include <Standard.hxx>
|
||||
#include <Standard_DefineAlloc.hxx>
|
||||
|
||||
//! @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.
|
||||
//!
|
||||
//! @warning The caller must ensure that the adaptor pointer remains valid
|
||||
//! for the entire lifetime of this object.
|
||||
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)
|
||||
: myAdaptor(theAdaptor)
|
||||
{
|
||||
}
|
||||
|
||||
//! 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;
|
||||
|
||||
//! Returns the adaptor pointer.
|
||||
const GeomAdaptor_Surface* Adaptor() const { return myAdaptor; }
|
||||
|
||||
//! 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;
|
||||
};
|
||||
|
||||
#endif // _GeomProp_Torus_HeaderFile
|
||||
@@ -11,4 +11,5 @@ set(OCCT_TKG3d_LIST_OF_PACKAGES
|
||||
GProp
|
||||
GeomHash
|
||||
GeomEval
|
||||
GeomProp
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user