mirror of
https://github.com/Open-Cascade-SAS/OCCT.git
synced 2026-09-08 05:38:12 +08:00
Modeling Data - Add Geom2dGridEval package for batch 2D curve evaluation (#1079)
Add new Geom2dGridEval package in TKG2d providing batch evaluation of 2D curves at multiple parameter values, mirroring the existing 3D GeomGridEval package in TKG3d. Specialized evaluators use analytical formulas for conics and cache-based evaluation for BSpline/Bezier curves, with a unified std::variant dispatcher for automatic type-based dispatch. New classes: - Geom2dGridEval_Line (header-only), _Circle, _Ellipse, _Hyperbola, _Parabola, _BezierCurve, _BSplineCurve, _OffsetCurve, _OtherCurve - Geom2dGridEval_Curve: unified dispatcher with Initialize() from Adaptor2d_Curve2d or occ::handle<Geom2d_Curve> - Geom2dGridEval.hxx: CurveD1/D2/D3 result structures BSplCLib_Cache changes: - Add D0Local/D1Local/D2Local/D3Local overloads for gp_Pnt2d/gp_Vec2d - Refactor existing 2D D0/D1/D2/D3 methods to delegate to D*Local, consistent with the existing 3D delegation pattern
This commit is contained in:
@@ -10,5 +10,10 @@ set(OCCT_TKG2d_GTests_FILES
|
||||
Geom2dAPI_InterCurveCurve_Test.cxx
|
||||
Geom2dGcc_Circ2d2TanOn_Test.cxx
|
||||
Geom2dGcc_Circ2d2TanRad_Test.cxx
|
||||
Geom2dGridEval_BezierCurve_Test.cxx
|
||||
Geom2dGridEval_Curve_Test.cxx
|
||||
Geom2dGridEval_Ellipse_Test.cxx
|
||||
Geom2dGridEval_Hyperbola_Test.cxx
|
||||
Geom2dGridEval_Parabola_Test.cxx
|
||||
Geom2dHash_CurveHasher_Test.cxx
|
||||
)
|
||||
|
||||
@@ -0,0 +1,190 @@
|
||||
// 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 <gtest/gtest.h>
|
||||
|
||||
#include <Geom2d_BezierCurve.hxx>
|
||||
#include <Geom2dGridEval_BezierCurve.hxx>
|
||||
#include <gp_Pnt2d.hxx>
|
||||
#include <gp_Vec2d.hxx>
|
||||
#include <NCollection_Array1.hxx>
|
||||
|
||||
#include <cmath>
|
||||
|
||||
namespace
|
||||
{
|
||||
const double THE_TOLERANCE = 1e-10;
|
||||
|
||||
NCollection_Array1<double> CreateUniformParams(double theFirst, double theLast, int theNbPoints)
|
||||
{
|
||||
NCollection_Array1<double> aParams(1, theNbPoints);
|
||||
const double aStep = (theLast - theFirst) / (theNbPoints - 1);
|
||||
for (int i = 1; i <= theNbPoints; ++i)
|
||||
{
|
||||
aParams.SetValue(i, theFirst + (i - 1) * aStep);
|
||||
}
|
||||
return aParams;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
TEST(Geom2dGridEval_BezierCurveTest, BasicD0)
|
||||
{
|
||||
NCollection_Array1<gp_Pnt2d> aPoles(1, 4);
|
||||
aPoles.SetValue(1, gp_Pnt2d(0, 0));
|
||||
aPoles.SetValue(2, gp_Pnt2d(1, 2));
|
||||
aPoles.SetValue(3, gp_Pnt2d(3, 2));
|
||||
aPoles.SetValue(4, gp_Pnt2d(4, 0));
|
||||
occ::handle<Geom2d_BezierCurve> aBezier = new Geom2d_BezierCurve(aPoles);
|
||||
|
||||
Geom2dGridEval_BezierCurve anEval(aBezier);
|
||||
EXPECT_FALSE(anEval.Geometry().IsNull());
|
||||
|
||||
NCollection_Array1<double> aParams = CreateUniformParams(0.0, 1.0, 11);
|
||||
|
||||
NCollection_Array1<gp_Pnt2d> aGrid = anEval.EvaluateGrid(aParams);
|
||||
EXPECT_EQ(aGrid.Size(), 11);
|
||||
|
||||
for (int i = 1; i <= 11; ++i)
|
||||
{
|
||||
gp_Pnt2d aExpected = aBezier->Value(aParams.Value(i));
|
||||
EXPECT_NEAR(aGrid.Value(i).Distance(aExpected), 0.0, THE_TOLERANCE);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Geom2dGridEval_BezierCurveTest, D1)
|
||||
{
|
||||
NCollection_Array1<gp_Pnt2d> aPoles(1, 4);
|
||||
aPoles.SetValue(1, gp_Pnt2d(0, 0));
|
||||
aPoles.SetValue(2, gp_Pnt2d(1, 2));
|
||||
aPoles.SetValue(3, gp_Pnt2d(3, 2));
|
||||
aPoles.SetValue(4, gp_Pnt2d(4, 0));
|
||||
occ::handle<Geom2d_BezierCurve> aBezier = new Geom2d_BezierCurve(aPoles);
|
||||
|
||||
Geom2dGridEval_BezierCurve anEval(aBezier);
|
||||
|
||||
NCollection_Array1<double> aParams = CreateUniformParams(0.0, 1.0, 11);
|
||||
|
||||
NCollection_Array1<Geom2dGridEval::CurveD1> aGrid = anEval.EvaluateGridD1(aParams);
|
||||
|
||||
for (int i = 1; i <= 11; ++i)
|
||||
{
|
||||
gp_Pnt2d aPnt;
|
||||
gp_Vec2d aD1;
|
||||
aBezier->D1(aParams.Value(i), aPnt, aD1);
|
||||
EXPECT_NEAR(aGrid.Value(i).Point.Distance(aPnt), 0.0, THE_TOLERANCE);
|
||||
EXPECT_NEAR((aGrid.Value(i).D1 - aD1).Magnitude(), 0.0, THE_TOLERANCE);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Geom2dGridEval_BezierCurveTest, D2)
|
||||
{
|
||||
NCollection_Array1<gp_Pnt2d> aPoles(1, 4);
|
||||
aPoles.SetValue(1, gp_Pnt2d(0, 0));
|
||||
aPoles.SetValue(2, gp_Pnt2d(1, 2));
|
||||
aPoles.SetValue(3, gp_Pnt2d(3, 2));
|
||||
aPoles.SetValue(4, gp_Pnt2d(4, 0));
|
||||
occ::handle<Geom2d_BezierCurve> aBezier = new Geom2d_BezierCurve(aPoles);
|
||||
|
||||
Geom2dGridEval_BezierCurve anEval(aBezier);
|
||||
|
||||
NCollection_Array1<double> aParams = CreateUniformParams(0.0, 1.0, 11);
|
||||
|
||||
NCollection_Array1<Geom2dGridEval::CurveD2> aGrid = anEval.EvaluateGridD2(aParams);
|
||||
|
||||
for (int i = 1; i <= 11; ++i)
|
||||
{
|
||||
gp_Pnt2d aPnt;
|
||||
gp_Vec2d aD1, aD2;
|
||||
aBezier->D2(aParams.Value(i), aPnt, aD1, aD2);
|
||||
EXPECT_NEAR(aGrid.Value(i).Point.Distance(aPnt), 0.0, THE_TOLERANCE);
|
||||
EXPECT_NEAR((aGrid.Value(i).D1 - aD1).Magnitude(), 0.0, THE_TOLERANCE);
|
||||
EXPECT_NEAR((aGrid.Value(i).D2 - aD2).Magnitude(), 0.0, THE_TOLERANCE);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Geom2dGridEval_BezierCurveTest, D3)
|
||||
{
|
||||
NCollection_Array1<gp_Pnt2d> aPoles(1, 4);
|
||||
aPoles.SetValue(1, gp_Pnt2d(0, 0));
|
||||
aPoles.SetValue(2, gp_Pnt2d(1, 2));
|
||||
aPoles.SetValue(3, gp_Pnt2d(3, 2));
|
||||
aPoles.SetValue(4, gp_Pnt2d(4, 0));
|
||||
occ::handle<Geom2d_BezierCurve> aBezier = new Geom2d_BezierCurve(aPoles);
|
||||
|
||||
Geom2dGridEval_BezierCurve anEval(aBezier);
|
||||
|
||||
NCollection_Array1<double> aParams = CreateUniformParams(0.0, 1.0, 11);
|
||||
|
||||
NCollection_Array1<Geom2dGridEval::CurveD3> aGrid = anEval.EvaluateGridD3(aParams);
|
||||
|
||||
for (int i = 1; i <= 11; ++i)
|
||||
{
|
||||
gp_Pnt2d aPnt;
|
||||
gp_Vec2d aD1, aD2, aD3;
|
||||
aBezier->D3(aParams.Value(i), aPnt, aD1, aD2, aD3);
|
||||
EXPECT_NEAR(aGrid.Value(i).Point.Distance(aPnt), 0.0, THE_TOLERANCE);
|
||||
EXPECT_NEAR((aGrid.Value(i).D1 - aD1).Magnitude(), 0.0, THE_TOLERANCE);
|
||||
EXPECT_NEAR((aGrid.Value(i).D2 - aD2).Magnitude(), 0.0, THE_TOLERANCE);
|
||||
EXPECT_NEAR((aGrid.Value(i).D3 - aD3).Magnitude(), 0.0, THE_TOLERANCE);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Geom2dGridEval_BezierCurveTest, DN_BeyondDegree)
|
||||
{
|
||||
NCollection_Array1<gp_Pnt2d> aPoles(1, 4);
|
||||
aPoles.SetValue(1, gp_Pnt2d(0, 0));
|
||||
aPoles.SetValue(2, gp_Pnt2d(1, 2));
|
||||
aPoles.SetValue(3, gp_Pnt2d(3, 2));
|
||||
aPoles.SetValue(4, gp_Pnt2d(4, 0));
|
||||
occ::handle<Geom2d_BezierCurve> aBezier = new Geom2d_BezierCurve(aPoles);
|
||||
|
||||
Geom2dGridEval_BezierCurve anEval(aBezier);
|
||||
|
||||
NCollection_Array1<double> aParams = CreateUniformParams(0.0, 1.0, 11);
|
||||
|
||||
// Degree 3 Bezier, 4th derivative should be zero
|
||||
NCollection_Array1<gp_Vec2d> aGrid = anEval.EvaluateGridDN(aParams, 4);
|
||||
|
||||
for (int i = 1; i <= 11; ++i)
|
||||
{
|
||||
EXPECT_NEAR(aGrid.Value(i).Magnitude(), 0.0, THE_TOLERANCE);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Geom2dGridEval_BezierCurveTest, RationalBezier)
|
||||
{
|
||||
NCollection_Array1<gp_Pnt2d> aPoles(1, 3);
|
||||
NCollection_Array1<double> aWeights(1, 3);
|
||||
|
||||
aPoles.SetValue(1, gp_Pnt2d(1, 0));
|
||||
aPoles.SetValue(2, gp_Pnt2d(1, 1));
|
||||
aPoles.SetValue(3, gp_Pnt2d(0, 1));
|
||||
|
||||
aWeights.SetValue(1, 1.0);
|
||||
aWeights.SetValue(2, 1.0 / std::sqrt(2.0));
|
||||
aWeights.SetValue(3, 1.0);
|
||||
|
||||
occ::handle<Geom2d_BezierCurve> aBezier = new Geom2d_BezierCurve(aPoles, aWeights);
|
||||
|
||||
Geom2dGridEval_BezierCurve anEval(aBezier);
|
||||
|
||||
NCollection_Array1<double> aParams = CreateUniformParams(0.0, 1.0, 21);
|
||||
|
||||
NCollection_Array1<gp_Pnt2d> aGrid = anEval.EvaluateGrid(aParams);
|
||||
|
||||
for (int i = 1; i <= 21; ++i)
|
||||
{
|
||||
gp_Pnt2d aExpected = aBezier->Value(aParams.Value(i));
|
||||
EXPECT_NEAR(aGrid.Value(i).Distance(aExpected), 0.0, THE_TOLERANCE);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,714 @@
|
||||
// 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 <gtest/gtest.h>
|
||||
|
||||
#include <Geom2d_BezierCurve.hxx>
|
||||
#include <Geom2d_BSplineCurve.hxx>
|
||||
#include <Geom2d_Circle.hxx>
|
||||
#include <Geom2d_Ellipse.hxx>
|
||||
#include <Geom2d_Hyperbola.hxx>
|
||||
#include <Geom2d_Line.hxx>
|
||||
#include <Geom2d_OffsetCurve.hxx>
|
||||
#include <Geom2d_Parabola.hxx>
|
||||
#include <Geom2dAdaptor_Curve.hxx>
|
||||
#include <Geom2dGridEval_BSplineCurve.hxx>
|
||||
#include <Geom2dGridEval_Circle.hxx>
|
||||
#include <Geom2dGridEval_Curve.hxx>
|
||||
#include <Geom2dGridEval_Line.hxx>
|
||||
#include <Geom2dGridEval_OtherCurve.hxx>
|
||||
#include <gp_Ax22d.hxx>
|
||||
#include <gp_Circ2d.hxx>
|
||||
#include <gp_Lin2d.hxx>
|
||||
#include <gp_Pnt2d.hxx>
|
||||
#include <NCollection_Array1.hxx>
|
||||
|
||||
#include <cmath>
|
||||
|
||||
namespace
|
||||
{
|
||||
const double THE_TOLERANCE = 1e-10;
|
||||
|
||||
//! Helper function to create uniform parameters
|
||||
NCollection_Array1<double> CreateUniformParams(double theFirst, double theLast, int theNbPoints)
|
||||
{
|
||||
NCollection_Array1<double> aParams(1, theNbPoints);
|
||||
const double aStep = (theLast - theFirst) / (theNbPoints - 1);
|
||||
for (int i = 1; i <= theNbPoints; ++i)
|
||||
{
|
||||
aParams.SetValue(i, theFirst + (i - 1) * aStep);
|
||||
}
|
||||
return aParams;
|
||||
}
|
||||
|
||||
//! Helper function to create a simple 2D B-spline curve
|
||||
occ::handle<Geom2d_BSplineCurve> CreateSimpleBSpline2d()
|
||||
{
|
||||
NCollection_Array1<gp_Pnt2d> aPoles(1, 4);
|
||||
aPoles.SetValue(1, gp_Pnt2d(0, 0));
|
||||
aPoles.SetValue(2, gp_Pnt2d(1, 2));
|
||||
aPoles.SetValue(3, gp_Pnt2d(3, 2));
|
||||
aPoles.SetValue(4, gp_Pnt2d(4, 0));
|
||||
|
||||
NCollection_Array1<double> aKnots(1, 2);
|
||||
NCollection_Array1<int> aMults(1, 2);
|
||||
aKnots.SetValue(1, 0.0);
|
||||
aKnots.SetValue(2, 1.0);
|
||||
aMults.SetValue(1, 4);
|
||||
aMults.SetValue(2, 4);
|
||||
|
||||
return new Geom2d_BSplineCurve(aPoles, aKnots, aMults, 3);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
//==================================================================================================
|
||||
// Tests for Geom2dGridEval_Line
|
||||
//==================================================================================================
|
||||
|
||||
TEST(Geom2dGridEval_LineTest, BasicEvaluation)
|
||||
{
|
||||
occ::handle<Geom2d_Line> aGeomLine = new Geom2d_Line(gp_Pnt2d(0, 0), gp_Dir2d(1, 0));
|
||||
|
||||
Geom2dGridEval_Line anEval(aGeomLine);
|
||||
EXPECT_FALSE(anEval.Geometry().IsNull());
|
||||
|
||||
NCollection_Array1<double> aParams = CreateUniformParams(0.0, 10.0, 11);
|
||||
|
||||
NCollection_Array1<gp_Pnt2d> aGrid = anEval.EvaluateGrid(aParams);
|
||||
EXPECT_EQ(aGrid.Size(), 11);
|
||||
|
||||
for (int i = 1; i <= 11; ++i)
|
||||
{
|
||||
const double t = aParams.Value(i);
|
||||
EXPECT_NEAR(aGrid.Value(i).X(), t, THE_TOLERANCE);
|
||||
EXPECT_NEAR(aGrid.Value(i).Y(), 0.0, THE_TOLERANCE);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Geom2dGridEval_LineTest, NonOriginLine)
|
||||
{
|
||||
occ::handle<Geom2d_Line> aGeomLine = new Geom2d_Line(gp_Pnt2d(1, 2), gp_Dir2d(1, 1));
|
||||
|
||||
Geom2dGridEval_Line anEval(aGeomLine);
|
||||
|
||||
NCollection_Array1<double> aParams = CreateUniformParams(0.0, 5.0, 6);
|
||||
|
||||
NCollection_Array1<gp_Pnt2d> aGrid = anEval.EvaluateGrid(aParams);
|
||||
|
||||
EXPECT_NEAR(aGrid.Value(1).Distance(gp_Pnt2d(1, 2)), 0.0, THE_TOLERANCE);
|
||||
|
||||
const double d = 5.0 / std::sqrt(2.0);
|
||||
EXPECT_NEAR(aGrid.Value(6).Distance(gp_Pnt2d(1 + d, 2 + d)), 0.0, THE_TOLERANCE);
|
||||
}
|
||||
|
||||
TEST(Geom2dGridEval_LineTest, DerivativeD1)
|
||||
{
|
||||
occ::handle<Geom2d_Line> aGeomLine = new Geom2d_Line(gp_Pnt2d(0, 0), gp_Dir2d(1, 2));
|
||||
Geom2dGridEval_Line anEval(aGeomLine);
|
||||
|
||||
NCollection_Array1<double> aParams = CreateUniformParams(0.0, 5.0, 6);
|
||||
|
||||
NCollection_Array1<Geom2dGridEval::CurveD1> aGrid = anEval.EvaluateGridD1(aParams);
|
||||
EXPECT_EQ(aGrid.Size(), 6);
|
||||
|
||||
gp_Dir2d aDir(1, 2);
|
||||
for (int i = 1; i <= 6; ++i)
|
||||
{
|
||||
EXPECT_NEAR(aGrid.Value(i).D1.X(), aDir.X(), THE_TOLERANCE);
|
||||
EXPECT_NEAR(aGrid.Value(i).D1.Y(), aDir.Y(), THE_TOLERANCE);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Geom2dGridEval_LineTest, DerivativeD2D3)
|
||||
{
|
||||
occ::handle<Geom2d_Line> aGeomLine = new Geom2d_Line(gp_Pnt2d(0, 0), gp_Dir2d(1, 0));
|
||||
Geom2dGridEval_Line anEval(aGeomLine);
|
||||
|
||||
NCollection_Array1<double> aParams = CreateUniformParams(0.0, 5.0, 6);
|
||||
|
||||
NCollection_Array1<Geom2dGridEval::CurveD2> aGridD2 = anEval.EvaluateGridD2(aParams);
|
||||
NCollection_Array1<Geom2dGridEval::CurveD3> aGridD3 = anEval.EvaluateGridD3(aParams);
|
||||
|
||||
for (int i = 1; i <= 6; ++i)
|
||||
{
|
||||
EXPECT_NEAR(aGridD2.Value(i).D2.Magnitude(), 0.0, THE_TOLERANCE);
|
||||
EXPECT_NEAR(aGridD3.Value(i).D2.Magnitude(), 0.0, THE_TOLERANCE);
|
||||
EXPECT_NEAR(aGridD3.Value(i).D3.Magnitude(), 0.0, THE_TOLERANCE);
|
||||
}
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
// Tests for Geom2dGridEval_Circle
|
||||
//==================================================================================================
|
||||
|
||||
TEST(Geom2dGridEval_CircleTest, BasicEvaluation)
|
||||
{
|
||||
occ::handle<Geom2d_Circle> aGeomCircle =
|
||||
new Geom2d_Circle(gp_Ax22d(gp_Pnt2d(0, 0), gp_Dir2d(1, 0)), 2.0);
|
||||
|
||||
Geom2dGridEval_Circle anEval(aGeomCircle);
|
||||
EXPECT_FALSE(anEval.Geometry().IsNull());
|
||||
|
||||
NCollection_Array1<double> aParams(1, 5);
|
||||
aParams.SetValue(1, 0.0);
|
||||
aParams.SetValue(2, M_PI / 2);
|
||||
aParams.SetValue(3, M_PI);
|
||||
aParams.SetValue(4, 3 * M_PI / 2);
|
||||
aParams.SetValue(5, 2 * M_PI);
|
||||
|
||||
NCollection_Array1<gp_Pnt2d> aGrid = anEval.EvaluateGrid(aParams);
|
||||
|
||||
EXPECT_NEAR(aGrid.Value(1).X(), 2.0, THE_TOLERANCE);
|
||||
EXPECT_NEAR(aGrid.Value(1).Y(), 0.0, THE_TOLERANCE);
|
||||
|
||||
EXPECT_NEAR(aGrid.Value(2).X(), 0.0, THE_TOLERANCE);
|
||||
EXPECT_NEAR(aGrid.Value(2).Y(), 2.0, THE_TOLERANCE);
|
||||
|
||||
EXPECT_NEAR(aGrid.Value(3).X(), -2.0, THE_TOLERANCE);
|
||||
EXPECT_NEAR(aGrid.Value(3).Y(), 0.0, THE_TOLERANCE);
|
||||
|
||||
EXPECT_NEAR(aGrid.Value(4).X(), 0.0, THE_TOLERANCE);
|
||||
EXPECT_NEAR(aGrid.Value(4).Y(), -2.0, THE_TOLERANCE);
|
||||
|
||||
EXPECT_NEAR(aGrid.Value(5).X(), 2.0, THE_TOLERANCE);
|
||||
EXPECT_NEAR(aGrid.Value(5).Y(), 0.0, THE_TOLERANCE);
|
||||
}
|
||||
|
||||
TEST(Geom2dGridEval_CircleTest, DerivativeD1)
|
||||
{
|
||||
occ::handle<Geom2d_Circle> aGeomCircle =
|
||||
new Geom2d_Circle(gp_Ax22d(gp_Pnt2d(0, 0), gp_Dir2d(1, 0)), 2.0);
|
||||
Geom2dGridEval_Circle anEval(aGeomCircle);
|
||||
|
||||
NCollection_Array1<double> aParams = CreateUniformParams(0.0, 2 * M_PI, 9);
|
||||
|
||||
NCollection_Array1<Geom2dGridEval::CurveD1> aGrid = anEval.EvaluateGridD1(aParams);
|
||||
|
||||
for (int i = 1; i <= 9; ++i)
|
||||
{
|
||||
gp_Pnt2d aPnt;
|
||||
gp_Vec2d aD1;
|
||||
aGeomCircle->D1(aParams.Value(i), aPnt, aD1);
|
||||
EXPECT_NEAR(aGrid.Value(i).Point.Distance(aPnt), 0.0, THE_TOLERANCE);
|
||||
EXPECT_NEAR((aGrid.Value(i).D1 - aD1).Magnitude(), 0.0, THE_TOLERANCE);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Geom2dGridEval_CircleTest, DerivativeD2)
|
||||
{
|
||||
occ::handle<Geom2d_Circle> aGeomCircle =
|
||||
new Geom2d_Circle(gp_Ax22d(gp_Pnt2d(0, 0), gp_Dir2d(1, 0)), 2.0);
|
||||
Geom2dGridEval_Circle anEval(aGeomCircle);
|
||||
|
||||
NCollection_Array1<double> aParams = CreateUniformParams(0.0, 2 * M_PI, 9);
|
||||
|
||||
NCollection_Array1<Geom2dGridEval::CurveD2> aGrid = anEval.EvaluateGridD2(aParams);
|
||||
|
||||
for (int i = 1; i <= 9; ++i)
|
||||
{
|
||||
gp_Pnt2d aPnt;
|
||||
gp_Vec2d aD1, aD2;
|
||||
aGeomCircle->D2(aParams.Value(i), aPnt, aD1, aD2);
|
||||
EXPECT_NEAR(aGrid.Value(i).Point.Distance(aPnt), 0.0, THE_TOLERANCE);
|
||||
EXPECT_NEAR((aGrid.Value(i).D1 - aD1).Magnitude(), 0.0, THE_TOLERANCE);
|
||||
EXPECT_NEAR((aGrid.Value(i).D2 - aD2).Magnitude(), 0.0, THE_TOLERANCE);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Geom2dGridEval_CircleTest, DerivativeD3)
|
||||
{
|
||||
occ::handle<Geom2d_Circle> aGeomCircle =
|
||||
new Geom2d_Circle(gp_Ax22d(gp_Pnt2d(0, 0), gp_Dir2d(1, 0)), 2.0);
|
||||
Geom2dGridEval_Circle anEval(aGeomCircle);
|
||||
|
||||
NCollection_Array1<double> aParams = CreateUniformParams(0.0, 2 * M_PI, 9);
|
||||
|
||||
NCollection_Array1<Geom2dGridEval::CurveD3> aGrid = anEval.EvaluateGridD3(aParams);
|
||||
|
||||
for (int i = 1; i <= 9; ++i)
|
||||
{
|
||||
gp_Pnt2d aPnt;
|
||||
gp_Vec2d aD1, aD2, aD3;
|
||||
aGeomCircle->D3(aParams.Value(i), aPnt, aD1, aD2, aD3);
|
||||
EXPECT_NEAR(aGrid.Value(i).Point.Distance(aPnt), 0.0, THE_TOLERANCE);
|
||||
EXPECT_NEAR((aGrid.Value(i).D1 - aD1).Magnitude(), 0.0, THE_TOLERANCE);
|
||||
EXPECT_NEAR((aGrid.Value(i).D2 - aD2).Magnitude(), 0.0, THE_TOLERANCE);
|
||||
EXPECT_NEAR((aGrid.Value(i).D3 - aD3).Magnitude(), 0.0, THE_TOLERANCE);
|
||||
}
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
// Tests for Geom2dGridEval_BSplineCurve
|
||||
//==================================================================================================
|
||||
|
||||
TEST(Geom2dGridEval_BSplineCurveTest, BasicEvaluation)
|
||||
{
|
||||
occ::handle<Geom2d_BSplineCurve> aCurve = CreateSimpleBSpline2d();
|
||||
|
||||
Geom2dGridEval_BSplineCurve anEval(aCurve);
|
||||
EXPECT_FALSE(anEval.Geometry().IsNull());
|
||||
|
||||
NCollection_Array1<double> aParams = CreateUniformParams(0.0, 1.0, 11);
|
||||
|
||||
NCollection_Array1<gp_Pnt2d> aGrid = anEval.EvaluateGrid(aParams);
|
||||
EXPECT_EQ(aGrid.Size(), 11);
|
||||
|
||||
for (int i = 1; i <= 11; ++i)
|
||||
{
|
||||
gp_Pnt2d aExpected = aCurve->Value(aParams.Value(i));
|
||||
EXPECT_NEAR(aGrid.Value(i).Distance(aExpected), 0.0, THE_TOLERANCE);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Geom2dGridEval_BSplineCurveTest, EndpointsMatch)
|
||||
{
|
||||
occ::handle<Geom2d_BSplineCurve> aCurve = CreateSimpleBSpline2d();
|
||||
|
||||
Geom2dGridEval_BSplineCurve anEval(aCurve);
|
||||
|
||||
NCollection_Array1<double> aParams(1, 2);
|
||||
aParams.SetValue(1, 0.0);
|
||||
aParams.SetValue(2, 1.0);
|
||||
|
||||
NCollection_Array1<gp_Pnt2d> aGrid = anEval.EvaluateGrid(aParams);
|
||||
|
||||
EXPECT_NEAR(aGrid.Value(1).Distance(gp_Pnt2d(0, 0)), 0.0, THE_TOLERANCE);
|
||||
EXPECT_NEAR(aGrid.Value(2).Distance(gp_Pnt2d(4, 0)), 0.0, THE_TOLERANCE);
|
||||
}
|
||||
|
||||
TEST(Geom2dGridEval_BSplineCurveTest, DerivativeD1)
|
||||
{
|
||||
occ::handle<Geom2d_BSplineCurve> aCurve = CreateSimpleBSpline2d();
|
||||
Geom2dGridEval_BSplineCurve anEval(aCurve);
|
||||
|
||||
NCollection_Array1<double> aParams = CreateUniformParams(0.0, 1.0, 11);
|
||||
|
||||
NCollection_Array1<Geom2dGridEval::CurveD1> aGrid = anEval.EvaluateGridD1(aParams);
|
||||
|
||||
for (int i = 1; i <= 11; ++i)
|
||||
{
|
||||
gp_Pnt2d aPnt;
|
||||
gp_Vec2d aD1;
|
||||
aCurve->D1(aParams.Value(i), aPnt, aD1);
|
||||
EXPECT_NEAR(aGrid.Value(i).Point.Distance(aPnt), 0.0, THE_TOLERANCE);
|
||||
EXPECT_NEAR((aGrid.Value(i).D1 - aD1).Magnitude(), 0.0, THE_TOLERANCE);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Geom2dGridEval_BSplineCurveTest, DerivativeD2)
|
||||
{
|
||||
occ::handle<Geom2d_BSplineCurve> aCurve = CreateSimpleBSpline2d();
|
||||
Geom2dGridEval_BSplineCurve anEval(aCurve);
|
||||
|
||||
NCollection_Array1<double> aParams = CreateUniformParams(0.0, 1.0, 11);
|
||||
|
||||
NCollection_Array1<Geom2dGridEval::CurveD2> aGrid = anEval.EvaluateGridD2(aParams);
|
||||
|
||||
for (int i = 1; i <= 11; ++i)
|
||||
{
|
||||
gp_Pnt2d aPnt;
|
||||
gp_Vec2d aD1, aD2;
|
||||
aCurve->D2(aParams.Value(i), aPnt, aD1, aD2);
|
||||
EXPECT_NEAR(aGrid.Value(i).Point.Distance(aPnt), 0.0, THE_TOLERANCE);
|
||||
EXPECT_NEAR((aGrid.Value(i).D1 - aD1).Magnitude(), 0.0, THE_TOLERANCE);
|
||||
EXPECT_NEAR((aGrid.Value(i).D2 - aD2).Magnitude(), 0.0, THE_TOLERANCE);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Geom2dGridEval_BSplineCurveTest, DerivativeD3)
|
||||
{
|
||||
occ::handle<Geom2d_BSplineCurve> aCurve = CreateSimpleBSpline2d();
|
||||
Geom2dGridEval_BSplineCurve anEval(aCurve);
|
||||
|
||||
NCollection_Array1<double> aParams = CreateUniformParams(0.0, 1.0, 11);
|
||||
|
||||
NCollection_Array1<Geom2dGridEval::CurveD3> aGrid = anEval.EvaluateGridD3(aParams);
|
||||
|
||||
for (int i = 1; i <= 11; ++i)
|
||||
{
|
||||
gp_Pnt2d aPnt;
|
||||
gp_Vec2d aD1, aD2, aD3;
|
||||
aCurve->D3(aParams.Value(i), aPnt, aD1, aD2, aD3);
|
||||
EXPECT_NEAR(aGrid.Value(i).Point.Distance(aPnt), 0.0, THE_TOLERANCE);
|
||||
EXPECT_NEAR((aGrid.Value(i).D1 - aD1).Magnitude(), 0.0, THE_TOLERANCE);
|
||||
EXPECT_NEAR((aGrid.Value(i).D2 - aD2).Magnitude(), 0.0, THE_TOLERANCE);
|
||||
EXPECT_NEAR((aGrid.Value(i).D3 - aD3).Magnitude(), 0.0, THE_TOLERANCE);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Geom2dGridEval_BSplineCurveTest, DerivativeDN_BeyondDegree)
|
||||
{
|
||||
occ::handle<Geom2d_BSplineCurve> aCurve = CreateSimpleBSpline2d();
|
||||
Geom2dGridEval_BSplineCurve anEval(aCurve);
|
||||
|
||||
NCollection_Array1<double> aParams = CreateUniformParams(0.0, 1.0, 11);
|
||||
|
||||
NCollection_Array1<gp_Vec2d> aGrid = anEval.EvaluateGridDN(aParams, 4);
|
||||
|
||||
for (int i = 1; i <= 11; ++i)
|
||||
{
|
||||
EXPECT_NEAR(aGrid.Value(i).Magnitude(), 0.0, THE_TOLERANCE);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Geom2dGridEval_BSplineCurveTest, MultiSpanBSpline)
|
||||
{
|
||||
NCollection_Array1<gp_Pnt2d> aPoles(1, 6);
|
||||
aPoles.SetValue(1, gp_Pnt2d(0, 0));
|
||||
aPoles.SetValue(2, gp_Pnt2d(1, 2));
|
||||
aPoles.SetValue(3, gp_Pnt2d(2, 2));
|
||||
aPoles.SetValue(4, gp_Pnt2d(3, 0));
|
||||
aPoles.SetValue(5, gp_Pnt2d(4, -1));
|
||||
aPoles.SetValue(6, gp_Pnt2d(5, 0));
|
||||
|
||||
NCollection_Array1<double> aKnots(1, 3);
|
||||
NCollection_Array1<int> aMults(1, 3);
|
||||
aKnots.SetValue(1, 0.0);
|
||||
aKnots.SetValue(2, 0.5);
|
||||
aKnots.SetValue(3, 1.0);
|
||||
aMults.SetValue(1, 4);
|
||||
aMults.SetValue(2, 2);
|
||||
aMults.SetValue(3, 4);
|
||||
|
||||
occ::handle<Geom2d_BSplineCurve> aCurve = new Geom2d_BSplineCurve(aPoles, aKnots, aMults, 3);
|
||||
|
||||
Geom2dGridEval_BSplineCurve anEval(aCurve);
|
||||
|
||||
NCollection_Array1<double> aParams = CreateUniformParams(0.0, 1.0, 31);
|
||||
|
||||
NCollection_Array1<gp_Pnt2d> aGrid = anEval.EvaluateGrid(aParams);
|
||||
|
||||
for (int i = 1; i <= 31; ++i)
|
||||
{
|
||||
gp_Pnt2d aExpected = aCurve->Value(aParams.Value(i));
|
||||
EXPECT_NEAR(aGrid.Value(i).Distance(aExpected), 0.0, THE_TOLERANCE);
|
||||
}
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
// Tests for Geom2dGridEval_Curve (unified dispatcher)
|
||||
//==================================================================================================
|
||||
|
||||
TEST(Geom2dGridEval_CurveTest, LineDispatch)
|
||||
{
|
||||
occ::handle<Geom2d_Line> aGeomLine = new Geom2d_Line(gp_Pnt2d(0, 0), gp_Dir2d(1, 0));
|
||||
Geom2dAdaptor_Curve anAdaptor(aGeomLine);
|
||||
|
||||
Geom2dGridEval_Curve anEval;
|
||||
anEval.Initialize(anAdaptor);
|
||||
EXPECT_TRUE(anEval.IsInitialized());
|
||||
EXPECT_EQ(anEval.GetType(), GeomAbs_Line);
|
||||
|
||||
NCollection_Array1<double> aParams = CreateUniformParams(0.0, 10.0, 11);
|
||||
|
||||
NCollection_Array1<gp_Pnt2d> aGrid = anEval.EvaluateGrid(aParams);
|
||||
EXPECT_EQ(aGrid.Size(), 11);
|
||||
|
||||
for (int i = 1; i <= 11; ++i)
|
||||
{
|
||||
gp_Pnt2d aExpected = aGeomLine->Value(aParams.Value(i));
|
||||
EXPECT_NEAR(aGrid.Value(i).Distance(aExpected), 0.0, THE_TOLERANCE);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Geom2dGridEval_CurveTest, CircleDispatch)
|
||||
{
|
||||
occ::handle<Geom2d_Circle> aGeomCircle =
|
||||
new Geom2d_Circle(gp_Ax22d(gp_Pnt2d(0, 0), gp_Dir2d(1, 0)), 2.0);
|
||||
Geom2dAdaptor_Curve anAdaptor(aGeomCircle);
|
||||
|
||||
Geom2dGridEval_Curve anEval;
|
||||
anEval.Initialize(anAdaptor);
|
||||
EXPECT_TRUE(anEval.IsInitialized());
|
||||
EXPECT_EQ(anEval.GetType(), GeomAbs_Circle);
|
||||
|
||||
NCollection_Array1<double> aParams = CreateUniformParams(0.0, 2 * M_PI, 17);
|
||||
|
||||
NCollection_Array1<gp_Pnt2d> aGrid = anEval.EvaluateGrid(aParams);
|
||||
|
||||
for (int i = 1; i <= 17; ++i)
|
||||
{
|
||||
gp_Pnt2d aExpected = aGeomCircle->Value(aParams.Value(i));
|
||||
EXPECT_NEAR(aGrid.Value(i).Distance(aExpected), 0.0, THE_TOLERANCE);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Geom2dGridEval_CurveTest, EllipseDispatch)
|
||||
{
|
||||
occ::handle<Geom2d_Ellipse> anEllipse =
|
||||
new Geom2d_Ellipse(gp_Ax22d(gp_Pnt2d(0, 0), gp_Dir2d(1, 0)), 3.0, 2.0);
|
||||
Geom2dAdaptor_Curve anAdaptor(anEllipse);
|
||||
|
||||
Geom2dGridEval_Curve anEval;
|
||||
anEval.Initialize(anAdaptor);
|
||||
EXPECT_TRUE(anEval.IsInitialized());
|
||||
EXPECT_EQ(anEval.GetType(), GeomAbs_Ellipse);
|
||||
|
||||
NCollection_Array1<double> aParams = CreateUniformParams(0.0, 2 * M_PI, 13);
|
||||
|
||||
NCollection_Array1<gp_Pnt2d> aGrid = anEval.EvaluateGrid(aParams);
|
||||
|
||||
for (int i = 1; i <= 13; ++i)
|
||||
{
|
||||
gp_Pnt2d aExpected = anEllipse->Value(aParams.Value(i));
|
||||
EXPECT_NEAR(aGrid.Value(i).Distance(aExpected), 0.0, THE_TOLERANCE);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Geom2dGridEval_CurveTest, HyperbolaDispatch)
|
||||
{
|
||||
occ::handle<Geom2d_Hyperbola> aHypr =
|
||||
new Geom2d_Hyperbola(gp_Ax22d(gp_Pnt2d(0, 0), gp_Dir2d(1, 0)), 3.0, 2.0);
|
||||
Geom2dAdaptor_Curve anAdaptor(aHypr);
|
||||
|
||||
Geom2dGridEval_Curve anEval;
|
||||
anEval.Initialize(anAdaptor);
|
||||
EXPECT_TRUE(anEval.IsInitialized());
|
||||
EXPECT_EQ(anEval.GetType(), GeomAbs_Hyperbola);
|
||||
|
||||
NCollection_Array1<double> aParams = CreateUniformParams(-2.0, 2.0, 11);
|
||||
|
||||
NCollection_Array1<gp_Pnt2d> aGrid = anEval.EvaluateGrid(aParams);
|
||||
|
||||
for (int i = 1; i <= 11; ++i)
|
||||
{
|
||||
gp_Pnt2d aExpected = aHypr->Value(aParams.Value(i));
|
||||
EXPECT_NEAR(aGrid.Value(i).Distance(aExpected), 0.0, THE_TOLERANCE);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Geom2dGridEval_CurveTest, ParabolaDispatch)
|
||||
{
|
||||
occ::handle<Geom2d_Parabola> aParab =
|
||||
new Geom2d_Parabola(gp_Ax22d(gp_Pnt2d(0, 0), gp_Dir2d(1, 0)), 1.0);
|
||||
Geom2dAdaptor_Curve anAdaptor(aParab);
|
||||
|
||||
Geom2dGridEval_Curve anEval;
|
||||
anEval.Initialize(anAdaptor);
|
||||
EXPECT_TRUE(anEval.IsInitialized());
|
||||
EXPECT_EQ(anEval.GetType(), GeomAbs_Parabola);
|
||||
|
||||
NCollection_Array1<double> aParams = CreateUniformParams(-2.0, 2.0, 11);
|
||||
|
||||
NCollection_Array1<gp_Pnt2d> aGrid = anEval.EvaluateGrid(aParams);
|
||||
|
||||
for (int i = 1; i <= 11; ++i)
|
||||
{
|
||||
gp_Pnt2d aExpected = aParab->Value(aParams.Value(i));
|
||||
EXPECT_NEAR(aGrid.Value(i).Distance(aExpected), 0.0, THE_TOLERANCE);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Geom2dGridEval_CurveTest, BSplineDispatch)
|
||||
{
|
||||
occ::handle<Geom2d_BSplineCurve> aCurve = CreateSimpleBSpline2d();
|
||||
Geom2dAdaptor_Curve anAdaptor(aCurve);
|
||||
|
||||
Geom2dGridEval_Curve anEval;
|
||||
anEval.Initialize(anAdaptor);
|
||||
EXPECT_TRUE(anEval.IsInitialized());
|
||||
EXPECT_EQ(anEval.GetType(), GeomAbs_BSplineCurve);
|
||||
|
||||
NCollection_Array1<double> aParams = CreateUniformParams(0.0, 1.0, 21);
|
||||
|
||||
NCollection_Array1<gp_Pnt2d> aGrid = anEval.EvaluateGrid(aParams);
|
||||
|
||||
for (int i = 1; i <= 21; ++i)
|
||||
{
|
||||
gp_Pnt2d aExpected = aCurve->Value(aParams.Value(i));
|
||||
EXPECT_NEAR(aGrid.Value(i).Distance(aExpected), 0.0, THE_TOLERANCE);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Geom2dGridEval_CurveTest, BezierCurveDispatch)
|
||||
{
|
||||
NCollection_Array1<gp_Pnt2d> aPoles(1, 4);
|
||||
aPoles.SetValue(1, gp_Pnt2d(0, 0));
|
||||
aPoles.SetValue(2, gp_Pnt2d(1, 2));
|
||||
aPoles.SetValue(3, gp_Pnt2d(3, 2));
|
||||
aPoles.SetValue(4, gp_Pnt2d(4, 0));
|
||||
occ::handle<Geom2d_BezierCurve> aBezier = new Geom2d_BezierCurve(aPoles);
|
||||
Geom2dAdaptor_Curve anAdaptor(aBezier);
|
||||
|
||||
Geom2dGridEval_Curve anEval;
|
||||
anEval.Initialize(anAdaptor);
|
||||
EXPECT_TRUE(anEval.IsInitialized());
|
||||
EXPECT_EQ(anEval.GetType(), GeomAbs_BezierCurve);
|
||||
|
||||
NCollection_Array1<double> aParams = CreateUniformParams(0.0, 1.0, 11);
|
||||
|
||||
NCollection_Array1<gp_Pnt2d> aGrid = anEval.EvaluateGrid(aParams);
|
||||
|
||||
for (int i = 1; i <= 11; ++i)
|
||||
{
|
||||
gp_Pnt2d aExpected = aBezier->Value(aParams.Value(i));
|
||||
EXPECT_NEAR(aGrid.Value(i).Distance(aExpected), 0.0, THE_TOLERANCE);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Geom2dGridEval_CurveTest, OffsetCurveDispatch)
|
||||
{
|
||||
occ::handle<Geom2d_Line> aLine = new Geom2d_Line(gp_Pnt2d(0, 0), gp_Dir2d(1, 0));
|
||||
occ::handle<Geom2d_OffsetCurve> anOffset = new Geom2d_OffsetCurve(aLine, 1.0);
|
||||
|
||||
Geom2dGridEval_Curve anEval;
|
||||
anEval.Initialize(anOffset);
|
||||
EXPECT_TRUE(anEval.IsInitialized());
|
||||
EXPECT_EQ(anEval.GetType(), GeomAbs_OffsetCurve);
|
||||
|
||||
NCollection_Array1<double> aParams = CreateUniformParams(0.0, 5.0, 6);
|
||||
|
||||
NCollection_Array1<gp_Pnt2d> aGrid = anEval.EvaluateGrid(aParams);
|
||||
|
||||
for (int i = 1; i <= 6; ++i)
|
||||
{
|
||||
gp_Pnt2d aExpected = anOffset->Value(aParams.Value(i));
|
||||
EXPECT_NEAR(aGrid.Value(i).Distance(aExpected), 0.0, THE_TOLERANCE);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Geom2dGridEval_CurveTest, DirectHandleInit)
|
||||
{
|
||||
occ::handle<Geom2d_Line> aGeomLine = new Geom2d_Line(gp_Pnt2d(0, 0), gp_Dir2d(1, 0));
|
||||
|
||||
Geom2dGridEval_Curve anEval;
|
||||
anEval.Initialize(aGeomLine);
|
||||
EXPECT_TRUE(anEval.IsInitialized());
|
||||
EXPECT_EQ(anEval.GetType(), GeomAbs_Line);
|
||||
|
||||
NCollection_Array1<double> aParams = CreateUniformParams(0.0, 10.0, 11);
|
||||
|
||||
NCollection_Array1<gp_Pnt2d> aGrid = anEval.EvaluateGrid(aParams);
|
||||
EXPECT_EQ(aGrid.Size(), 11);
|
||||
EXPECT_NEAR(aGrid.Value(1).X(), 0.0, THE_TOLERANCE);
|
||||
}
|
||||
|
||||
TEST(Geom2dGridEval_CurveTest, UninitializedState)
|
||||
{
|
||||
Geom2dGridEval_Curve anEval;
|
||||
EXPECT_FALSE(anEval.IsInitialized());
|
||||
|
||||
NCollection_Array1<double> aEmptyParams;
|
||||
NCollection_Array1<gp_Pnt2d> aGrid = anEval.EvaluateGrid(aEmptyParams);
|
||||
EXPECT_TRUE(aGrid.IsEmpty());
|
||||
}
|
||||
|
||||
TEST(Geom2dGridEval_CurveTest, EmptyParams)
|
||||
{
|
||||
occ::handle<Geom2d_Line> aGeomLine = new Geom2d_Line(gp_Pnt2d(0, 0), gp_Dir2d(1, 0));
|
||||
Geom2dAdaptor_Curve anAdaptor(aGeomLine);
|
||||
|
||||
Geom2dGridEval_Curve anEval;
|
||||
anEval.Initialize(anAdaptor);
|
||||
EXPECT_TRUE(anEval.IsInitialized());
|
||||
|
||||
NCollection_Array1<double> aEmptyParams;
|
||||
NCollection_Array1<gp_Pnt2d> aGrid = anEval.EvaluateGrid(aEmptyParams);
|
||||
EXPECT_TRUE(aGrid.IsEmpty());
|
||||
}
|
||||
|
||||
TEST(Geom2dGridEval_CurveTest, UnifiedDerivativeD1)
|
||||
{
|
||||
occ::handle<Geom2d_Circle> aGeomCircle =
|
||||
new Geom2d_Circle(gp_Ax22d(gp_Pnt2d(0, 0), gp_Dir2d(1, 0)), 2.0);
|
||||
Geom2dAdaptor_Curve anAdaptor(aGeomCircle);
|
||||
|
||||
Geom2dGridEval_Curve anEval;
|
||||
anEval.Initialize(anAdaptor);
|
||||
|
||||
NCollection_Array1<double> aParams = CreateUniformParams(0.0, 2 * M_PI, 9);
|
||||
|
||||
NCollection_Array1<Geom2dGridEval::CurveD1> aGrid = anEval.EvaluateGridD1(aParams);
|
||||
|
||||
for (int i = 1; i <= 9; ++i)
|
||||
{
|
||||
gp_Pnt2d aPnt;
|
||||
gp_Vec2d aD1;
|
||||
aGeomCircle->D1(aParams.Value(i), aPnt, aD1);
|
||||
EXPECT_NEAR(aGrid.Value(i).Point.Distance(aPnt), 0.0, THE_TOLERANCE);
|
||||
EXPECT_NEAR((aGrid.Value(i).D1 - aD1).Magnitude(), 0.0, THE_TOLERANCE);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Geom2dGridEval_CurveTest, UnifiedDerivativeD2)
|
||||
{
|
||||
occ::handle<Geom2d_BSplineCurve> aCurve = CreateSimpleBSpline2d();
|
||||
Geom2dAdaptor_Curve anAdaptor(aCurve);
|
||||
|
||||
Geom2dGridEval_Curve anEval;
|
||||
anEval.Initialize(anAdaptor);
|
||||
|
||||
NCollection_Array1<double> aParams = CreateUniformParams(0.0, 1.0, 11);
|
||||
|
||||
NCollection_Array1<Geom2dGridEval::CurveD2> aGrid = anEval.EvaluateGridD2(aParams);
|
||||
|
||||
for (int i = 1; i <= 11; ++i)
|
||||
{
|
||||
gp_Pnt2d aPnt;
|
||||
gp_Vec2d aD1, aD2;
|
||||
aCurve->D2(aParams.Value(i), aPnt, aD1, aD2);
|
||||
EXPECT_NEAR(aGrid.Value(i).Point.Distance(aPnt), 0.0, THE_TOLERANCE);
|
||||
EXPECT_NEAR((aGrid.Value(i).D1 - aD1).Magnitude(), 0.0, THE_TOLERANCE);
|
||||
EXPECT_NEAR((aGrid.Value(i).D2 - aD2).Magnitude(), 0.0, THE_TOLERANCE);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Geom2dGridEval_CurveTest, UnifiedDerivativeD3)
|
||||
{
|
||||
occ::handle<Geom2d_BSplineCurve> aCurve = CreateSimpleBSpline2d();
|
||||
Geom2dAdaptor_Curve anAdaptor(aCurve);
|
||||
|
||||
Geom2dGridEval_Curve anEval;
|
||||
anEval.Initialize(anAdaptor);
|
||||
|
||||
NCollection_Array1<double> aParams = CreateUniformParams(0.0, 1.0, 11);
|
||||
|
||||
NCollection_Array1<Geom2dGridEval::CurveD3> aGrid = anEval.EvaluateGridD3(aParams);
|
||||
|
||||
for (int i = 1; i <= 11; ++i)
|
||||
{
|
||||
gp_Pnt2d aPnt;
|
||||
gp_Vec2d aD1, aD2, aD3;
|
||||
aCurve->D3(aParams.Value(i), aPnt, aD1, aD2, aD3);
|
||||
EXPECT_NEAR(aGrid.Value(i).Point.Distance(aPnt), 0.0, THE_TOLERANCE);
|
||||
EXPECT_NEAR((aGrid.Value(i).D1 - aD1).Magnitude(), 0.0, THE_TOLERANCE);
|
||||
EXPECT_NEAR((aGrid.Value(i).D2 - aD2).Magnitude(), 0.0, THE_TOLERANCE);
|
||||
EXPECT_NEAR((aGrid.Value(i).D3 - aD3).Magnitude(), 0.0, THE_TOLERANCE);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Geom2dGridEval_CurveTest, OffsetCurveDerivativeD3)
|
||||
{
|
||||
occ::handle<Geom2d_Circle> aCircle =
|
||||
new Geom2d_Circle(gp_Ax22d(gp_Pnt2d(0, 0), gp_Dir2d(1, 0)), 2.0);
|
||||
occ::handle<Geom2d_OffsetCurve> anOffset = new Geom2d_OffsetCurve(aCircle, 0.5);
|
||||
|
||||
Geom2dGridEval_Curve anEval;
|
||||
anEval.Initialize(anOffset);
|
||||
EXPECT_EQ(anEval.GetType(), GeomAbs_OffsetCurve);
|
||||
|
||||
NCollection_Array1<double> aParams = CreateUniformParams(0.0, 2 * M_PI, 9);
|
||||
|
||||
NCollection_Array1<Geom2dGridEval::CurveD3> aGrid = anEval.EvaluateGridD3(aParams);
|
||||
|
||||
for (int i = 1; i <= 9; ++i)
|
||||
{
|
||||
gp_Pnt2d aPnt;
|
||||
gp_Vec2d aD1, aD2, aD3;
|
||||
anOffset->D3(aParams.Value(i), aPnt, aD1, aD2, aD3);
|
||||
EXPECT_NEAR(aGrid.Value(i).Point.Distance(aPnt), 0.0, THE_TOLERANCE);
|
||||
EXPECT_NEAR((aGrid.Value(i).D1 - aD1).Magnitude(), 0.0, THE_TOLERANCE);
|
||||
EXPECT_NEAR((aGrid.Value(i).D2 - aD2).Magnitude(), 0.0, THE_TOLERANCE);
|
||||
EXPECT_NEAR((aGrid.Value(i).D3 - aD3).Magnitude(), 0.0, THE_TOLERANCE);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
// 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 <gtest/gtest.h>
|
||||
|
||||
#include <Geom2d_Ellipse.hxx>
|
||||
#include <Geom2dGridEval_Ellipse.hxx>
|
||||
#include <gp_Ax22d.hxx>
|
||||
#include <gp_Pnt2d.hxx>
|
||||
#include <gp_Vec2d.hxx>
|
||||
#include <NCollection_Array1.hxx>
|
||||
|
||||
#include <cmath>
|
||||
|
||||
namespace
|
||||
{
|
||||
const double THE_TOLERANCE = 1e-10;
|
||||
|
||||
NCollection_Array1<double> CreateUniformParams(double theFirst, double theLast, int theNbPoints)
|
||||
{
|
||||
NCollection_Array1<double> aParams(1, theNbPoints);
|
||||
const double aStep = (theLast - theFirst) / (theNbPoints - 1);
|
||||
for (int i = 1; i <= theNbPoints; ++i)
|
||||
{
|
||||
aParams.SetValue(i, theFirst + (i - 1) * aStep);
|
||||
}
|
||||
return aParams;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
TEST(Geom2dGridEval_EllipseTest, BasicD0)
|
||||
{
|
||||
occ::handle<Geom2d_Ellipse> anEllipse =
|
||||
new Geom2d_Ellipse(gp_Ax22d(gp_Pnt2d(0, 0), gp_Dir2d(1, 0)), 3.0, 2.0);
|
||||
|
||||
Geom2dGridEval_Ellipse anEval(anEllipse);
|
||||
EXPECT_FALSE(anEval.Geometry().IsNull());
|
||||
|
||||
NCollection_Array1<double> aParams = CreateUniformParams(0.0, 2 * M_PI, 13);
|
||||
|
||||
NCollection_Array1<gp_Pnt2d> aGrid = anEval.EvaluateGrid(aParams);
|
||||
EXPECT_EQ(aGrid.Size(), 13);
|
||||
|
||||
for (int i = 1; i <= 13; ++i)
|
||||
{
|
||||
gp_Pnt2d aExpected = anEllipse->Value(aParams.Value(i));
|
||||
EXPECT_NEAR(aGrid.Value(i).Distance(aExpected), 0.0, THE_TOLERANCE);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Geom2dGridEval_EllipseTest, CardinalPoints)
|
||||
{
|
||||
occ::handle<Geom2d_Ellipse> anEllipse =
|
||||
new Geom2d_Ellipse(gp_Ax22d(gp_Pnt2d(0, 0), gp_Dir2d(1, 0)), 3.0, 2.0);
|
||||
|
||||
Geom2dGridEval_Ellipse anEval(anEllipse);
|
||||
|
||||
NCollection_Array1<double> aParams(1, 4);
|
||||
aParams.SetValue(1, 0.0);
|
||||
aParams.SetValue(2, M_PI / 2);
|
||||
aParams.SetValue(3, M_PI);
|
||||
aParams.SetValue(4, 3 * M_PI / 2);
|
||||
|
||||
NCollection_Array1<gp_Pnt2d> aGrid = anEval.EvaluateGrid(aParams);
|
||||
|
||||
// u=0: (3, 0)
|
||||
EXPECT_NEAR(aGrid.Value(1).X(), 3.0, THE_TOLERANCE);
|
||||
EXPECT_NEAR(aGrid.Value(1).Y(), 0.0, THE_TOLERANCE);
|
||||
|
||||
// u=PI/2: (0, 2)
|
||||
EXPECT_NEAR(aGrid.Value(2).X(), 0.0, THE_TOLERANCE);
|
||||
EXPECT_NEAR(aGrid.Value(2).Y(), 2.0, THE_TOLERANCE);
|
||||
|
||||
// u=PI: (-3, 0)
|
||||
EXPECT_NEAR(aGrid.Value(3).X(), -3.0, THE_TOLERANCE);
|
||||
EXPECT_NEAR(aGrid.Value(3).Y(), 0.0, THE_TOLERANCE);
|
||||
|
||||
// u=3PI/2: (0, -2)
|
||||
EXPECT_NEAR(aGrid.Value(4).X(), 0.0, THE_TOLERANCE);
|
||||
EXPECT_NEAR(aGrid.Value(4).Y(), -2.0, THE_TOLERANCE);
|
||||
}
|
||||
|
||||
TEST(Geom2dGridEval_EllipseTest, D1)
|
||||
{
|
||||
occ::handle<Geom2d_Ellipse> anEllipse =
|
||||
new Geom2d_Ellipse(gp_Ax22d(gp_Pnt2d(1, 2), gp_Dir2d(1, 0)), 5.0, 3.0);
|
||||
|
||||
Geom2dGridEval_Ellipse anEval(anEllipse);
|
||||
|
||||
NCollection_Array1<double> aParams = CreateUniformParams(0.0, 2 * M_PI, 13);
|
||||
|
||||
NCollection_Array1<Geom2dGridEval::CurveD1> aGrid = anEval.EvaluateGridD1(aParams);
|
||||
|
||||
for (int i = 1; i <= 13; ++i)
|
||||
{
|
||||
gp_Pnt2d aPnt;
|
||||
gp_Vec2d aD1;
|
||||
anEllipse->D1(aParams.Value(i), aPnt, aD1);
|
||||
EXPECT_NEAR(aGrid.Value(i).Point.Distance(aPnt), 0.0, THE_TOLERANCE);
|
||||
EXPECT_NEAR((aGrid.Value(i).D1 - aD1).Magnitude(), 0.0, THE_TOLERANCE);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Geom2dGridEval_EllipseTest, D2)
|
||||
{
|
||||
occ::handle<Geom2d_Ellipse> anEllipse =
|
||||
new Geom2d_Ellipse(gp_Ax22d(gp_Pnt2d(0, 0), gp_Dir2d(1, 0)), 3.0, 2.0);
|
||||
|
||||
Geom2dGridEval_Ellipse anEval(anEllipse);
|
||||
|
||||
NCollection_Array1<double> aParams = CreateUniformParams(0.0, 2 * M_PI, 9);
|
||||
|
||||
NCollection_Array1<Geom2dGridEval::CurveD2> aGrid = anEval.EvaluateGridD2(aParams);
|
||||
|
||||
for (int i = 1; i <= 9; ++i)
|
||||
{
|
||||
gp_Pnt2d aPnt;
|
||||
gp_Vec2d aD1, aD2;
|
||||
anEllipse->D2(aParams.Value(i), aPnt, aD1, aD2);
|
||||
EXPECT_NEAR(aGrid.Value(i).Point.Distance(aPnt), 0.0, THE_TOLERANCE);
|
||||
EXPECT_NEAR((aGrid.Value(i).D1 - aD1).Magnitude(), 0.0, THE_TOLERANCE);
|
||||
EXPECT_NEAR((aGrid.Value(i).D2 - aD2).Magnitude(), 0.0, THE_TOLERANCE);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Geom2dGridEval_EllipseTest, D3)
|
||||
{
|
||||
occ::handle<Geom2d_Ellipse> anEllipse =
|
||||
new Geom2d_Ellipse(gp_Ax22d(gp_Pnt2d(0, 0), gp_Dir2d(1, 0)), 3.0, 2.0);
|
||||
|
||||
Geom2dGridEval_Ellipse anEval(anEllipse);
|
||||
|
||||
NCollection_Array1<double> aParams = CreateUniformParams(0.0, 2 * M_PI, 9);
|
||||
|
||||
NCollection_Array1<Geom2dGridEval::CurveD3> aGrid = anEval.EvaluateGridD3(aParams);
|
||||
|
||||
for (int i = 1; i <= 9; ++i)
|
||||
{
|
||||
gp_Pnt2d aPnt;
|
||||
gp_Vec2d aD1, aD2, aD3;
|
||||
anEllipse->D3(aParams.Value(i), aPnt, aD1, aD2, aD3);
|
||||
EXPECT_NEAR(aGrid.Value(i).Point.Distance(aPnt), 0.0, THE_TOLERANCE);
|
||||
EXPECT_NEAR((aGrid.Value(i).D1 - aD1).Magnitude(), 0.0, THE_TOLERANCE);
|
||||
EXPECT_NEAR((aGrid.Value(i).D2 - aD2).Magnitude(), 0.0, THE_TOLERANCE);
|
||||
EXPECT_NEAR((aGrid.Value(i).D3 - aD3).Magnitude(), 0.0, THE_TOLERANCE);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,142 @@
|
||||
// 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 <gtest/gtest.h>
|
||||
|
||||
#include <Geom2d_Hyperbola.hxx>
|
||||
#include <Geom2dGridEval_Hyperbola.hxx>
|
||||
#include <gp_Ax22d.hxx>
|
||||
#include <gp_Pnt2d.hxx>
|
||||
#include <gp_Vec2d.hxx>
|
||||
#include <NCollection_Array1.hxx>
|
||||
|
||||
#include <cmath>
|
||||
|
||||
namespace
|
||||
{
|
||||
const double THE_TOLERANCE = 1e-10;
|
||||
|
||||
NCollection_Array1<double> CreateUniformParams(double theFirst, double theLast, int theNbPoints)
|
||||
{
|
||||
NCollection_Array1<double> aParams(1, theNbPoints);
|
||||
const double aStep = (theLast - theFirst) / (theNbPoints - 1);
|
||||
for (int i = 1; i <= theNbPoints; ++i)
|
||||
{
|
||||
aParams.SetValue(i, theFirst + (i - 1) * aStep);
|
||||
}
|
||||
return aParams;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
TEST(Geom2dGridEval_HyperbolaTest, BasicD0)
|
||||
{
|
||||
occ::handle<Geom2d_Hyperbola> aHypr =
|
||||
new Geom2d_Hyperbola(gp_Ax22d(gp_Pnt2d(0, 0), gp_Dir2d(1, 0)), 3.0, 2.0);
|
||||
|
||||
Geom2dGridEval_Hyperbola anEval(aHypr);
|
||||
EXPECT_FALSE(anEval.Geometry().IsNull());
|
||||
|
||||
NCollection_Array1<double> aParams = CreateUniformParams(-2.0, 2.0, 11);
|
||||
|
||||
NCollection_Array1<gp_Pnt2d> aGrid = anEval.EvaluateGrid(aParams);
|
||||
EXPECT_EQ(aGrid.Size(), 11);
|
||||
|
||||
for (int i = 1; i <= 11; ++i)
|
||||
{
|
||||
gp_Pnt2d aExpected = aHypr->Value(aParams.Value(i));
|
||||
EXPECT_NEAR(aGrid.Value(i).Distance(aExpected), 0.0, THE_TOLERANCE);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Geom2dGridEval_HyperbolaTest, AtOrigin)
|
||||
{
|
||||
occ::handle<Geom2d_Hyperbola> aHypr =
|
||||
new Geom2d_Hyperbola(gp_Ax22d(gp_Pnt2d(0, 0), gp_Dir2d(1, 0)), 3.0, 2.0);
|
||||
|
||||
Geom2dGridEval_Hyperbola anEval(aHypr);
|
||||
|
||||
NCollection_Array1<double> aParams(1, 1);
|
||||
aParams.SetValue(1, 0.0);
|
||||
|
||||
NCollection_Array1<gp_Pnt2d> aGrid = anEval.EvaluateGrid(aParams);
|
||||
|
||||
// At u=0: P = Center + MajR*cosh(0)*X + MinR*sinh(0)*Y = Center + MajR*X = (3, 0)
|
||||
EXPECT_NEAR(aGrid.Value(1).X(), 3.0, THE_TOLERANCE);
|
||||
EXPECT_NEAR(aGrid.Value(1).Y(), 0.0, THE_TOLERANCE);
|
||||
}
|
||||
|
||||
TEST(Geom2dGridEval_HyperbolaTest, D1)
|
||||
{
|
||||
occ::handle<Geom2d_Hyperbola> aHypr =
|
||||
new Geom2d_Hyperbola(gp_Ax22d(gp_Pnt2d(1, 2), gp_Dir2d(1, 0)), 3.0, 2.0);
|
||||
|
||||
Geom2dGridEval_Hyperbola anEval(aHypr);
|
||||
|
||||
NCollection_Array1<double> aParams = CreateUniformParams(-2.0, 2.0, 11);
|
||||
|
||||
NCollection_Array1<Geom2dGridEval::CurveD1> aGrid = anEval.EvaluateGridD1(aParams);
|
||||
|
||||
for (int i = 1; i <= 11; ++i)
|
||||
{
|
||||
gp_Pnt2d aPnt;
|
||||
gp_Vec2d aD1;
|
||||
aHypr->D1(aParams.Value(i), aPnt, aD1);
|
||||
EXPECT_NEAR(aGrid.Value(i).Point.Distance(aPnt), 0.0, THE_TOLERANCE);
|
||||
EXPECT_NEAR((aGrid.Value(i).D1 - aD1).Magnitude(), 0.0, THE_TOLERANCE);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Geom2dGridEval_HyperbolaTest, D2)
|
||||
{
|
||||
occ::handle<Geom2d_Hyperbola> aHypr =
|
||||
new Geom2d_Hyperbola(gp_Ax22d(gp_Pnt2d(0, 0), gp_Dir2d(1, 0)), 3.0, 2.0);
|
||||
|
||||
Geom2dGridEval_Hyperbola anEval(aHypr);
|
||||
|
||||
NCollection_Array1<double> aParams = CreateUniformParams(-2.0, 2.0, 11);
|
||||
|
||||
NCollection_Array1<Geom2dGridEval::CurveD2> aGrid = anEval.EvaluateGridD2(aParams);
|
||||
|
||||
for (int i = 1; i <= 11; ++i)
|
||||
{
|
||||
gp_Pnt2d aPnt;
|
||||
gp_Vec2d aD1, aD2;
|
||||
aHypr->D2(aParams.Value(i), aPnt, aD1, aD2);
|
||||
EXPECT_NEAR(aGrid.Value(i).Point.Distance(aPnt), 0.0, THE_TOLERANCE);
|
||||
EXPECT_NEAR((aGrid.Value(i).D1 - aD1).Magnitude(), 0.0, THE_TOLERANCE);
|
||||
EXPECT_NEAR((aGrid.Value(i).D2 - aD2).Magnitude(), 0.0, THE_TOLERANCE);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Geom2dGridEval_HyperbolaTest, D3)
|
||||
{
|
||||
occ::handle<Geom2d_Hyperbola> aHypr =
|
||||
new Geom2d_Hyperbola(gp_Ax22d(gp_Pnt2d(0, 0), gp_Dir2d(1, 0)), 3.0, 2.0);
|
||||
|
||||
Geom2dGridEval_Hyperbola anEval(aHypr);
|
||||
|
||||
NCollection_Array1<double> aParams = CreateUniformParams(-2.0, 2.0, 11);
|
||||
|
||||
NCollection_Array1<Geom2dGridEval::CurveD3> aGrid = anEval.EvaluateGridD3(aParams);
|
||||
|
||||
for (int i = 1; i <= 11; ++i)
|
||||
{
|
||||
gp_Pnt2d aPnt;
|
||||
gp_Vec2d aD1, aD2, aD3;
|
||||
aHypr->D3(aParams.Value(i), aPnt, aD1, aD2, aD3);
|
||||
EXPECT_NEAR(aGrid.Value(i).Point.Distance(aPnt), 0.0, THE_TOLERANCE);
|
||||
EXPECT_NEAR((aGrid.Value(i).D1 - aD1).Magnitude(), 0.0, THE_TOLERANCE);
|
||||
EXPECT_NEAR((aGrid.Value(i).D2 - aD2).Magnitude(), 0.0, THE_TOLERANCE);
|
||||
EXPECT_NEAR((aGrid.Value(i).D3 - aD3).Magnitude(), 0.0, THE_TOLERANCE);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,160 @@
|
||||
// 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 <gtest/gtest.h>
|
||||
|
||||
#include <Geom2d_Parabola.hxx>
|
||||
#include <Geom2dGridEval_Parabola.hxx>
|
||||
#include <gp_Ax22d.hxx>
|
||||
#include <gp_Pnt2d.hxx>
|
||||
#include <gp_Vec2d.hxx>
|
||||
#include <NCollection_Array1.hxx>
|
||||
|
||||
#include <cmath>
|
||||
|
||||
namespace
|
||||
{
|
||||
const double THE_TOLERANCE = 1e-10;
|
||||
|
||||
NCollection_Array1<double> CreateUniformParams(double theFirst, double theLast, int theNbPoints)
|
||||
{
|
||||
NCollection_Array1<double> aParams(1, theNbPoints);
|
||||
const double aStep = (theLast - theFirst) / (theNbPoints - 1);
|
||||
for (int i = 1; i <= theNbPoints; ++i)
|
||||
{
|
||||
aParams.SetValue(i, theFirst + (i - 1) * aStep);
|
||||
}
|
||||
return aParams;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
TEST(Geom2dGridEval_ParabolaTest, BasicD0)
|
||||
{
|
||||
occ::handle<Geom2d_Parabola> aParab =
|
||||
new Geom2d_Parabola(gp_Ax22d(gp_Pnt2d(0, 0), gp_Dir2d(1, 0)), 1.0);
|
||||
|
||||
Geom2dGridEval_Parabola anEval(aParab);
|
||||
EXPECT_FALSE(anEval.Geometry().IsNull());
|
||||
|
||||
NCollection_Array1<double> aParams = CreateUniformParams(-3.0, 3.0, 13);
|
||||
|
||||
NCollection_Array1<gp_Pnt2d> aGrid = anEval.EvaluateGrid(aParams);
|
||||
EXPECT_EQ(aGrid.Size(), 13);
|
||||
|
||||
for (int i = 1; i <= 13; ++i)
|
||||
{
|
||||
gp_Pnt2d aExpected = aParab->Value(aParams.Value(i));
|
||||
EXPECT_NEAR(aGrid.Value(i).Distance(aExpected), 0.0, THE_TOLERANCE);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Geom2dGridEval_ParabolaTest, AtOrigin)
|
||||
{
|
||||
occ::handle<Geom2d_Parabola> aParab =
|
||||
new Geom2d_Parabola(gp_Ax22d(gp_Pnt2d(0, 0), gp_Dir2d(1, 0)), 1.0);
|
||||
|
||||
Geom2dGridEval_Parabola anEval(aParab);
|
||||
|
||||
NCollection_Array1<double> aParams(1, 1);
|
||||
aParams.SetValue(1, 0.0);
|
||||
|
||||
NCollection_Array1<gp_Pnt2d> aGrid = anEval.EvaluateGrid(aParams);
|
||||
|
||||
// At u=0: P = Center + 0*XDir + 0*YDir = (0, 0)
|
||||
EXPECT_NEAR(aGrid.Value(1).X(), 0.0, THE_TOLERANCE);
|
||||
EXPECT_NEAR(aGrid.Value(1).Y(), 0.0, THE_TOLERANCE);
|
||||
}
|
||||
|
||||
TEST(Geom2dGridEval_ParabolaTest, D1)
|
||||
{
|
||||
occ::handle<Geom2d_Parabola> aParab =
|
||||
new Geom2d_Parabola(gp_Ax22d(gp_Pnt2d(1, 2), gp_Dir2d(1, 0)), 2.0);
|
||||
|
||||
Geom2dGridEval_Parabola anEval(aParab);
|
||||
|
||||
NCollection_Array1<double> aParams = CreateUniformParams(-3.0, 3.0, 13);
|
||||
|
||||
NCollection_Array1<Geom2dGridEval::CurveD1> aGrid = anEval.EvaluateGridD1(aParams);
|
||||
|
||||
for (int i = 1; i <= 13; ++i)
|
||||
{
|
||||
gp_Pnt2d aPnt;
|
||||
gp_Vec2d aD1;
|
||||
aParab->D1(aParams.Value(i), aPnt, aD1);
|
||||
EXPECT_NEAR(aGrid.Value(i).Point.Distance(aPnt), 0.0, THE_TOLERANCE);
|
||||
EXPECT_NEAR((aGrid.Value(i).D1 - aD1).Magnitude(), 0.0, THE_TOLERANCE);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Geom2dGridEval_ParabolaTest, D2)
|
||||
{
|
||||
occ::handle<Geom2d_Parabola> aParab =
|
||||
new Geom2d_Parabola(gp_Ax22d(gp_Pnt2d(0, 0), gp_Dir2d(1, 0)), 1.0);
|
||||
|
||||
Geom2dGridEval_Parabola anEval(aParab);
|
||||
|
||||
NCollection_Array1<double> aParams = CreateUniformParams(-3.0, 3.0, 13);
|
||||
|
||||
NCollection_Array1<Geom2dGridEval::CurveD2> aGrid = anEval.EvaluateGridD2(aParams);
|
||||
|
||||
for (int i = 1; i <= 13; ++i)
|
||||
{
|
||||
gp_Pnt2d aPnt;
|
||||
gp_Vec2d aD1, aD2;
|
||||
aParab->D2(aParams.Value(i), aPnt, aD1, aD2);
|
||||
EXPECT_NEAR(aGrid.Value(i).Point.Distance(aPnt), 0.0, THE_TOLERANCE);
|
||||
EXPECT_NEAR((aGrid.Value(i).D1 - aD1).Magnitude(), 0.0, THE_TOLERANCE);
|
||||
EXPECT_NEAR((aGrid.Value(i).D2 - aD2).Magnitude(), 0.0, THE_TOLERANCE);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Geom2dGridEval_ParabolaTest, D3)
|
||||
{
|
||||
occ::handle<Geom2d_Parabola> aParab =
|
||||
new Geom2d_Parabola(gp_Ax22d(gp_Pnt2d(0, 0), gp_Dir2d(1, 0)), 1.0);
|
||||
|
||||
Geom2dGridEval_Parabola anEval(aParab);
|
||||
|
||||
NCollection_Array1<double> aParams = CreateUniformParams(-3.0, 3.0, 13);
|
||||
|
||||
NCollection_Array1<Geom2dGridEval::CurveD3> aGrid = anEval.EvaluateGridD3(aParams);
|
||||
|
||||
for (int i = 1; i <= 13; ++i)
|
||||
{
|
||||
gp_Pnt2d aPnt;
|
||||
gp_Vec2d aD1, aD2, aD3;
|
||||
aParab->D3(aParams.Value(i), aPnt, aD1, aD2, aD3);
|
||||
EXPECT_NEAR(aGrid.Value(i).Point.Distance(aPnt), 0.0, THE_TOLERANCE);
|
||||
EXPECT_NEAR((aGrid.Value(i).D1 - aD1).Magnitude(), 0.0, THE_TOLERANCE);
|
||||
EXPECT_NEAR((aGrid.Value(i).D2 - aD2).Magnitude(), 0.0, THE_TOLERANCE);
|
||||
EXPECT_NEAR((aGrid.Value(i).D3 - aD3).Magnitude(), 0.0, THE_TOLERANCE);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Geom2dGridEval_ParabolaTest, DN_HighOrder)
|
||||
{
|
||||
occ::handle<Geom2d_Parabola> aParab =
|
||||
new Geom2d_Parabola(gp_Ax22d(gp_Pnt2d(0, 0), gp_Dir2d(1, 0)), 1.0);
|
||||
|
||||
Geom2dGridEval_Parabola anEval(aParab);
|
||||
|
||||
NCollection_Array1<double> aParams = CreateUniformParams(-3.0, 3.0, 7);
|
||||
|
||||
// D3 and higher should be zero for parabola
|
||||
NCollection_Array1<gp_Vec2d> aGrid = anEval.EvaluateGridDN(aParams, 3);
|
||||
|
||||
for (int i = 1; i <= 7; ++i)
|
||||
{
|
||||
EXPECT_NEAR(aGrid.Value(i).Magnitude(), 0.0, THE_TOLERANCE);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
# Source files for Geom2dGridEval package
|
||||
set(OCCT_Geom2dGridEval_FILES_LOCATION "${CMAKE_CURRENT_LIST_DIR}")
|
||||
|
||||
set(OCCT_Geom2dGridEval_FILES
|
||||
Geom2dGridEval.hxx
|
||||
Geom2dGridEval_BezierCurve.cxx
|
||||
Geom2dGridEval_BezierCurve.hxx
|
||||
Geom2dGridEval_BSplineCurve.cxx
|
||||
Geom2dGridEval_BSplineCurve.hxx
|
||||
Geom2dGridEval_Circle.cxx
|
||||
Geom2dGridEval_Circle.hxx
|
||||
Geom2dGridEval_Curve.cxx
|
||||
Geom2dGridEval_Curve.hxx
|
||||
Geom2dGridEval_Ellipse.cxx
|
||||
Geom2dGridEval_Ellipse.hxx
|
||||
Geom2dGridEval_Hyperbola.cxx
|
||||
Geom2dGridEval_Hyperbola.hxx
|
||||
Geom2dGridEval_Line.hxx
|
||||
Geom2dGridEval_OffsetCurve.cxx
|
||||
Geom2dGridEval_OffsetCurve.hxx
|
||||
Geom2dGridEval_OtherCurve.cxx
|
||||
Geom2dGridEval_OtherCurve.hxx
|
||||
Geom2dGridEval_Parabola.cxx
|
||||
Geom2dGridEval_Parabola.hxx
|
||||
)
|
||||
@@ -0,0 +1,54 @@
|
||||
// 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 _Geom2dGridEval_HeaderFile
|
||||
#define _Geom2dGridEval_HeaderFile
|
||||
|
||||
#include <gp_Pnt2d.hxx>
|
||||
#include <gp_Vec2d.hxx>
|
||||
#include <NCollection_Array1.hxx>
|
||||
|
||||
//! @brief Namespace containing result structures for 2D curve grid evaluators.
|
||||
//!
|
||||
//! Provides lightweight POD structures for returning evaluation results
|
||||
//! with derivatives from 2D curve grid evaluators.
|
||||
namespace Geom2dGridEval
|
||||
{
|
||||
|
||||
//! Result structure for curve D1 evaluation (point and first derivative).
|
||||
struct CurveD1
|
||||
{
|
||||
gp_Pnt2d Point;
|
||||
gp_Vec2d D1;
|
||||
};
|
||||
|
||||
//! Result structure for curve D2 evaluation (point and first two derivatives).
|
||||
struct CurveD2
|
||||
{
|
||||
gp_Pnt2d Point;
|
||||
gp_Vec2d D1;
|
||||
gp_Vec2d D2;
|
||||
};
|
||||
|
||||
//! Result structure for curve D3 evaluation (point and first three derivatives).
|
||||
struct CurveD3
|
||||
{
|
||||
gp_Pnt2d Point;
|
||||
gp_Vec2d D1;
|
||||
gp_Vec2d D2;
|
||||
gp_Vec2d D3;
|
||||
};
|
||||
|
||||
} // namespace Geom2dGridEval
|
||||
|
||||
#endif // _Geom2dGridEval_HeaderFile
|
||||
@@ -0,0 +1,375 @@
|
||||
// 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 <Geom2dGridEval_BSplineCurve.hxx>
|
||||
|
||||
#include <BSplCLib.hxx>
|
||||
#include <BSplCLib_Cache.hxx>
|
||||
#include <gp_Pnt2d.hxx>
|
||||
#include <NCollection_Array1.hxx>
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
//! Threshold for using cache vs direct evaluation.
|
||||
constexpr int THE_CACHE_THRESHOLD = 4;
|
||||
|
||||
//! Helper structure holding extracted 2D B-spline curve data.
|
||||
struct CurveData
|
||||
{
|
||||
const NCollection_Array1<double>* FlatKnots;
|
||||
const NCollection_Array1<gp_Pnt2d>* Poles;
|
||||
const NCollection_Array1<double>* Weights;
|
||||
const NCollection_Array1<double>* Knots;
|
||||
const NCollection_Array1<int>* Mults;
|
||||
int Degree;
|
||||
bool IsPeriodic;
|
||||
};
|
||||
|
||||
//! Extract curve data from geometry. Returns false if data is invalid.
|
||||
bool extractCurveData(const occ::handle<Geom2d_BSplineCurve>& theGeom, CurveData& theData)
|
||||
{
|
||||
if (theGeom.IsNull())
|
||||
return false;
|
||||
|
||||
theData.FlatKnots = &theGeom->KnotSequence();
|
||||
theData.Poles = &theGeom->Poles();
|
||||
theData.Weights = theGeom->Weights();
|
||||
theData.Knots = &theGeom->Knots();
|
||||
theData.Mults = &theGeom->Multiplicities();
|
||||
theData.Degree = theGeom->Degree();
|
||||
theData.IsPeriodic = theGeom->IsPeriodic();
|
||||
return true;
|
||||
}
|
||||
|
||||
//! Locate parameter and compute span index.
|
||||
inline void locateSpan(double theParam,
|
||||
const NCollection_Array1<double>& theFlatKnots,
|
||||
int theDegree,
|
||||
bool theIsPeriodic,
|
||||
double& theAdjustedParam,
|
||||
int& theSpanIdx)
|
||||
{
|
||||
theAdjustedParam = theParam;
|
||||
BSplCLib::LocateParameter(theDegree,
|
||||
theFlatKnots,
|
||||
BSplCLib::NoMults(),
|
||||
theParam,
|
||||
theIsPeriodic,
|
||||
theSpanIdx,
|
||||
theAdjustedParam);
|
||||
}
|
||||
|
||||
//! Count consecutive parameters in the same span (for cache threshold decision).
|
||||
inline int countSpanSize(const NCollection_Array1<double>& theParams,
|
||||
const NCollection_Array1<double>& theFlatKnots,
|
||||
int theDegree,
|
||||
bool theIsPeriodic,
|
||||
int theStartIdx,
|
||||
int theTargetSpan)
|
||||
{
|
||||
const int aLower = theParams.Lower();
|
||||
const int aNb = theParams.Size();
|
||||
int aCount = 1;
|
||||
|
||||
for (int i = theStartIdx + 1; i < aNb; ++i)
|
||||
{
|
||||
double aParam = theParams.Value(aLower + i);
|
||||
double aAdjusted = aParam;
|
||||
int aSpan = 0;
|
||||
BSplCLib::LocateParameter(theDegree,
|
||||
theFlatKnots,
|
||||
BSplCLib::NoMults(),
|
||||
aParam,
|
||||
theIsPeriodic,
|
||||
aSpan,
|
||||
aAdjusted);
|
||||
if (aSpan == theTargetSpan)
|
||||
++aCount;
|
||||
else
|
||||
break;
|
||||
}
|
||||
return aCount;
|
||||
}
|
||||
|
||||
//! Compute span local parameter coefficients (start and length).
|
||||
//! Note: Curve cache uses [0,1] local parameter range (unlike surface which uses [-1,1]).
|
||||
inline void computeSpanCoeffs(const NCollection_Array1<double>& theFlatKnots,
|
||||
int theSpan,
|
||||
double& theStart,
|
||||
double& theLen)
|
||||
{
|
||||
theStart = theFlatKnots.Value(theSpan);
|
||||
theLen = theFlatKnots.Value(theSpan + 1) - theStart;
|
||||
}
|
||||
|
||||
//! Template helper for cached grid evaluation.
|
||||
//! @tparam ResultT result type (gp_Pnt2d, CurveD1, CurveD2, CurveD3)
|
||||
//! @tparam CacheEvalF functor: (cache, localParam, result) -> void
|
||||
//! @tparam DirectEvalF functor: (data, param, spanIdx, result) -> void
|
||||
template <typename ResultT, typename CacheEvalF, typename DirectEvalF>
|
||||
NCollection_Array1<ResultT> evaluateGridCached(const CurveData& theData,
|
||||
const NCollection_Array1<double>& theParams,
|
||||
CacheEvalF theCacheEval,
|
||||
DirectEvalF theDirectEval)
|
||||
{
|
||||
const int aNbParams = theParams.Size();
|
||||
const int aLow = theParams.Lower();
|
||||
|
||||
NCollection_Array1<ResultT> aResults(1, aNbParams);
|
||||
occ::handle<BSplCLib_Cache> aCache = new BSplCLib_Cache(theData.Degree,
|
||||
theData.IsPeriodic,
|
||||
*theData.FlatKnots,
|
||||
*theData.Poles,
|
||||
theData.Weights);
|
||||
|
||||
int aPrevSpan = -1;
|
||||
int aSpanSize = 0;
|
||||
double aSpanStart = 0.0;
|
||||
double aSpanLen = 1.0;
|
||||
bool aUseCache = false;
|
||||
|
||||
for (int i = 0; i < aNbParams; ++i)
|
||||
{
|
||||
const double aParam = theParams.Value(aLow + i);
|
||||
double aAdjParam = aParam;
|
||||
int aSpan = 0;
|
||||
locateSpan(aParam, *theData.FlatKnots, theData.Degree, theData.IsPeriodic, aAdjParam, aSpan);
|
||||
|
||||
// Update span info when span changes
|
||||
if (aSpan != aPrevSpan)
|
||||
{
|
||||
aPrevSpan = aSpan;
|
||||
aSpanSize =
|
||||
countSpanSize(theParams, *theData.FlatKnots, theData.Degree, theData.IsPeriodic, i, aSpan);
|
||||
computeSpanCoeffs(*theData.FlatKnots, aSpan, aSpanStart, aSpanLen);
|
||||
|
||||
aUseCache = (aSpanSize >= THE_CACHE_THRESHOLD);
|
||||
if (aUseCache)
|
||||
{
|
||||
aCache->BuildCache(aAdjParam, *theData.FlatKnots, *theData.Poles, theData.Weights);
|
||||
}
|
||||
}
|
||||
|
||||
ResultT& aResult = aResults.ChangeValue(i + 1);
|
||||
if (aUseCache)
|
||||
{
|
||||
// Curve cache uses [0,1] local parameter range
|
||||
const double aLocalParam = (aSpanLen > 0.0) ? (aAdjParam - aSpanStart) / aSpanLen : 0.0;
|
||||
theCacheEval(aCache, aLocalParam, aResult);
|
||||
}
|
||||
else
|
||||
{
|
||||
theDirectEval(theData, aAdjParam, aSpan, aResult);
|
||||
}
|
||||
}
|
||||
|
||||
return aResults;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
NCollection_Array1<gp_Pnt2d> Geom2dGridEval_BSplineCurve::EvaluateGrid(
|
||||
const NCollection_Array1<double>& theParams) const
|
||||
{
|
||||
CurveData aData;
|
||||
if (theParams.IsEmpty() || !extractCurveData(myGeom, aData))
|
||||
{
|
||||
return NCollection_Array1<gp_Pnt2d>();
|
||||
}
|
||||
|
||||
return evaluateGridCached<gp_Pnt2d>(
|
||||
aData,
|
||||
theParams,
|
||||
[](const occ::handle<BSplCLib_Cache>& theCache, double theLocalParam, gp_Pnt2d& theResult) {
|
||||
theCache->D0Local(theLocalParam, theResult);
|
||||
},
|
||||
[](const CurveData& theData, double theParam, int theSpanIdx, gp_Pnt2d& theResult) {
|
||||
BSplCLib::D0(theParam,
|
||||
theSpanIdx,
|
||||
theData.Degree,
|
||||
theData.IsPeriodic,
|
||||
*theData.Poles,
|
||||
theData.Weights,
|
||||
*theData.FlatKnots,
|
||||
nullptr,
|
||||
theResult);
|
||||
});
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
NCollection_Array1<Geom2dGridEval::CurveD1> Geom2dGridEval_BSplineCurve::EvaluateGridD1(
|
||||
const NCollection_Array1<double>& theParams) const
|
||||
{
|
||||
CurveData aData;
|
||||
if (theParams.IsEmpty() || !extractCurveData(myGeom, aData))
|
||||
{
|
||||
return NCollection_Array1<Geom2dGridEval::CurveD1>();
|
||||
}
|
||||
|
||||
return evaluateGridCached<Geom2dGridEval::CurveD1>(
|
||||
aData,
|
||||
theParams,
|
||||
[](const occ::handle<BSplCLib_Cache>& theCache,
|
||||
double theLocalParam,
|
||||
Geom2dGridEval::CurveD1& theResult) {
|
||||
theCache->D1Local(theLocalParam, theResult.Point, theResult.D1);
|
||||
},
|
||||
[](const CurveData& theData,
|
||||
double theParam,
|
||||
int theSpanIdx,
|
||||
Geom2dGridEval::CurveD1& theResult) {
|
||||
BSplCLib::D1(theParam,
|
||||
theSpanIdx,
|
||||
theData.Degree,
|
||||
theData.IsPeriodic,
|
||||
*theData.Poles,
|
||||
theData.Weights,
|
||||
*theData.FlatKnots,
|
||||
nullptr,
|
||||
theResult.Point,
|
||||
theResult.D1);
|
||||
});
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
NCollection_Array1<Geom2dGridEval::CurveD2> Geom2dGridEval_BSplineCurve::EvaluateGridD2(
|
||||
const NCollection_Array1<double>& theParams) const
|
||||
{
|
||||
CurveData aData;
|
||||
if (theParams.IsEmpty() || !extractCurveData(myGeom, aData))
|
||||
{
|
||||
return NCollection_Array1<Geom2dGridEval::CurveD2>();
|
||||
}
|
||||
|
||||
return evaluateGridCached<Geom2dGridEval::CurveD2>(
|
||||
aData,
|
||||
theParams,
|
||||
[](const occ::handle<BSplCLib_Cache>& theCache,
|
||||
double theLocalParam,
|
||||
Geom2dGridEval::CurveD2& theResult) {
|
||||
theCache->D2Local(theLocalParam, theResult.Point, theResult.D1, theResult.D2);
|
||||
},
|
||||
[](const CurveData& theData,
|
||||
double theParam,
|
||||
int theSpanIdx,
|
||||
Geom2dGridEval::CurveD2& theResult) {
|
||||
BSplCLib::D2(theParam,
|
||||
theSpanIdx,
|
||||
theData.Degree,
|
||||
theData.IsPeriodic,
|
||||
*theData.Poles,
|
||||
theData.Weights,
|
||||
*theData.FlatKnots,
|
||||
nullptr,
|
||||
theResult.Point,
|
||||
theResult.D1,
|
||||
theResult.D2);
|
||||
});
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
NCollection_Array1<Geom2dGridEval::CurveD3> Geom2dGridEval_BSplineCurve::EvaluateGridD3(
|
||||
const NCollection_Array1<double>& theParams) const
|
||||
{
|
||||
CurveData aData;
|
||||
if (theParams.IsEmpty() || !extractCurveData(myGeom, aData))
|
||||
{
|
||||
return NCollection_Array1<Geom2dGridEval::CurveD3>();
|
||||
}
|
||||
|
||||
return evaluateGridCached<Geom2dGridEval::CurveD3>(
|
||||
aData,
|
||||
theParams,
|
||||
[](const occ::handle<BSplCLib_Cache>& theCache,
|
||||
double theLocalParam,
|
||||
Geom2dGridEval::CurveD3& theResult) {
|
||||
theCache->D3Local(theLocalParam, theResult.Point, theResult.D1, theResult.D2, theResult.D3);
|
||||
},
|
||||
[](const CurveData& theData,
|
||||
double theParam,
|
||||
int theSpanIdx,
|
||||
Geom2dGridEval::CurveD3& theResult) {
|
||||
BSplCLib::D3(theParam,
|
||||
theSpanIdx,
|
||||
theData.Degree,
|
||||
theData.IsPeriodic,
|
||||
*theData.Poles,
|
||||
theData.Weights,
|
||||
*theData.FlatKnots,
|
||||
nullptr,
|
||||
theResult.Point,
|
||||
theResult.D1,
|
||||
theResult.D2,
|
||||
theResult.D3);
|
||||
});
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
NCollection_Array1<gp_Vec2d> Geom2dGridEval_BSplineCurve::EvaluateGridDN(
|
||||
const NCollection_Array1<double>& theParams,
|
||||
int theN) const
|
||||
{
|
||||
CurveData aData;
|
||||
if (theParams.IsEmpty() || theN < 1 || !extractCurveData(myGeom, aData))
|
||||
{
|
||||
return NCollection_Array1<gp_Vec2d>();
|
||||
}
|
||||
|
||||
const int aNbParams = theParams.Size();
|
||||
const int aLow = theParams.Lower();
|
||||
|
||||
// Derivatives beyond degree are zero
|
||||
if (theN > aData.Degree)
|
||||
{
|
||||
NCollection_Array1<gp_Vec2d> aResult(1, aNbParams);
|
||||
const gp_Vec2d aZero(0.0, 0.0);
|
||||
for (int i = 1; i <= aNbParams; ++i)
|
||||
{
|
||||
aResult.SetValue(i, aZero);
|
||||
}
|
||||
return aResult;
|
||||
}
|
||||
|
||||
NCollection_Array1<gp_Vec2d> aResult(1, aNbParams);
|
||||
|
||||
// DN uses direct evaluation (no cache available)
|
||||
for (int i = 0; i < aNbParams; ++i)
|
||||
{
|
||||
const double aParam = theParams.Value(aLow + i);
|
||||
double aAdjParam = aParam;
|
||||
int aSpan = 0;
|
||||
locateSpan(aParam, *aData.FlatKnots, aData.Degree, aData.IsPeriodic, aAdjParam, aSpan);
|
||||
|
||||
gp_Vec2d aDN;
|
||||
BSplCLib::DN(aAdjParam,
|
||||
theN,
|
||||
aSpan,
|
||||
aData.Degree,
|
||||
aData.IsPeriodic,
|
||||
*aData.Poles,
|
||||
aData.Weights,
|
||||
*aData.Knots,
|
||||
aData.Mults,
|
||||
aDN);
|
||||
aResult.SetValue(i + 1, aDN);
|
||||
}
|
||||
|
||||
return aResult;
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
// 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 _Geom2dGridEval_BSplineCurve_HeaderFile
|
||||
#define _Geom2dGridEval_BSplineCurve_HeaderFile
|
||||
|
||||
#include <BSplCLib_Cache.hxx>
|
||||
#include <Geom2d_BSplineCurve.hxx>
|
||||
#include <Geom2dGridEval.hxx>
|
||||
#include <NCollection_Array1.hxx>
|
||||
#include <Standard.hxx>
|
||||
#include <Standard_DefineAlloc.hxx>
|
||||
|
||||
//! @brief Efficient batch evaluator for 2D B-spline curve grid points.
|
||||
//!
|
||||
//! Optimizes evaluation of multiple points on a 2D B-spline curve by:
|
||||
//! - Pre-computing span indices for input parameters (no runtime binary search)
|
||||
//! - Pre-grouping parameters by span for cache-optimal iteration
|
||||
//! - Rebuilding cache only once per span block (not per point)
|
||||
//! - Using KnotSequence() from Geom2d_BSplineCurve for direct flat knot access
|
||||
//!
|
||||
//! Usage:
|
||||
//! @code
|
||||
//! Geom2dGridEval_BSplineCurve anEvaluator(myBSplineCurve2d);
|
||||
//! NCollection_Array1<gp_Pnt2d> aGrid = anEvaluator.EvaluateGrid(myParams);
|
||||
//! @endcode
|
||||
class Geom2dGridEval_BSplineCurve
|
||||
{
|
||||
public:
|
||||
DEFINE_STANDARD_ALLOC
|
||||
|
||||
//! Constructor with geometry.
|
||||
//! @param theCurve the 2D B-spline curve to evaluate
|
||||
Geom2dGridEval_BSplineCurve(const occ::handle<Geom2d_BSplineCurve>& theCurve)
|
||||
: myGeom(theCurve)
|
||||
{
|
||||
}
|
||||
|
||||
//! Non-copyable and non-movable.
|
||||
Geom2dGridEval_BSplineCurve(const Geom2dGridEval_BSplineCurve&) = delete;
|
||||
Geom2dGridEval_BSplineCurve& operator=(const Geom2dGridEval_BSplineCurve&) = delete;
|
||||
Geom2dGridEval_BSplineCurve(Geom2dGridEval_BSplineCurve&&) = delete;
|
||||
Geom2dGridEval_BSplineCurve& operator=(Geom2dGridEval_BSplineCurve&&) = delete;
|
||||
|
||||
//! Returns the geometry handle.
|
||||
const occ::handle<Geom2d_BSplineCurve>& Geometry() const { return myGeom; }
|
||||
|
||||
//! Evaluate all grid points.
|
||||
//! Points are evaluated in span-grouped order to minimize cache rebuilds.
|
||||
//! @param theParams array of parameter values
|
||||
//! @return array of evaluated points (1-based indexing),
|
||||
//! or empty array if geometry is null or no parameters
|
||||
Standard_EXPORT NCollection_Array1<gp_Pnt2d> EvaluateGrid(
|
||||
const NCollection_Array1<double>& theParams) const;
|
||||
|
||||
//! Evaluate all grid points with first derivative.
|
||||
//! @param theParams array of parameter values
|
||||
//! @return array of CurveD1 (1-based indexing),
|
||||
//! or empty array if geometry is null or no parameters
|
||||
Standard_EXPORT NCollection_Array1<Geom2dGridEval::CurveD1> EvaluateGridD1(
|
||||
const NCollection_Array1<double>& theParams) const;
|
||||
|
||||
//! Evaluate all grid points with first and second derivatives.
|
||||
//! @param theParams array of parameter values
|
||||
//! @return array of CurveD2 (1-based indexing),
|
||||
//! or empty array if geometry is null or no parameters
|
||||
Standard_EXPORT NCollection_Array1<Geom2dGridEval::CurveD2> EvaluateGridD2(
|
||||
const NCollection_Array1<double>& theParams) const;
|
||||
|
||||
//! Evaluate all grid points with first, second, and third derivatives.
|
||||
//! @param theParams array of parameter values
|
||||
//! @return array of CurveD3 (1-based indexing),
|
||||
//! or empty array if geometry is null or no parameters
|
||||
Standard_EXPORT NCollection_Array1<Geom2dGridEval::CurveD3> EvaluateGridD3(
|
||||
const NCollection_Array1<double>& theParams) const;
|
||||
|
||||
//! Evaluate Nth derivative at all grid points.
|
||||
//! For orders 1-3, reuses EvaluateGridD1/D2/D3.
|
||||
//! For orders > 3, uses BSplCLib::DN.
|
||||
//! @param theParams array of parameter values
|
||||
//! @param theN derivative order (N >= 1)
|
||||
//! @return array of derivative vectors (1-based indexing)
|
||||
Standard_EXPORT NCollection_Array1<gp_Vec2d> EvaluateGridDN(
|
||||
const NCollection_Array1<double>& theParams,
|
||||
int theN) const;
|
||||
|
||||
private:
|
||||
occ::handle<Geom2d_BSplineCurve> myGeom;
|
||||
};
|
||||
|
||||
#endif // _Geom2dGridEval_BSplineCurve_HeaderFile
|
||||
@@ -0,0 +1,185 @@
|
||||
// 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 <Geom2dGridEval_BezierCurve.hxx>
|
||||
|
||||
#include <BSplCLib.hxx>
|
||||
#include <BSplCLib_Cache.hxx>
|
||||
#include <gp_Pnt2d.hxx>
|
||||
|
||||
namespace
|
||||
{
|
||||
//! Creates a BSplCLib_Cache for a 2D Bezier curve.
|
||||
//! @param theCurve the 2D Bezier curve geometry
|
||||
//! @return initialized cache ready for evaluation
|
||||
occ::handle<BSplCLib_Cache> CreateBezierCache2d(const occ::handle<Geom2d_BezierCurve>& theCurve)
|
||||
{
|
||||
const NCollection_Array1<double>& aKnotSequence = theCurve->KnotSequence();
|
||||
const NCollection_Array1<gp_Pnt2d>& aPoles = theCurve->Poles();
|
||||
const NCollection_Array1<double>* aWeights = theCurve->Weights();
|
||||
|
||||
occ::handle<BSplCLib_Cache> aCache =
|
||||
new BSplCLib_Cache(theCurve->Degree(), false, aKnotSequence, aPoles, aWeights);
|
||||
aCache->BuildCache(0.5, aKnotSequence, aPoles, aWeights);
|
||||
return aCache;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
NCollection_Array1<gp_Pnt2d> Geom2dGridEval_BezierCurve::EvaluateGrid(
|
||||
const NCollection_Array1<double>& theParams) const
|
||||
{
|
||||
if (myGeom.IsNull() || theParams.IsEmpty())
|
||||
{
|
||||
return NCollection_Array1<gp_Pnt2d>();
|
||||
}
|
||||
|
||||
const int aNb = theParams.Size();
|
||||
NCollection_Array1<gp_Pnt2d> aResult(1, aNb);
|
||||
|
||||
occ::handle<BSplCLib_Cache> aCache = CreateBezierCache2d(myGeom);
|
||||
|
||||
for (int i = theParams.Lower(); i <= theParams.Upper(); ++i)
|
||||
{
|
||||
gp_Pnt2d aP;
|
||||
aCache->D0(theParams.Value(i), aP);
|
||||
aResult.SetValue(i - theParams.Lower() + 1, aP);
|
||||
}
|
||||
return aResult;
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
NCollection_Array1<Geom2dGridEval::CurveD1> Geom2dGridEval_BezierCurve::EvaluateGridD1(
|
||||
const NCollection_Array1<double>& theParams) const
|
||||
{
|
||||
if (myGeom.IsNull() || theParams.IsEmpty())
|
||||
{
|
||||
return NCollection_Array1<Geom2dGridEval::CurveD1>();
|
||||
}
|
||||
|
||||
const int aNb = theParams.Size();
|
||||
NCollection_Array1<Geom2dGridEval::CurveD1> aResult(1, aNb);
|
||||
|
||||
occ::handle<BSplCLib_Cache> aCache = CreateBezierCache2d(myGeom);
|
||||
|
||||
for (int i = theParams.Lower(); i <= theParams.Upper(); ++i)
|
||||
{
|
||||
gp_Pnt2d aP;
|
||||
gp_Vec2d aD1;
|
||||
aCache->D1(theParams.Value(i), aP, aD1);
|
||||
aResult.ChangeValue(i - theParams.Lower() + 1) = {aP, aD1};
|
||||
}
|
||||
return aResult;
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
NCollection_Array1<Geom2dGridEval::CurveD2> Geom2dGridEval_BezierCurve::EvaluateGridD2(
|
||||
const NCollection_Array1<double>& theParams) const
|
||||
{
|
||||
if (myGeom.IsNull() || theParams.IsEmpty())
|
||||
{
|
||||
return NCollection_Array1<Geom2dGridEval::CurveD2>();
|
||||
}
|
||||
|
||||
const int aNb = theParams.Size();
|
||||
NCollection_Array1<Geom2dGridEval::CurveD2> aResult(1, aNb);
|
||||
|
||||
occ::handle<BSplCLib_Cache> aCache = CreateBezierCache2d(myGeom);
|
||||
|
||||
for (int i = theParams.Lower(); i <= theParams.Upper(); ++i)
|
||||
{
|
||||
gp_Pnt2d aP;
|
||||
gp_Vec2d aD1, aD2;
|
||||
aCache->D2(theParams.Value(i), aP, aD1, aD2);
|
||||
aResult.ChangeValue(i - theParams.Lower() + 1) = {aP, aD1, aD2};
|
||||
}
|
||||
return aResult;
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
NCollection_Array1<Geom2dGridEval::CurveD3> Geom2dGridEval_BezierCurve::EvaluateGridD3(
|
||||
const NCollection_Array1<double>& theParams) const
|
||||
{
|
||||
if (myGeom.IsNull() || theParams.IsEmpty())
|
||||
{
|
||||
return NCollection_Array1<Geom2dGridEval::CurveD3>();
|
||||
}
|
||||
|
||||
const int aNb = theParams.Size();
|
||||
NCollection_Array1<Geom2dGridEval::CurveD3> aResult(1, aNb);
|
||||
|
||||
occ::handle<BSplCLib_Cache> aCache = CreateBezierCache2d(myGeom);
|
||||
|
||||
for (int i = theParams.Lower(); i <= theParams.Upper(); ++i)
|
||||
{
|
||||
gp_Pnt2d aP;
|
||||
gp_Vec2d aD1, aD2, aD3;
|
||||
aCache->D3(theParams.Value(i), aP, aD1, aD2, aD3);
|
||||
aResult.ChangeValue(i - theParams.Lower() + 1) = {aP, aD1, aD2, aD3};
|
||||
}
|
||||
return aResult;
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
NCollection_Array1<gp_Vec2d> Geom2dGridEval_BezierCurve::EvaluateGridDN(
|
||||
const NCollection_Array1<double>& theParams,
|
||||
int theN) const
|
||||
{
|
||||
if (myGeom.IsNull() || theParams.IsEmpty() || theN < 1)
|
||||
{
|
||||
return NCollection_Array1<gp_Vec2d>();
|
||||
}
|
||||
|
||||
const int aNb = theParams.Size();
|
||||
NCollection_Array1<gp_Vec2d> aResult(1, aNb);
|
||||
|
||||
// For Bezier curves, derivatives become zero when order exceeds degree
|
||||
const int aDegree = myGeom->Degree();
|
||||
if (theN > aDegree)
|
||||
{
|
||||
const gp_Vec2d aZeroVec(0.0, 0.0);
|
||||
for (int i = 1; i <= aNb; ++i)
|
||||
{
|
||||
aResult.SetValue(i, aZeroVec);
|
||||
}
|
||||
return aResult;
|
||||
}
|
||||
|
||||
// Get poles, weights, and flat knots from geometry
|
||||
const NCollection_Array1<gp_Pnt2d>& aPoles = myGeom->Poles();
|
||||
const NCollection_Array1<double>* aWeights = myGeom->Weights();
|
||||
const NCollection_Array1<double>& aKnotSequence = myGeom->KnotSequence();
|
||||
|
||||
// Bezier has a single span (index 0 with flat knots), non-periodic
|
||||
for (int i = theParams.Lower(); i <= theParams.Upper(); ++i)
|
||||
{
|
||||
gp_Vec2d aDN;
|
||||
BSplCLib::DN(theParams.Value(i),
|
||||
theN,
|
||||
0, // span index (single span for Bezier with flat knots)
|
||||
aDegree,
|
||||
false, // not periodic
|
||||
aPoles,
|
||||
aWeights,
|
||||
aKnotSequence,
|
||||
nullptr, // no multiplicities with flat knots
|
||||
aDN);
|
||||
aResult.SetValue(i - theParams.Lower() + 1, aDN);
|
||||
}
|
||||
return aResult;
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
// 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 _Geom2dGridEval_BezierCurve_HeaderFile
|
||||
#define _Geom2dGridEval_BezierCurve_HeaderFile
|
||||
|
||||
#include <BSplCLib_Cache.hxx>
|
||||
#include <Geom2d_BezierCurve.hxx>
|
||||
#include <Geom2dGridEval.hxx>
|
||||
#include <NCollection_Array1.hxx>
|
||||
#include <Standard.hxx>
|
||||
#include <Standard_DefineAlloc.hxx>
|
||||
|
||||
//! @brief Efficient batch evaluator for 2D Bezier curve grid points.
|
||||
//!
|
||||
//! Uses BSplCLib to evaluate Bezier curves (treated as B-Splines).
|
||||
//!
|
||||
//! Usage:
|
||||
//! @code
|
||||
//! Geom2dGridEval_BezierCurve anEvaluator(myGeom2dBezier);
|
||||
//! NCollection_Array1<gp_Pnt2d> aGrid = anEvaluator.EvaluateGrid(myParams);
|
||||
//! @endcode
|
||||
class Geom2dGridEval_BezierCurve
|
||||
{
|
||||
public:
|
||||
DEFINE_STANDARD_ALLOC
|
||||
|
||||
//! Constructor with geometry.
|
||||
//! @param theBezier the 2D bezier curve geometry to evaluate
|
||||
Geom2dGridEval_BezierCurve(const occ::handle<Geom2d_BezierCurve>& theBezier)
|
||||
: myGeom(theBezier)
|
||||
{
|
||||
}
|
||||
|
||||
//! Non-copyable and non-movable.
|
||||
Geom2dGridEval_BezierCurve(const Geom2dGridEval_BezierCurve&) = delete;
|
||||
Geom2dGridEval_BezierCurve& operator=(const Geom2dGridEval_BezierCurve&) = delete;
|
||||
Geom2dGridEval_BezierCurve(Geom2dGridEval_BezierCurve&&) = delete;
|
||||
Geom2dGridEval_BezierCurve& operator=(Geom2dGridEval_BezierCurve&&) = delete;
|
||||
|
||||
//! Returns the geometry handle.
|
||||
const occ::handle<Geom2d_BezierCurve>& Geometry() const { return myGeom; }
|
||||
|
||||
//! Evaluate all grid points.
|
||||
//! @param theParams array of parameter values
|
||||
//! @return array of evaluated points (1-based indexing),
|
||||
//! or empty array if geometry is null or no parameters
|
||||
Standard_EXPORT NCollection_Array1<gp_Pnt2d> EvaluateGrid(
|
||||
const NCollection_Array1<double>& theParams) const;
|
||||
|
||||
//! Evaluate all grid points with first derivative.
|
||||
//! @param theParams array of parameter values
|
||||
//! @return array of CurveD1 (1-based indexing)
|
||||
Standard_EXPORT NCollection_Array1<Geom2dGridEval::CurveD1> EvaluateGridD1(
|
||||
const NCollection_Array1<double>& theParams) const;
|
||||
|
||||
//! Evaluate all grid points with first and second derivatives.
|
||||
//! @param theParams array of parameter values
|
||||
//! @return array of CurveD2 (1-based indexing)
|
||||
Standard_EXPORT NCollection_Array1<Geom2dGridEval::CurveD2> EvaluateGridD2(
|
||||
const NCollection_Array1<double>& theParams) const;
|
||||
|
||||
//! Evaluate all grid points with first, second, and third derivatives.
|
||||
//! @param theParams array of parameter values
|
||||
//! @return array of CurveD3 (1-based indexing)
|
||||
Standard_EXPORT NCollection_Array1<Geom2dGridEval::CurveD3> EvaluateGridD3(
|
||||
const NCollection_Array1<double>& theParams) const;
|
||||
|
||||
//! Evaluate Nth derivative at all grid points.
|
||||
//! For orders 1-3, reuses EvaluateGridD1/D2/D3.
|
||||
//! For orders > 3, uses BSplCLib::DN.
|
||||
//! @param theParams array of parameter values
|
||||
//! @param theN derivative order (N >= 1)
|
||||
//! @return array of derivative vectors (1-based indexing)
|
||||
Standard_EXPORT NCollection_Array1<gp_Vec2d> EvaluateGridDN(
|
||||
const NCollection_Array1<double>& theParams,
|
||||
int theN) const;
|
||||
|
||||
private:
|
||||
occ::handle<Geom2d_BezierCurve> myGeom;
|
||||
};
|
||||
|
||||
#endif // _Geom2dGridEval_BezierCurve_HeaderFile
|
||||
@@ -0,0 +1,256 @@
|
||||
// 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 <Geom2dGridEval_Circle.hxx>
|
||||
|
||||
#include <gp_Circ2d.hxx>
|
||||
|
||||
#include <cmath>
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
NCollection_Array1<gp_Pnt2d> Geom2dGridEval_Circle::EvaluateGrid(
|
||||
const NCollection_Array1<double>& theParams) const
|
||||
{
|
||||
if (myGeom.IsNull() || theParams.IsEmpty())
|
||||
{
|
||||
return NCollection_Array1<gp_Pnt2d>();
|
||||
}
|
||||
|
||||
const int aNb = theParams.Size();
|
||||
NCollection_Array1<gp_Pnt2d> aResult(1, aNb);
|
||||
|
||||
// Extract circle data from geometry
|
||||
const gp_Circ2d& aCirc = myGeom->Circ2d();
|
||||
const gp_Pnt2d& aCenter = aCirc.Location();
|
||||
const gp_Dir2d& aXDir = aCirc.Position().XDirection();
|
||||
const gp_Dir2d& aYDir = aCirc.Position().YDirection();
|
||||
const double aRadius = aCirc.Radius();
|
||||
|
||||
// Pre-extract coordinates for performance
|
||||
const double aCX = aCenter.X();
|
||||
const double aCY = aCenter.Y();
|
||||
const double aXX = aXDir.X();
|
||||
const double aXY = aXDir.Y();
|
||||
const double aYX = aYDir.X();
|
||||
const double aYY = aYDir.Y();
|
||||
|
||||
for (int i = theParams.Lower(); i <= theParams.Upper(); ++i)
|
||||
{
|
||||
const double u = theParams.Value(i);
|
||||
const double cosU = std::cos(u);
|
||||
const double sinU = std::sin(u);
|
||||
|
||||
aResult.SetValue(i - theParams.Lower() + 1,
|
||||
gp_Pnt2d(aCX + aRadius * (cosU * aXX + sinU * aYX),
|
||||
aCY + aRadius * (cosU * aXY + sinU * aYY)));
|
||||
}
|
||||
return aResult;
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
NCollection_Array1<Geom2dGridEval::CurveD1> Geom2dGridEval_Circle::EvaluateGridD1(
|
||||
const NCollection_Array1<double>& theParams) const
|
||||
{
|
||||
if (myGeom.IsNull() || theParams.IsEmpty())
|
||||
{
|
||||
return NCollection_Array1<Geom2dGridEval::CurveD1>();
|
||||
}
|
||||
|
||||
const int aNb = theParams.Size();
|
||||
NCollection_Array1<Geom2dGridEval::CurveD1> aResult(1, aNb);
|
||||
|
||||
const gp_Circ2d& aCirc = myGeom->Circ2d();
|
||||
const gp_Pnt2d& aCenter = aCirc.Location();
|
||||
const gp_Dir2d& aXDir = aCirc.Position().XDirection();
|
||||
const gp_Dir2d& aYDir = aCirc.Position().YDirection();
|
||||
const double aRadius = aCirc.Radius();
|
||||
|
||||
const double aCX = aCenter.X();
|
||||
const double aCY = aCenter.Y();
|
||||
const double aXX = aXDir.X();
|
||||
const double aXY = aXDir.Y();
|
||||
const double aYX = aYDir.X();
|
||||
const double aYY = aYDir.Y();
|
||||
|
||||
for (int i = theParams.Lower(); i <= theParams.Upper(); ++i)
|
||||
{
|
||||
const double u = theParams.Value(i);
|
||||
const double cosU = std::cos(u);
|
||||
const double sinU = std::sin(u);
|
||||
|
||||
// P = C + R * (cos(u) * X + sin(u) * Y)
|
||||
// D1 = R * (-sin(u) * X + cos(u) * Y)
|
||||
aResult.ChangeValue(i - theParams.Lower() + 1) = {
|
||||
gp_Pnt2d(aCX + aRadius * (cosU * aXX + sinU * aYX),
|
||||
aCY + aRadius * (cosU * aXY + sinU * aYY)),
|
||||
gp_Vec2d(aRadius * (-sinU * aXX + cosU * aYX), aRadius * (-sinU * aXY + cosU * aYY))};
|
||||
}
|
||||
return aResult;
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
NCollection_Array1<Geom2dGridEval::CurveD2> Geom2dGridEval_Circle::EvaluateGridD2(
|
||||
const NCollection_Array1<double>& theParams) const
|
||||
{
|
||||
if (myGeom.IsNull() || theParams.IsEmpty())
|
||||
{
|
||||
return NCollection_Array1<Geom2dGridEval::CurveD2>();
|
||||
}
|
||||
|
||||
const int aNb = theParams.Size();
|
||||
NCollection_Array1<Geom2dGridEval::CurveD2> aResult(1, aNb);
|
||||
|
||||
const gp_Circ2d& aCirc = myGeom->Circ2d();
|
||||
const gp_Pnt2d& aCenter = aCirc.Location();
|
||||
const gp_Dir2d& aXDir = aCirc.Position().XDirection();
|
||||
const gp_Dir2d& aYDir = aCirc.Position().YDirection();
|
||||
const double aRadius = aCirc.Radius();
|
||||
|
||||
const double aCX = aCenter.X();
|
||||
const double aCY = aCenter.Y();
|
||||
const double aXX = aXDir.X();
|
||||
const double aXY = aXDir.Y();
|
||||
const double aYX = aYDir.X();
|
||||
const double aYY = aYDir.Y();
|
||||
|
||||
for (int i = theParams.Lower(); i <= theParams.Upper(); ++i)
|
||||
{
|
||||
const double u = theParams.Value(i);
|
||||
const double cosU = std::cos(u);
|
||||
const double sinU = std::sin(u);
|
||||
|
||||
// P = C + R * (cos(u) * X + sin(u) * Y)
|
||||
// D1 = R * (-sin(u) * X + cos(u) * Y)
|
||||
// D2 = R * (-cos(u) * X - sin(u) * Y)
|
||||
aResult.ChangeValue(i - theParams.Lower() + 1) = {
|
||||
gp_Pnt2d(aCX + aRadius * (cosU * aXX + sinU * aYX),
|
||||
aCY + aRadius * (cosU * aXY + sinU * aYY)),
|
||||
gp_Vec2d(aRadius * (-sinU * aXX + cosU * aYX), aRadius * (-sinU * aXY + cosU * aYY)),
|
||||
gp_Vec2d(aRadius * (-cosU * aXX - sinU * aYX), aRadius * (-cosU * aXY - sinU * aYY))};
|
||||
}
|
||||
return aResult;
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
NCollection_Array1<Geom2dGridEval::CurveD3> Geom2dGridEval_Circle::EvaluateGridD3(
|
||||
const NCollection_Array1<double>& theParams) const
|
||||
{
|
||||
if (myGeom.IsNull() || theParams.IsEmpty())
|
||||
{
|
||||
return NCollection_Array1<Geom2dGridEval::CurveD3>();
|
||||
}
|
||||
|
||||
const int aNb = theParams.Size();
|
||||
NCollection_Array1<Geom2dGridEval::CurveD3> aResult(1, aNb);
|
||||
|
||||
const gp_Circ2d& aCirc = myGeom->Circ2d();
|
||||
const gp_Pnt2d& aCenter = aCirc.Location();
|
||||
const gp_Dir2d& aXDir = aCirc.Position().XDirection();
|
||||
const gp_Dir2d& aYDir = aCirc.Position().YDirection();
|
||||
const double aRadius = aCirc.Radius();
|
||||
|
||||
const double aCX = aCenter.X();
|
||||
const double aCY = aCenter.Y();
|
||||
const double aXX = aXDir.X();
|
||||
const double aXY = aXDir.Y();
|
||||
const double aYX = aYDir.X();
|
||||
const double aYY = aYDir.Y();
|
||||
|
||||
for (int i = theParams.Lower(); i <= theParams.Upper(); ++i)
|
||||
{
|
||||
const double u = theParams.Value(i);
|
||||
const double cosU = std::cos(u);
|
||||
const double sinU = std::sin(u);
|
||||
|
||||
// P = C + R * (cos(u) * X + sin(u) * Y)
|
||||
// D1 = R * (-sin(u) * X + cos(u) * Y)
|
||||
// D2 = R * (-cos(u) * X - sin(u) * Y)
|
||||
// D3 = R * (sin(u) * X - cos(u) * Y)
|
||||
aResult.ChangeValue(i - theParams.Lower() + 1) = {
|
||||
gp_Pnt2d(aCX + aRadius * (cosU * aXX + sinU * aYX),
|
||||
aCY + aRadius * (cosU * aXY + sinU * aYY)),
|
||||
gp_Vec2d(aRadius * (-sinU * aXX + cosU * aYX), aRadius * (-sinU * aXY + cosU * aYY)),
|
||||
gp_Vec2d(aRadius * (-cosU * aXX - sinU * aYX), aRadius * (-cosU * aXY - sinU * aYY)),
|
||||
gp_Vec2d(aRadius * (sinU * aXX - cosU * aYX), aRadius * (sinU * aXY - cosU * aYY))};
|
||||
}
|
||||
return aResult;
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
NCollection_Array1<gp_Vec2d> Geom2dGridEval_Circle::EvaluateGridDN(
|
||||
const NCollection_Array1<double>& theParams,
|
||||
int theN) const
|
||||
{
|
||||
if (myGeom.IsNull() || theParams.IsEmpty() || theN < 1)
|
||||
{
|
||||
return NCollection_Array1<gp_Vec2d>();
|
||||
}
|
||||
|
||||
const int aNb = theParams.Size();
|
||||
NCollection_Array1<gp_Vec2d> aResult(1, aNb);
|
||||
|
||||
const gp_Circ2d& aCirc = myGeom->Circ2d();
|
||||
const gp_Dir2d& aXDir = aCirc.Position().XDirection();
|
||||
const gp_Dir2d& aYDir = aCirc.Position().YDirection();
|
||||
const double aRadius = aCirc.Radius();
|
||||
|
||||
const double aXX = aXDir.X();
|
||||
const double aXY = aXDir.Y();
|
||||
const double aYX = aYDir.X();
|
||||
const double aYY = aYDir.Y();
|
||||
|
||||
// Circle derivatives are cyclic with period 4:
|
||||
// D1 = R * (-sin(u) * X + cos(u) * Y) -> coefficients: (-sin, cos)
|
||||
// D2 = R * (-cos(u) * X - sin(u) * Y) -> coefficients: (-cos, -sin)
|
||||
// D3 = R * (sin(u) * X - cos(u) * Y) -> coefficients: (sin, -cos)
|
||||
// D4 = R * (cos(u) * X + sin(u) * Y) -> coefficients: (cos, sin) = D0
|
||||
const int aPhase = (theN - 1) % 4; // 0->D1, 1->D2, 2->D3, 3->D4
|
||||
|
||||
for (int i = theParams.Lower(); i <= theParams.Upper(); ++i)
|
||||
{
|
||||
const double u = theParams.Value(i);
|
||||
const double cosU = std::cos(u);
|
||||
const double sinU = std::sin(u);
|
||||
|
||||
double aCoeffX, aCoeffY;
|
||||
switch (aPhase)
|
||||
{
|
||||
case 0: // D1, D5, D9, ...
|
||||
aCoeffX = -sinU;
|
||||
aCoeffY = cosU;
|
||||
break;
|
||||
case 1: // D2, D6, D10, ...
|
||||
aCoeffX = -cosU;
|
||||
aCoeffY = -sinU;
|
||||
break;
|
||||
case 2: // D3, D7, D11, ...
|
||||
aCoeffX = sinU;
|
||||
aCoeffY = -cosU;
|
||||
break;
|
||||
default: // D4, D8, D12, ... (case 3)
|
||||
aCoeffX = cosU;
|
||||
aCoeffY = sinU;
|
||||
break;
|
||||
}
|
||||
|
||||
aResult.SetValue(i - theParams.Lower() + 1,
|
||||
gp_Vec2d(aRadius * (aCoeffX * aXX + aCoeffY * aYX),
|
||||
aRadius * (aCoeffX * aXY + aCoeffY * aYY)));
|
||||
}
|
||||
return aResult;
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
// 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 _Geom2dGridEval_Circle_HeaderFile
|
||||
#define _Geom2dGridEval_Circle_HeaderFile
|
||||
|
||||
#include <Geom2d_Circle.hxx>
|
||||
#include <Geom2dGridEval.hxx>
|
||||
#include <NCollection_Array1.hxx>
|
||||
#include <Standard.hxx>
|
||||
#include <Standard_DefineAlloc.hxx>
|
||||
|
||||
//! @brief Efficient batch evaluator for 2D circle grid points.
|
||||
//!
|
||||
//! Uses analytical formula: P(u) = Center + R * (cos(u) * XDir + sin(u) * YDir)
|
||||
//!
|
||||
//! Usage:
|
||||
//! @code
|
||||
//! Geom2dGridEval_Circle anEvaluator(myGeom2dCircle);
|
||||
//! NCollection_Array1<gp_Pnt2d> aGrid = anEvaluator.EvaluateGrid(myParams);
|
||||
//! @endcode
|
||||
class Geom2dGridEval_Circle
|
||||
{
|
||||
public:
|
||||
DEFINE_STANDARD_ALLOC
|
||||
|
||||
//! Constructor with geometry.
|
||||
//! @param theCircle the 2D circle geometry to evaluate
|
||||
Geom2dGridEval_Circle(const occ::handle<Geom2d_Circle>& theCircle)
|
||||
: myGeom(theCircle)
|
||||
{
|
||||
}
|
||||
|
||||
//! Non-copyable and non-movable.
|
||||
Geom2dGridEval_Circle(const Geom2dGridEval_Circle&) = delete;
|
||||
Geom2dGridEval_Circle& operator=(const Geom2dGridEval_Circle&) = delete;
|
||||
Geom2dGridEval_Circle(Geom2dGridEval_Circle&&) = delete;
|
||||
Geom2dGridEval_Circle& operator=(Geom2dGridEval_Circle&&) = delete;
|
||||
|
||||
//! Returns the geometry handle.
|
||||
const occ::handle<Geom2d_Circle>& Geometry() const { return myGeom; }
|
||||
|
||||
//! Evaluate all grid points.
|
||||
//! @param theParams array of parameter values (angles in radians)
|
||||
//! @return array of evaluated points (1-based indexing),
|
||||
//! or empty array if geometry is null or no parameters
|
||||
Standard_EXPORT NCollection_Array1<gp_Pnt2d> EvaluateGrid(
|
||||
const NCollection_Array1<double>& theParams) const;
|
||||
|
||||
//! Evaluate all grid points with first derivative.
|
||||
//! D1 = R * (-sin(u) * XDir + cos(u) * YDir)
|
||||
//! @param theParams array of parameter values
|
||||
//! @return array of CurveD1 (1-based indexing),
|
||||
//! or empty array if geometry is null or no parameters
|
||||
Standard_EXPORT NCollection_Array1<Geom2dGridEval::CurveD1> EvaluateGridD1(
|
||||
const NCollection_Array1<double>& theParams) const;
|
||||
|
||||
//! Evaluate all grid points with first and second derivatives.
|
||||
//! D2 = R * (-cos(u) * XDir - sin(u) * YDir) = -P (relative to center)
|
||||
//! @param theParams array of parameter values
|
||||
//! @return array of CurveD2 (1-based indexing),
|
||||
//! or empty array if geometry is null or no parameters
|
||||
Standard_EXPORT NCollection_Array1<Geom2dGridEval::CurveD2> EvaluateGridD2(
|
||||
const NCollection_Array1<double>& theParams) const;
|
||||
|
||||
//! Evaluate all grid points with first, second, and third derivatives.
|
||||
//! D3 = R * (sin(u) * XDir - cos(u) * YDir) = -D1
|
||||
//! @param theParams array of parameter values
|
||||
//! @return array of CurveD3 (1-based indexing),
|
||||
//! or empty array if geometry is null or no parameters
|
||||
Standard_EXPORT NCollection_Array1<Geom2dGridEval::CurveD3> EvaluateGridD3(
|
||||
const NCollection_Array1<double>& theParams) const;
|
||||
|
||||
//! Evaluate Nth derivative at all grid points.
|
||||
//! Circle has cyclic derivatives with period 4:
|
||||
//! D1 = R * (-sin(u) * X + cos(u) * Y)
|
||||
//! D2 = R * (-cos(u) * X - sin(u) * Y)
|
||||
//! D3 = R * (sin(u) * X - cos(u) * Y)
|
||||
//! D4 = R * (cos(u) * X + sin(u) * Y) = D0, then repeats
|
||||
//! @param theParams array of parameter values
|
||||
//! @param theN derivative order (N >= 1)
|
||||
//! @return array of derivative vectors (1-based indexing),
|
||||
//! or empty array if geometry is null or no parameters
|
||||
Standard_EXPORT NCollection_Array1<gp_Vec2d> EvaluateGridDN(
|
||||
const NCollection_Array1<double>& theParams,
|
||||
int theN) const;
|
||||
|
||||
private:
|
||||
occ::handle<Geom2d_Circle> myGeom;
|
||||
};
|
||||
|
||||
#endif // _Geom2dGridEval_Circle_HeaderFile
|
||||
@@ -0,0 +1,229 @@
|
||||
// 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 <Geom2dGridEval_Curve.hxx>
|
||||
|
||||
#include <Geom2dAdaptor_Curve.hxx>
|
||||
#include <Geom2d_BezierCurve.hxx>
|
||||
#include <Geom2d_BSplineCurve.hxx>
|
||||
#include <Geom2d_Circle.hxx>
|
||||
#include <Geom2d_Ellipse.hxx>
|
||||
#include <Geom2d_Hyperbola.hxx>
|
||||
#include <Geom2d_Line.hxx>
|
||||
#include <Geom2d_OffsetCurve.hxx>
|
||||
#include <Geom2d_Parabola.hxx>
|
||||
#include <Geom2d_TrimmedCurve.hxx>
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
//! Extracts basis curve from potentially nested TrimmedCurve wrappers.
|
||||
//! @param theCurve input curve (may be TrimmedCurve or any other)
|
||||
//! @return the underlying basis curve, or theCurve if not a TrimmedCurve
|
||||
occ::handle<Geom2d_Curve> ExtractBasisCurve(const occ::handle<Geom2d_Curve>& theCurve)
|
||||
{
|
||||
occ::handle<Geom2d_Curve> aResult = theCurve;
|
||||
while (auto aTrimmed = occ::down_cast<Geom2d_TrimmedCurve>(aResult))
|
||||
{
|
||||
aResult = aTrimmed->BasisCurve();
|
||||
}
|
||||
return aResult;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
void Geom2dGridEval_Curve::Initialize(const Adaptor2d_Curve2d& theCurve)
|
||||
{
|
||||
if (theCurve.IsKind(STANDARD_TYPE(Geom2dAdaptor_Curve)))
|
||||
{
|
||||
Initialize(static_cast<const Geom2dAdaptor_Curve&>(theCurve).Curve());
|
||||
return;
|
||||
}
|
||||
|
||||
// For non-Geom2dAdaptor or when Geom2d_Curve is not available,
|
||||
// use reference for the evaluator
|
||||
myCurveType = theCurve.GetType();
|
||||
myEvaluator.emplace<Geom2dGridEval_OtherCurve>(theCurve);
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
void Geom2dGridEval_Curve::Initialize(const occ::handle<Geom2d_Curve>& theCurve)
|
||||
{
|
||||
if (theCurve.IsNull())
|
||||
{
|
||||
myEvaluator.emplace<std::monostate>();
|
||||
myCurveType = GeomAbs_OtherCurve;
|
||||
return;
|
||||
}
|
||||
|
||||
// Extract basis curve from potentially nested TrimmedCurve wrappers
|
||||
occ::handle<Geom2d_Curve> aBasisCurve = ExtractBasisCurve(theCurve);
|
||||
|
||||
if (auto aLine = occ::down_cast<Geom2d_Line>(aBasisCurve))
|
||||
{
|
||||
myCurveType = GeomAbs_Line;
|
||||
myEvaluator.emplace<Geom2dGridEval_Line>(aLine);
|
||||
}
|
||||
else if (auto aCircle = occ::down_cast<Geom2d_Circle>(aBasisCurve))
|
||||
{
|
||||
myCurveType = GeomAbs_Circle;
|
||||
myEvaluator.emplace<Geom2dGridEval_Circle>(aCircle);
|
||||
}
|
||||
else if (auto anEllipse = occ::down_cast<Geom2d_Ellipse>(aBasisCurve))
|
||||
{
|
||||
myCurveType = GeomAbs_Ellipse;
|
||||
myEvaluator.emplace<Geom2dGridEval_Ellipse>(anEllipse);
|
||||
}
|
||||
else if (auto aHyperbola = occ::down_cast<Geom2d_Hyperbola>(aBasisCurve))
|
||||
{
|
||||
myCurveType = GeomAbs_Hyperbola;
|
||||
myEvaluator.emplace<Geom2dGridEval_Hyperbola>(aHyperbola);
|
||||
}
|
||||
else if (auto aParabola = occ::down_cast<Geom2d_Parabola>(aBasisCurve))
|
||||
{
|
||||
myCurveType = GeomAbs_Parabola;
|
||||
myEvaluator.emplace<Geom2dGridEval_Parabola>(aParabola);
|
||||
}
|
||||
else if (auto aBezier = occ::down_cast<Geom2d_BezierCurve>(aBasisCurve))
|
||||
{
|
||||
myCurveType = GeomAbs_BezierCurve;
|
||||
myEvaluator.emplace<Geom2dGridEval_BezierCurve>(aBezier);
|
||||
}
|
||||
else if (auto aBSpline = occ::down_cast<Geom2d_BSplineCurve>(aBasisCurve))
|
||||
{
|
||||
myCurveType = GeomAbs_BSplineCurve;
|
||||
myEvaluator.emplace<Geom2dGridEval_BSplineCurve>(aBSpline);
|
||||
}
|
||||
else if (auto anOffset = occ::down_cast<Geom2d_OffsetCurve>(aBasisCurve))
|
||||
{
|
||||
myCurveType = GeomAbs_OffsetCurve;
|
||||
myEvaluator.emplace<Geom2dGridEval_OffsetCurve>(anOffset);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Unknown curve type - set uninitialized
|
||||
myEvaluator.emplace<std::monostate>();
|
||||
myCurveType = GeomAbs_OtherCurve;
|
||||
}
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
bool Geom2dGridEval_Curve::IsInitialized() const
|
||||
{
|
||||
return !std::holds_alternative<std::monostate>(myEvaluator);
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
NCollection_Array1<gp_Pnt2d> Geom2dGridEval_Curve::EvaluateGrid(
|
||||
const NCollection_Array1<double>& theParams) const
|
||||
{
|
||||
return std::visit(
|
||||
[&theParams](const auto& theEval) -> NCollection_Array1<gp_Pnt2d> {
|
||||
using T = std::decay_t<decltype(theEval)>;
|
||||
if constexpr (std::is_same_v<T, std::monostate>)
|
||||
{
|
||||
return NCollection_Array1<gp_Pnt2d>();
|
||||
}
|
||||
else
|
||||
{
|
||||
return theEval.EvaluateGrid(theParams);
|
||||
}
|
||||
},
|
||||
myEvaluator);
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
NCollection_Array1<Geom2dGridEval::CurveD1> Geom2dGridEval_Curve::EvaluateGridD1(
|
||||
const NCollection_Array1<double>& theParams) const
|
||||
{
|
||||
return std::visit(
|
||||
[&theParams](const auto& theEval) -> NCollection_Array1<Geom2dGridEval::CurveD1> {
|
||||
using T = std::decay_t<decltype(theEval)>;
|
||||
if constexpr (std::is_same_v<T, std::monostate>)
|
||||
{
|
||||
return NCollection_Array1<Geom2dGridEval::CurveD1>();
|
||||
}
|
||||
else
|
||||
{
|
||||
return theEval.EvaluateGridD1(theParams);
|
||||
}
|
||||
},
|
||||
myEvaluator);
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
NCollection_Array1<Geom2dGridEval::CurveD2> Geom2dGridEval_Curve::EvaluateGridD2(
|
||||
const NCollection_Array1<double>& theParams) const
|
||||
{
|
||||
return std::visit(
|
||||
[&theParams](const auto& theEval) -> NCollection_Array1<Geom2dGridEval::CurveD2> {
|
||||
using T = std::decay_t<decltype(theEval)>;
|
||||
if constexpr (std::is_same_v<T, std::monostate>)
|
||||
{
|
||||
return NCollection_Array1<Geom2dGridEval::CurveD2>();
|
||||
}
|
||||
else
|
||||
{
|
||||
return theEval.EvaluateGridD2(theParams);
|
||||
}
|
||||
},
|
||||
myEvaluator);
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
NCollection_Array1<Geom2dGridEval::CurveD3> Geom2dGridEval_Curve::EvaluateGridD3(
|
||||
const NCollection_Array1<double>& theParams) const
|
||||
{
|
||||
return std::visit(
|
||||
[&theParams](const auto& theEval) -> NCollection_Array1<Geom2dGridEval::CurveD3> {
|
||||
using T = std::decay_t<decltype(theEval)>;
|
||||
if constexpr (std::is_same_v<T, std::monostate>)
|
||||
{
|
||||
return NCollection_Array1<Geom2dGridEval::CurveD3>();
|
||||
}
|
||||
else
|
||||
{
|
||||
return theEval.EvaluateGridD3(theParams);
|
||||
}
|
||||
},
|
||||
myEvaluator);
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
NCollection_Array1<gp_Vec2d> Geom2dGridEval_Curve::EvaluateGridDN(
|
||||
const NCollection_Array1<double>& theParams,
|
||||
int theN) const
|
||||
{
|
||||
return std::visit(
|
||||
[&theParams, theN](const auto& theEval) -> NCollection_Array1<gp_Vec2d> {
|
||||
using T = std::decay_t<decltype(theEval)>;
|
||||
if constexpr (std::is_same_v<T, std::monostate>)
|
||||
{
|
||||
return NCollection_Array1<gp_Vec2d>();
|
||||
}
|
||||
else
|
||||
{
|
||||
return theEval.EvaluateGridDN(theParams, theN);
|
||||
}
|
||||
},
|
||||
myEvaluator);
|
||||
}
|
||||
@@ -0,0 +1,146 @@
|
||||
// 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 _Geom2dGridEval_Curve_HeaderFile
|
||||
#define _Geom2dGridEval_Curve_HeaderFile
|
||||
|
||||
#include <Adaptor2d_Curve2d.hxx>
|
||||
#include <GeomAbs_CurveType.hxx>
|
||||
#include <Geom2d_Curve.hxx>
|
||||
#include <Geom2dGridEval_BSplineCurve.hxx>
|
||||
#include <Geom2dGridEval_BezierCurve.hxx>
|
||||
#include <Geom2dGridEval_Circle.hxx>
|
||||
#include <Geom2dGridEval_Ellipse.hxx>
|
||||
#include <Geom2dGridEval_Hyperbola.hxx>
|
||||
#include <Geom2dGridEval_Line.hxx>
|
||||
#include <Geom2dGridEval_OffsetCurve.hxx>
|
||||
#include <Geom2dGridEval_OtherCurve.hxx>
|
||||
#include <Geom2dGridEval_Parabola.hxx>
|
||||
#include <gp_Pnt2d.hxx>
|
||||
#include <NCollection_Array1.hxx>
|
||||
#include <Standard.hxx>
|
||||
#include <Standard_DefineAlloc.hxx>
|
||||
|
||||
#include <variant>
|
||||
|
||||
//! @brief Unified grid evaluator for any 2D curve.
|
||||
//!
|
||||
//! Uses std::variant for compile-time type safety and zero heap allocation
|
||||
//! for the evaluator itself. Automatically detects curve type from
|
||||
//! Adaptor2d_Curve2d and dispatches to the appropriate specialized evaluator.
|
||||
//!
|
||||
//! Supported curve types with optimized evaluation:
|
||||
//! - Line: Direct analytical formula
|
||||
//! - Circle: Trigonometric formula
|
||||
//! - Ellipse: Analytical formula
|
||||
//! - Hyperbola: Analytical formula
|
||||
//! - Parabola: Analytical formula
|
||||
//! - BezierCurve: Optimized batch evaluation via BSplCLib
|
||||
//! - BSplineCurve: Optimized batch evaluation via BSplCLib with span caching
|
||||
//! - OffsetCurve: Composite evaluation using basis curve batch evaluator
|
||||
//! - Other: Fallback using Adaptor2d_Curve2d::D0
|
||||
//!
|
||||
//! Usage:
|
||||
//! @code
|
||||
//! Geom2dGridEval_Curve anEval;
|
||||
//! anEval.Initialize(myAdaptorCurve2d);
|
||||
//! // OR
|
||||
//! anEval.Initialize(myGeom2dCurve);
|
||||
//! NCollection_Array1<gp_Pnt2d> aGrid = anEval.EvaluateGrid(myParams);
|
||||
//! @endcode
|
||||
class Geom2dGridEval_Curve
|
||||
{
|
||||
public:
|
||||
DEFINE_STANDARD_ALLOC
|
||||
|
||||
//! Variant type holding all possible 2D curve evaluators.
|
||||
using EvaluatorVariant = std::variant<std::monostate, // Uninitialized state
|
||||
Geom2dGridEval_Line, // Line curve
|
||||
Geom2dGridEval_Circle, // Circle curve
|
||||
Geom2dGridEval_Ellipse, // Ellipse curve
|
||||
Geom2dGridEval_Hyperbola, // Hyperbola curve
|
||||
Geom2dGridEval_Parabola, // Parabola curve
|
||||
Geom2dGridEval_BezierCurve, // Bezier curve
|
||||
Geom2dGridEval_BSplineCurve, // B-spline curve
|
||||
Geom2dGridEval_OffsetCurve, // Offset curve
|
||||
Geom2dGridEval_OtherCurve>; // Fallback for other types
|
||||
|
||||
//! Default constructor - uninitialized state.
|
||||
Geom2dGridEval_Curve()
|
||||
: myEvaluator(std::monostate{}),
|
||||
myCurveType(GeomAbs_OtherCurve)
|
||||
{
|
||||
}
|
||||
|
||||
//! Non-copyable and non-movable.
|
||||
Geom2dGridEval_Curve(const Geom2dGridEval_Curve&) = delete;
|
||||
Geom2dGridEval_Curve& operator=(const Geom2dGridEval_Curve&) = delete;
|
||||
Geom2dGridEval_Curve(Geom2dGridEval_Curve&&) = delete;
|
||||
Geom2dGridEval_Curve& operator=(Geom2dGridEval_Curve&&) = delete;
|
||||
|
||||
//! Initialize from 2D adaptor reference (auto-detects curve type).
|
||||
//! For Geom2dAdaptor_Curve, extracts underlying Geom2d_Curve for optimized evaluation.
|
||||
//! For other adaptors, stores reference for fallback evaluation.
|
||||
//! @note The curve adaptor reference must remain valid during the lifetime
|
||||
//! of this evaluator when using fallback evaluation.
|
||||
//! @param theCurve 2D curve adaptor reference to evaluate
|
||||
Standard_EXPORT void Initialize(const Adaptor2d_Curve2d& theCurve);
|
||||
|
||||
//! Initialize from geometry handle (auto-detects curve type).
|
||||
//! @param theCurve 2D geometry to evaluate
|
||||
Standard_EXPORT void Initialize(const occ::handle<Geom2d_Curve>& theCurve);
|
||||
|
||||
//! Returns true if properly initialized.
|
||||
Standard_EXPORT bool IsInitialized() const;
|
||||
|
||||
//! Evaluate grid points at all parameters.
|
||||
//! @param theParams array of parameter values
|
||||
//! @return array of 2D points (1-based indexing)
|
||||
Standard_EXPORT NCollection_Array1<gp_Pnt2d> EvaluateGrid(
|
||||
const NCollection_Array1<double>& theParams) const;
|
||||
|
||||
//! Evaluate grid points with first derivative.
|
||||
//! @param theParams array of parameter values
|
||||
//! @return array of CurveD1 (1-based indexing)
|
||||
Standard_EXPORT NCollection_Array1<Geom2dGridEval::CurveD1> EvaluateGridD1(
|
||||
const NCollection_Array1<double>& theParams) const;
|
||||
|
||||
//! Evaluate grid points with first and second derivatives.
|
||||
//! @param theParams array of parameter values
|
||||
//! @return array of CurveD2 (1-based indexing)
|
||||
Standard_EXPORT NCollection_Array1<Geom2dGridEval::CurveD2> EvaluateGridD2(
|
||||
const NCollection_Array1<double>& theParams) const;
|
||||
|
||||
//! Evaluate grid points with first, second, and third derivatives.
|
||||
//! @param theParams array of parameter values
|
||||
//! @return array of CurveD3 (1-based indexing)
|
||||
Standard_EXPORT NCollection_Array1<Geom2dGridEval::CurveD3> EvaluateGridD3(
|
||||
const NCollection_Array1<double>& theParams) const;
|
||||
|
||||
//! Evaluate Nth derivative at all grid points.
|
||||
//! @param theParams array of parameter values
|
||||
//! @param theN derivative order (N >= 1)
|
||||
//! @return array of derivative vectors (1-based indexing)
|
||||
Standard_EXPORT NCollection_Array1<gp_Vec2d> EvaluateGridDN(
|
||||
const NCollection_Array1<double>& theParams,
|
||||
int theN) const;
|
||||
|
||||
//! Returns the detected curve type.
|
||||
GeomAbs_CurveType GetType() const { return myCurveType; }
|
||||
|
||||
private:
|
||||
EvaluatorVariant myEvaluator;
|
||||
GeomAbs_CurveType myCurveType;
|
||||
};
|
||||
|
||||
#endif // _Geom2dGridEval_Curve_HeaderFile
|
||||
@@ -0,0 +1,263 @@
|
||||
// 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 <Geom2dGridEval_Ellipse.hxx>
|
||||
|
||||
#include <gp_Elips2d.hxx>
|
||||
|
||||
#include <cmath>
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
NCollection_Array1<gp_Pnt2d> Geom2dGridEval_Ellipse::EvaluateGrid(
|
||||
const NCollection_Array1<double>& theParams) const
|
||||
{
|
||||
if (myGeom.IsNull() || theParams.IsEmpty())
|
||||
{
|
||||
return NCollection_Array1<gp_Pnt2d>();
|
||||
}
|
||||
|
||||
const int aNb = theParams.Size();
|
||||
NCollection_Array1<gp_Pnt2d> aResult(1, aNb);
|
||||
|
||||
const gp_Elips2d& anElips = myGeom->Elips2d();
|
||||
const gp_Pnt2d& aCenter = anElips.Location();
|
||||
const gp_Dir2d aXDir = anElips.XAxis().Direction();
|
||||
const gp_Dir2d aYDir = anElips.YAxis().Direction();
|
||||
const double aMajR = anElips.MajorRadius();
|
||||
const double aMinR = anElips.MinorRadius();
|
||||
|
||||
const double aCX = aCenter.X();
|
||||
const double aCY = aCenter.Y();
|
||||
const double aXX = aXDir.X();
|
||||
const double aXY = aXDir.Y();
|
||||
const double aYX = aYDir.X();
|
||||
const double aYY = aYDir.Y();
|
||||
|
||||
for (int i = theParams.Lower(); i <= theParams.Upper(); ++i)
|
||||
{
|
||||
const double u = theParams.Value(i);
|
||||
const double cosU = std::cos(u);
|
||||
const double sinU = std::sin(u);
|
||||
|
||||
// P = Center + MajorR * cos(u) * XDir + MinorR * sin(u) * YDir
|
||||
aResult.SetValue(i - theParams.Lower() + 1,
|
||||
gp_Pnt2d(aCX + aMajR * cosU * aXX + aMinR * sinU * aYX,
|
||||
aCY + aMajR * cosU * aXY + aMinR * sinU * aYY));
|
||||
}
|
||||
return aResult;
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
NCollection_Array1<Geom2dGridEval::CurveD1> Geom2dGridEval_Ellipse::EvaluateGridD1(
|
||||
const NCollection_Array1<double>& theParams) const
|
||||
{
|
||||
if (myGeom.IsNull() || theParams.IsEmpty())
|
||||
{
|
||||
return NCollection_Array1<Geom2dGridEval::CurveD1>();
|
||||
}
|
||||
|
||||
const int aNb = theParams.Size();
|
||||
NCollection_Array1<Geom2dGridEval::CurveD1> aResult(1, aNb);
|
||||
|
||||
const gp_Elips2d& anElips = myGeom->Elips2d();
|
||||
const gp_Pnt2d& aCenter = anElips.Location();
|
||||
const gp_Dir2d aXDir = anElips.XAxis().Direction();
|
||||
const gp_Dir2d aYDir = anElips.YAxis().Direction();
|
||||
const double aMajR = anElips.MajorRadius();
|
||||
const double aMinR = anElips.MinorRadius();
|
||||
|
||||
const double aCX = aCenter.X();
|
||||
const double aCY = aCenter.Y();
|
||||
const double aXX = aXDir.X();
|
||||
const double aXY = aXDir.Y();
|
||||
const double aYX = aYDir.X();
|
||||
const double aYY = aYDir.Y();
|
||||
|
||||
for (int i = theParams.Lower(); i <= theParams.Upper(); ++i)
|
||||
{
|
||||
const double u = theParams.Value(i);
|
||||
const double cosU = std::cos(u);
|
||||
const double sinU = std::sin(u);
|
||||
|
||||
// P = Center + MajorR * cos(u) * XDir + MinorR * sin(u) * YDir
|
||||
// D1 = -MajorR * sin(u) * XDir + MinorR * cos(u) * YDir
|
||||
|
||||
aResult.ChangeValue(i - theParams.Lower() + 1) = {
|
||||
gp_Pnt2d(aCX + aMajR * cosU * aXX + aMinR * sinU * aYX,
|
||||
aCY + aMajR * cosU * aXY + aMinR * sinU * aYY),
|
||||
gp_Vec2d(-aMajR * sinU * aXX + aMinR * cosU * aYX, -aMajR * sinU * aXY + aMinR * cosU * aYY)};
|
||||
}
|
||||
return aResult;
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
NCollection_Array1<Geom2dGridEval::CurveD2> Geom2dGridEval_Ellipse::EvaluateGridD2(
|
||||
const NCollection_Array1<double>& theParams) const
|
||||
{
|
||||
if (myGeom.IsNull() || theParams.IsEmpty())
|
||||
{
|
||||
return NCollection_Array1<Geom2dGridEval::CurveD2>();
|
||||
}
|
||||
|
||||
const int aNb = theParams.Size();
|
||||
NCollection_Array1<Geom2dGridEval::CurveD2> aResult(1, aNb);
|
||||
|
||||
const gp_Elips2d& anElips = myGeom->Elips2d();
|
||||
const gp_Pnt2d& aCenter = anElips.Location();
|
||||
const gp_Dir2d aXDir = anElips.XAxis().Direction();
|
||||
const gp_Dir2d aYDir = anElips.YAxis().Direction();
|
||||
const double aMajR = anElips.MajorRadius();
|
||||
const double aMinR = anElips.MinorRadius();
|
||||
|
||||
const double aCX = aCenter.X();
|
||||
const double aCY = aCenter.Y();
|
||||
const double aXX = aXDir.X();
|
||||
const double aXY = aXDir.Y();
|
||||
const double aYX = aYDir.X();
|
||||
const double aYY = aYDir.Y();
|
||||
|
||||
for (int i = theParams.Lower(); i <= theParams.Upper(); ++i)
|
||||
{
|
||||
const double u = theParams.Value(i);
|
||||
const double cosU = std::cos(u);
|
||||
const double sinU = std::sin(u);
|
||||
|
||||
// P = Center + MajorR * cos(u) * XDir + MinorR * sin(u) * YDir
|
||||
// D1 = -MajorR * sin(u) * XDir + MinorR * cos(u) * YDir
|
||||
// D2 = -MajorR * cos(u) * XDir - MinorR * sin(u) * YDir = -(P - Center)
|
||||
|
||||
aResult.ChangeValue(i - theParams.Lower() + 1) = {
|
||||
gp_Pnt2d(aCX + aMajR * cosU * aXX + aMinR * sinU * aYX,
|
||||
aCY + aMajR * cosU * aXY + aMinR * sinU * aYY),
|
||||
gp_Vec2d(-aMajR * sinU * aXX + aMinR * cosU * aYX, -aMajR * sinU * aXY + aMinR * cosU * aYY),
|
||||
gp_Vec2d(-aMajR * cosU * aXX - aMinR * sinU * aYX, -aMajR * cosU * aXY - aMinR * sinU * aYY)};
|
||||
}
|
||||
return aResult;
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
NCollection_Array1<Geom2dGridEval::CurveD3> Geom2dGridEval_Ellipse::EvaluateGridD3(
|
||||
const NCollection_Array1<double>& theParams) const
|
||||
{
|
||||
if (myGeom.IsNull() || theParams.IsEmpty())
|
||||
{
|
||||
return NCollection_Array1<Geom2dGridEval::CurveD3>();
|
||||
}
|
||||
|
||||
const int aNb = theParams.Size();
|
||||
NCollection_Array1<Geom2dGridEval::CurveD3> aResult(1, aNb);
|
||||
|
||||
const gp_Elips2d& anElips = myGeom->Elips2d();
|
||||
const gp_Pnt2d& aCenter = anElips.Location();
|
||||
const gp_Dir2d aXDir = anElips.XAxis().Direction();
|
||||
const gp_Dir2d aYDir = anElips.YAxis().Direction();
|
||||
const double aMajR = anElips.MajorRadius();
|
||||
const double aMinR = anElips.MinorRadius();
|
||||
|
||||
const double aCX = aCenter.X();
|
||||
const double aCY = aCenter.Y();
|
||||
const double aXX = aXDir.X();
|
||||
const double aXY = aXDir.Y();
|
||||
const double aYX = aYDir.X();
|
||||
const double aYY = aYDir.Y();
|
||||
|
||||
for (int i = theParams.Lower(); i <= theParams.Upper(); ++i)
|
||||
{
|
||||
const double u = theParams.Value(i);
|
||||
const double cosU = std::cos(u);
|
||||
const double sinU = std::sin(u);
|
||||
|
||||
// P = Center + MajorR * cos(u) * XDir + MinorR * sin(u) * YDir
|
||||
// D1 = -MajorR * sin(u) * XDir + MinorR * cos(u) * YDir
|
||||
// D2 = -MajorR * cos(u) * XDir - MinorR * sin(u) * YDir
|
||||
// D3 = MajorR * sin(u) * XDir - MinorR * cos(u) * YDir = -D1
|
||||
|
||||
aResult.ChangeValue(i - theParams.Lower() + 1) = {
|
||||
gp_Pnt2d(aCX + aMajR * cosU * aXX + aMinR * sinU * aYX,
|
||||
aCY + aMajR * cosU * aXY + aMinR * sinU * aYY),
|
||||
gp_Vec2d(-aMajR * sinU * aXX + aMinR * cosU * aYX, -aMajR * sinU * aXY + aMinR * cosU * aYY),
|
||||
gp_Vec2d(-aMajR * cosU * aXX - aMinR * sinU * aYX, -aMajR * cosU * aXY - aMinR * sinU * aYY),
|
||||
gp_Vec2d(aMajR * sinU * aXX - aMinR * cosU * aYX, aMajR * sinU * aXY - aMinR * cosU * aYY)};
|
||||
}
|
||||
return aResult;
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
NCollection_Array1<gp_Vec2d> Geom2dGridEval_Ellipse::EvaluateGridDN(
|
||||
const NCollection_Array1<double>& theParams,
|
||||
int theN) const
|
||||
{
|
||||
if (myGeom.IsNull() || theParams.IsEmpty() || theN < 1)
|
||||
{
|
||||
return NCollection_Array1<gp_Vec2d>();
|
||||
}
|
||||
|
||||
const int aNb = theParams.Size();
|
||||
NCollection_Array1<gp_Vec2d> aResult(1, aNb);
|
||||
|
||||
const gp_Elips2d& anElips = myGeom->Elips2d();
|
||||
const gp_Dir2d aXDir = anElips.XAxis().Direction();
|
||||
const gp_Dir2d aYDir = anElips.YAxis().Direction();
|
||||
const double aMajR = anElips.MajorRadius();
|
||||
const double aMinR = anElips.MinorRadius();
|
||||
|
||||
const double aXX = aXDir.X();
|
||||
const double aXY = aXDir.Y();
|
||||
const double aYX = aYDir.X();
|
||||
const double aYY = aYDir.Y();
|
||||
|
||||
// Ellipse derivatives are cyclic with period 4:
|
||||
// D1 = -MajR * sin(u) * X + MinR * cos(u) * Y -> coefficients: (-sin, cos)
|
||||
// D2 = -MajR * cos(u) * X - MinR * sin(u) * Y -> coefficients: (-cos, -sin)
|
||||
// D3 = MajR * sin(u) * X - MinR * cos(u) * Y -> coefficients: (sin, -cos)
|
||||
// D4 = MajR * cos(u) * X + MinR * sin(u) * Y -> coefficients: (cos, sin) = D0
|
||||
const int aPhase = (theN - 1) % 4;
|
||||
|
||||
for (int i = theParams.Lower(); i <= theParams.Upper(); ++i)
|
||||
{
|
||||
const double u = theParams.Value(i);
|
||||
const double cosU = std::cos(u);
|
||||
const double sinU = std::sin(u);
|
||||
|
||||
double aCoeffMajR, aCoeffMinR;
|
||||
switch (aPhase)
|
||||
{
|
||||
case 0: // D1, D5, D9, ...
|
||||
aCoeffMajR = -sinU;
|
||||
aCoeffMinR = cosU;
|
||||
break;
|
||||
case 1: // D2, D6, D10, ...
|
||||
aCoeffMajR = -cosU;
|
||||
aCoeffMinR = -sinU;
|
||||
break;
|
||||
case 2: // D3, D7, D11, ...
|
||||
aCoeffMajR = sinU;
|
||||
aCoeffMinR = -cosU;
|
||||
break;
|
||||
default: // D4, D8, D12, ... (case 3)
|
||||
aCoeffMajR = cosU;
|
||||
aCoeffMinR = sinU;
|
||||
break;
|
||||
}
|
||||
|
||||
aResult.SetValue(i - theParams.Lower() + 1,
|
||||
gp_Vec2d(aMajR * aCoeffMajR * aXX + aMinR * aCoeffMinR * aYX,
|
||||
aMajR * aCoeffMajR * aXY + aMinR * aCoeffMinR * aYY));
|
||||
}
|
||||
return aResult;
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
// 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 _Geom2dGridEval_Ellipse_HeaderFile
|
||||
#define _Geom2dGridEval_Ellipse_HeaderFile
|
||||
|
||||
#include <Geom2d_Ellipse.hxx>
|
||||
#include <Geom2dGridEval.hxx>
|
||||
#include <NCollection_Array1.hxx>
|
||||
#include <Standard.hxx>
|
||||
#include <Standard_DefineAlloc.hxx>
|
||||
|
||||
//! @brief Efficient batch evaluator for 2D ellipse grid points.
|
||||
//!
|
||||
//! Uses analytical formula:
|
||||
//! P(u) = Center + MajorRadius * cos(u) * XDir + MinorRadius * sin(u) * YDir
|
||||
//!
|
||||
//! Usage:
|
||||
//! @code
|
||||
//! Geom2dGridEval_Ellipse anEvaluator(myGeom2dEllipse);
|
||||
//! NCollection_Array1<gp_Pnt2d> aGrid = anEvaluator.EvaluateGrid(myParams);
|
||||
//! @endcode
|
||||
class Geom2dGridEval_Ellipse
|
||||
{
|
||||
public:
|
||||
DEFINE_STANDARD_ALLOC
|
||||
|
||||
//! Constructor with geometry.
|
||||
//! @param theEllipse the 2D ellipse geometry to evaluate
|
||||
Geom2dGridEval_Ellipse(const occ::handle<Geom2d_Ellipse>& theEllipse)
|
||||
: myGeom(theEllipse)
|
||||
{
|
||||
}
|
||||
|
||||
//! Non-copyable and non-movable.
|
||||
Geom2dGridEval_Ellipse(const Geom2dGridEval_Ellipse&) = delete;
|
||||
Geom2dGridEval_Ellipse& operator=(const Geom2dGridEval_Ellipse&) = delete;
|
||||
Geom2dGridEval_Ellipse(Geom2dGridEval_Ellipse&&) = delete;
|
||||
Geom2dGridEval_Ellipse& operator=(Geom2dGridEval_Ellipse&&) = delete;
|
||||
|
||||
//! Returns the geometry handle.
|
||||
const occ::handle<Geom2d_Ellipse>& Geometry() const { return myGeom; }
|
||||
|
||||
//! Evaluate all grid points.
|
||||
//! @param theParams array of parameter values
|
||||
//! @return array of evaluated points (1-based indexing),
|
||||
//! or empty array if geometry is null or no parameters
|
||||
Standard_EXPORT NCollection_Array1<gp_Pnt2d> EvaluateGrid(
|
||||
const NCollection_Array1<double>& theParams) const;
|
||||
|
||||
//! Evaluate all grid points with first derivative.
|
||||
//! @param theParams array of parameter values
|
||||
//! @return array of CurveD1 (1-based indexing),
|
||||
//! or empty array if geometry is null or no parameters
|
||||
Standard_EXPORT NCollection_Array1<Geom2dGridEval::CurveD1> EvaluateGridD1(
|
||||
const NCollection_Array1<double>& theParams) const;
|
||||
|
||||
//! Evaluate all grid points with first and second derivatives.
|
||||
//! @param theParams array of parameter values
|
||||
//! @return array of CurveD2 (1-based indexing),
|
||||
//! or empty array if geometry is null or no parameters
|
||||
Standard_EXPORT NCollection_Array1<Geom2dGridEval::CurveD2> EvaluateGridD2(
|
||||
const NCollection_Array1<double>& theParams) const;
|
||||
|
||||
//! Evaluate all grid points with first, second, and third derivatives.
|
||||
//! @param theParams array of parameter values
|
||||
//! @return array of CurveD3 (1-based indexing),
|
||||
//! or empty array if geometry is null or no parameters
|
||||
Standard_EXPORT NCollection_Array1<Geom2dGridEval::CurveD3> EvaluateGridD3(
|
||||
const NCollection_Array1<double>& theParams) const;
|
||||
|
||||
//! Evaluate Nth derivative at all grid points.
|
||||
//! Ellipse has cyclic derivatives with period 4:
|
||||
//! D1 = -MajR * sin(u) * X + MinR * cos(u) * Y
|
||||
//! D2 = -MajR * cos(u) * X - MinR * sin(u) * Y
|
||||
//! D3 = MajR * sin(u) * X - MinR * cos(u) * Y
|
||||
//! D4 = MajR * cos(u) * X + MinR * sin(u) * Y = D0, then repeats
|
||||
//! @param theParams array of parameter values
|
||||
//! @param theN derivative order (N >= 1)
|
||||
//! @return array of derivative vectors (1-based indexing),
|
||||
//! or empty array if geometry is null or no parameters
|
||||
Standard_EXPORT NCollection_Array1<gp_Vec2d> EvaluateGridDN(
|
||||
const NCollection_Array1<double>& theParams,
|
||||
int theN) const;
|
||||
|
||||
private:
|
||||
occ::handle<Geom2d_Ellipse> myGeom;
|
||||
};
|
||||
|
||||
#endif // _Geom2dGridEval_Ellipse_HeaderFile
|
||||
@@ -0,0 +1,250 @@
|
||||
// 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 <Geom2dGridEval_Hyperbola.hxx>
|
||||
|
||||
#include <gp_Hypr2d.hxx>
|
||||
|
||||
#include <cmath>
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
NCollection_Array1<gp_Pnt2d> Geom2dGridEval_Hyperbola::EvaluateGrid(
|
||||
const NCollection_Array1<double>& theParams) const
|
||||
{
|
||||
if (myGeom.IsNull() || theParams.IsEmpty())
|
||||
{
|
||||
return NCollection_Array1<gp_Pnt2d>();
|
||||
}
|
||||
|
||||
const int aNb = theParams.Size();
|
||||
NCollection_Array1<gp_Pnt2d> aResult(1, aNb);
|
||||
|
||||
const gp_Hypr2d& aHypr = myGeom->Hypr2d();
|
||||
const gp_Pnt2d& aCenter = aHypr.Location();
|
||||
const gp_Dir2d aXDir = aHypr.XAxis().Direction();
|
||||
const gp_Dir2d aYDir = aHypr.YAxis().Direction();
|
||||
const double aMajR = aHypr.MajorRadius();
|
||||
const double aMinR = aHypr.MinorRadius();
|
||||
|
||||
const double aCX = aCenter.X();
|
||||
const double aCY = aCenter.Y();
|
||||
const double aXX = aXDir.X();
|
||||
const double aXY = aXDir.Y();
|
||||
const double aYX = aYDir.X();
|
||||
const double aYY = aYDir.Y();
|
||||
|
||||
for (int i = theParams.Lower(); i <= theParams.Upper(); ++i)
|
||||
{
|
||||
const double u = theParams.Value(i);
|
||||
const double coshU = std::cosh(u);
|
||||
const double sinhU = std::sinh(u);
|
||||
|
||||
aResult.SetValue(i - theParams.Lower() + 1,
|
||||
gp_Pnt2d(aCX + aMajR * coshU * aXX + aMinR * sinhU * aYX,
|
||||
aCY + aMajR * coshU * aXY + aMinR * sinhU * aYY));
|
||||
}
|
||||
return aResult;
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
NCollection_Array1<Geom2dGridEval::CurveD1> Geom2dGridEval_Hyperbola::EvaluateGridD1(
|
||||
const NCollection_Array1<double>& theParams) const
|
||||
{
|
||||
if (myGeom.IsNull() || theParams.IsEmpty())
|
||||
{
|
||||
return NCollection_Array1<Geom2dGridEval::CurveD1>();
|
||||
}
|
||||
|
||||
const int aNb = theParams.Size();
|
||||
NCollection_Array1<Geom2dGridEval::CurveD1> aResult(1, aNb);
|
||||
|
||||
const gp_Hypr2d& aHypr = myGeom->Hypr2d();
|
||||
const gp_Pnt2d& aCenter = aHypr.Location();
|
||||
const gp_Dir2d aXDir = aHypr.XAxis().Direction();
|
||||
const gp_Dir2d aYDir = aHypr.YAxis().Direction();
|
||||
const double aMajR = aHypr.MajorRadius();
|
||||
const double aMinR = aHypr.MinorRadius();
|
||||
|
||||
const double aCX = aCenter.X();
|
||||
const double aCY = aCenter.Y();
|
||||
const double aXX = aXDir.X();
|
||||
const double aXY = aXDir.Y();
|
||||
const double aYX = aYDir.X();
|
||||
const double aYY = aYDir.Y();
|
||||
|
||||
for (int i = theParams.Lower(); i <= theParams.Upper(); ++i)
|
||||
{
|
||||
const double u = theParams.Value(i);
|
||||
const double coshU = std::cosh(u);
|
||||
const double sinhU = std::sinh(u);
|
||||
|
||||
// P = Center + MajorR * cosh(u) * XDir + MinorR * sinh(u) * YDir
|
||||
// D1 = MajorR * sinh(u) * XDir + MinorR * cosh(u) * YDir
|
||||
|
||||
aResult.ChangeValue(i - theParams.Lower()
|
||||
+ 1) = {gp_Pnt2d(aCX + aMajR * coshU * aXX + aMinR * sinhU * aYX,
|
||||
aCY + aMajR * coshU * aXY + aMinR * sinhU * aYY),
|
||||
gp_Vec2d(aMajR * sinhU * aXX + aMinR * coshU * aYX,
|
||||
aMajR * sinhU * aXY + aMinR * coshU * aYY)};
|
||||
}
|
||||
return aResult;
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
NCollection_Array1<Geom2dGridEval::CurveD2> Geom2dGridEval_Hyperbola::EvaluateGridD2(
|
||||
const NCollection_Array1<double>& theParams) const
|
||||
{
|
||||
if (myGeom.IsNull() || theParams.IsEmpty())
|
||||
{
|
||||
return NCollection_Array1<Geom2dGridEval::CurveD2>();
|
||||
}
|
||||
|
||||
const int aNb = theParams.Size();
|
||||
NCollection_Array1<Geom2dGridEval::CurveD2> aResult(1, aNb);
|
||||
|
||||
const gp_Hypr2d& aHypr = myGeom->Hypr2d();
|
||||
const gp_Pnt2d& aCenter = aHypr.Location();
|
||||
const gp_Dir2d aXDir = aHypr.XAxis().Direction();
|
||||
const gp_Dir2d aYDir = aHypr.YAxis().Direction();
|
||||
const double aMajR = aHypr.MajorRadius();
|
||||
const double aMinR = aHypr.MinorRadius();
|
||||
|
||||
const double aCX = aCenter.X();
|
||||
const double aCY = aCenter.Y();
|
||||
const double aXX = aXDir.X();
|
||||
const double aXY = aXDir.Y();
|
||||
const double aYX = aYDir.X();
|
||||
const double aYY = aYDir.Y();
|
||||
|
||||
for (int i = theParams.Lower(); i <= theParams.Upper(); ++i)
|
||||
{
|
||||
const double u = theParams.Value(i);
|
||||
const double coshU = std::cosh(u);
|
||||
const double sinhU = std::sinh(u);
|
||||
|
||||
// D2 = MajorR * cosh(u) * XDir + MinorR * sinh(u) * YDir = (P - Center)
|
||||
|
||||
aResult.ChangeValue(i - theParams.Lower()
|
||||
+ 1) = {gp_Pnt2d(aCX + aMajR * coshU * aXX + aMinR * sinhU * aYX,
|
||||
aCY + aMajR * coshU * aXY + aMinR * sinhU * aYY),
|
||||
gp_Vec2d(aMajR * sinhU * aXX + aMinR * coshU * aYX,
|
||||
aMajR * sinhU * aXY + aMinR * coshU * aYY),
|
||||
gp_Vec2d(aMajR * coshU * aXX + aMinR * sinhU * aYX,
|
||||
aMajR * coshU * aXY + aMinR * sinhU * aYY)};
|
||||
}
|
||||
return aResult;
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
NCollection_Array1<Geom2dGridEval::CurveD3> Geom2dGridEval_Hyperbola::EvaluateGridD3(
|
||||
const NCollection_Array1<double>& theParams) const
|
||||
{
|
||||
if (myGeom.IsNull() || theParams.IsEmpty())
|
||||
{
|
||||
return NCollection_Array1<Geom2dGridEval::CurveD3>();
|
||||
}
|
||||
|
||||
const int aNb = theParams.Size();
|
||||
NCollection_Array1<Geom2dGridEval::CurveD3> aResult(1, aNb);
|
||||
|
||||
const gp_Hypr2d& aHypr = myGeom->Hypr2d();
|
||||
const gp_Pnt2d& aCenter = aHypr.Location();
|
||||
const gp_Dir2d aXDir = aHypr.XAxis().Direction();
|
||||
const gp_Dir2d aYDir = aHypr.YAxis().Direction();
|
||||
const double aMajR = aHypr.MajorRadius();
|
||||
const double aMinR = aHypr.MinorRadius();
|
||||
|
||||
const double aCX = aCenter.X();
|
||||
const double aCY = aCenter.Y();
|
||||
const double aXX = aXDir.X();
|
||||
const double aXY = aXDir.Y();
|
||||
const double aYX = aYDir.X();
|
||||
const double aYY = aYDir.Y();
|
||||
|
||||
for (int i = theParams.Lower(); i <= theParams.Upper(); ++i)
|
||||
{
|
||||
const double u = theParams.Value(i);
|
||||
const double coshU = std::cosh(u);
|
||||
const double sinhU = std::sinh(u);
|
||||
|
||||
// D3 = MajorR * sinh(u) * XDir + MinorR * cosh(u) * YDir = D1
|
||||
|
||||
aResult.ChangeValue(i - theParams.Lower()
|
||||
+ 1) = {gp_Pnt2d(aCX + aMajR * coshU * aXX + aMinR * sinhU * aYX,
|
||||
aCY + aMajR * coshU * aXY + aMinR * sinhU * aYY),
|
||||
gp_Vec2d(aMajR * sinhU * aXX + aMinR * coshU * aYX,
|
||||
aMajR * sinhU * aXY + aMinR * coshU * aYY),
|
||||
gp_Vec2d(aMajR * coshU * aXX + aMinR * sinhU * aYX,
|
||||
aMajR * coshU * aXY + aMinR * sinhU * aYY),
|
||||
gp_Vec2d(aMajR * sinhU * aXX + aMinR * coshU * aYX,
|
||||
aMajR * sinhU * aXY + aMinR * coshU * aYY)};
|
||||
}
|
||||
return aResult;
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
NCollection_Array1<gp_Vec2d> Geom2dGridEval_Hyperbola::EvaluateGridDN(
|
||||
const NCollection_Array1<double>& theParams,
|
||||
int theN) const
|
||||
{
|
||||
if (myGeom.IsNull() || theParams.IsEmpty() || theN < 1)
|
||||
{
|
||||
return NCollection_Array1<gp_Vec2d>();
|
||||
}
|
||||
|
||||
const int aNb = theParams.Size();
|
||||
NCollection_Array1<gp_Vec2d> aResult(1, aNb);
|
||||
|
||||
const gp_Hypr2d& aHypr = myGeom->Hypr2d();
|
||||
const gp_Dir2d aXDir = aHypr.XAxis().Direction();
|
||||
const gp_Dir2d aYDir = aHypr.YAxis().Direction();
|
||||
const double aMajR = aHypr.MajorRadius();
|
||||
const double aMinR = aHypr.MinorRadius();
|
||||
|
||||
const double aXX = aXDir.X();
|
||||
const double aXY = aXDir.Y();
|
||||
const double aYX = aYDir.X();
|
||||
const double aYY = aYDir.Y();
|
||||
|
||||
// Hyperbola derivatives are cyclic with period 2:
|
||||
// D0 = MajR * cosh(u) * X + MinR * sinh(u) * Y -> coefficients: (cosh, sinh)
|
||||
// D1 = MajR * sinh(u) * X + MinR * cosh(u) * Y -> coefficients: (sinh, cosh)
|
||||
// D2 = D0, D3 = D1, etc.
|
||||
const bool isOdd = (theN % 2) == 1;
|
||||
|
||||
for (int i = theParams.Lower(); i <= theParams.Upper(); ++i)
|
||||
{
|
||||
const double u = theParams.Value(i);
|
||||
const double coshU = std::cosh(u);
|
||||
const double sinhU = std::sinh(u);
|
||||
|
||||
if (isOdd)
|
||||
{
|
||||
aResult.SetValue(i - theParams.Lower() + 1,
|
||||
gp_Vec2d(aMajR * sinhU * aXX + aMinR * coshU * aYX,
|
||||
aMajR * sinhU * aXY + aMinR * coshU * aYY));
|
||||
}
|
||||
else
|
||||
{
|
||||
aResult.SetValue(i - theParams.Lower() + 1,
|
||||
gp_Vec2d(aMajR * coshU * aXX + aMinR * sinhU * aYX,
|
||||
aMajR * coshU * aXY + aMinR * sinhU * aYY));
|
||||
}
|
||||
}
|
||||
return aResult;
|
||||
}
|
||||
@@ -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 _Geom2dGridEval_Hyperbola_HeaderFile
|
||||
#define _Geom2dGridEval_Hyperbola_HeaderFile
|
||||
|
||||
#include <Geom2d_Hyperbola.hxx>
|
||||
#include <Geom2dGridEval.hxx>
|
||||
#include <NCollection_Array1.hxx>
|
||||
#include <Standard.hxx>
|
||||
#include <Standard_DefineAlloc.hxx>
|
||||
|
||||
//! @brief Efficient batch evaluator for 2D hyperbola grid points.
|
||||
//!
|
||||
//! Uses analytical formula:
|
||||
//! P(u) = Center + MajorRadius * cosh(u) * XDir + MinorRadius * sinh(u) * YDir
|
||||
//!
|
||||
//! Usage:
|
||||
//! @code
|
||||
//! Geom2dGridEval_Hyperbola anEvaluator(myGeom2dHyperbola);
|
||||
//! NCollection_Array1<gp_Pnt2d> aGrid = anEvaluator.EvaluateGrid(myParams);
|
||||
//! @endcode
|
||||
class Geom2dGridEval_Hyperbola
|
||||
{
|
||||
public:
|
||||
DEFINE_STANDARD_ALLOC
|
||||
|
||||
//! Constructor with geometry.
|
||||
//! @param theHyperbola the 2D hyperbola geometry to evaluate
|
||||
Geom2dGridEval_Hyperbola(const occ::handle<Geom2d_Hyperbola>& theHyperbola)
|
||||
: myGeom(theHyperbola)
|
||||
{
|
||||
}
|
||||
|
||||
//! Non-copyable and non-movable.
|
||||
Geom2dGridEval_Hyperbola(const Geom2dGridEval_Hyperbola&) = delete;
|
||||
Geom2dGridEval_Hyperbola& operator=(const Geom2dGridEval_Hyperbola&) = delete;
|
||||
Geom2dGridEval_Hyperbola(Geom2dGridEval_Hyperbola&&) = delete;
|
||||
Geom2dGridEval_Hyperbola& operator=(Geom2dGridEval_Hyperbola&&) = delete;
|
||||
|
||||
//! Returns the geometry handle.
|
||||
const occ::handle<Geom2d_Hyperbola>& Geometry() const { return myGeom; }
|
||||
|
||||
//! Evaluate all grid points.
|
||||
//! @param theParams array of parameter values
|
||||
//! @return array of evaluated points (1-based indexing),
|
||||
//! or empty array if geometry is null or no parameters
|
||||
Standard_EXPORT NCollection_Array1<gp_Pnt2d> EvaluateGrid(
|
||||
const NCollection_Array1<double>& theParams) const;
|
||||
|
||||
//! Evaluate all grid points with first derivative.
|
||||
//! @param theParams array of parameter values
|
||||
//! @return array of CurveD1 (1-based indexing)
|
||||
Standard_EXPORT NCollection_Array1<Geom2dGridEval::CurveD1> EvaluateGridD1(
|
||||
const NCollection_Array1<double>& theParams) const;
|
||||
|
||||
//! Evaluate all grid points with first and second derivatives.
|
||||
//! @param theParams array of parameter values
|
||||
//! @return array of CurveD2 (1-based indexing)
|
||||
Standard_EXPORT NCollection_Array1<Geom2dGridEval::CurveD2> EvaluateGridD2(
|
||||
const NCollection_Array1<double>& theParams) const;
|
||||
|
||||
//! Evaluate all grid points with first, second, and third derivatives.
|
||||
//! @param theParams array of parameter values
|
||||
//! @return array of CurveD3 (1-based indexing)
|
||||
Standard_EXPORT NCollection_Array1<Geom2dGridEval::CurveD3> EvaluateGridD3(
|
||||
const NCollection_Array1<double>& theParams) const;
|
||||
|
||||
//! Evaluate Nth derivative at all grid points.
|
||||
//! Hyperbola has cyclic derivatives with period 2:
|
||||
//! D1 = MajR * sinh(u) * X + MinR * cosh(u) * Y
|
||||
//! D2 = MajR * cosh(u) * X + MinR * sinh(u) * Y = D0
|
||||
//! D3 = D1, D4 = D0, etc.
|
||||
//! @param theParams array of parameter values
|
||||
//! @param theN derivative order (N >= 1)
|
||||
//! @return array of derivative vectors (1-based indexing)
|
||||
Standard_EXPORT NCollection_Array1<gp_Vec2d> EvaluateGridDN(
|
||||
const NCollection_Array1<double>& theParams,
|
||||
int theN) const;
|
||||
|
||||
private:
|
||||
occ::handle<Geom2d_Hyperbola> myGeom;
|
||||
};
|
||||
|
||||
#endif // _Geom2dGridEval_Hyperbola_HeaderFile
|
||||
@@ -0,0 +1,230 @@
|
||||
// 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 _Geom2dGridEval_Line_HeaderFile
|
||||
#define _Geom2dGridEval_Line_HeaderFile
|
||||
|
||||
#include <Geom2d_Line.hxx>
|
||||
#include <Geom2dGridEval.hxx>
|
||||
#include <NCollection_Array1.hxx>
|
||||
#include <Standard_DefineAlloc.hxx>
|
||||
|
||||
//! @brief Efficient batch evaluator for 2D line grid points.
|
||||
//!
|
||||
//! Uses direct analytical formula: P(t) = Location + t * Direction
|
||||
//!
|
||||
//! Usage:
|
||||
//! @code
|
||||
//! Geom2dGridEval_Line anEvaluator(myGeom2dLine);
|
||||
//! NCollection_Array1<gp_Pnt2d> aGrid = anEvaluator.EvaluateGrid(myParams);
|
||||
//! @endcode
|
||||
class Geom2dGridEval_Line
|
||||
{
|
||||
public:
|
||||
DEFINE_STANDARD_ALLOC
|
||||
|
||||
//! Constructor with geometry.
|
||||
//! @param theLine the 2D line geometry to evaluate
|
||||
Geom2dGridEval_Line(const occ::handle<Geom2d_Line>& theLine)
|
||||
: myGeom(theLine)
|
||||
{
|
||||
}
|
||||
|
||||
//! Non-copyable and non-movable.
|
||||
Geom2dGridEval_Line(const Geom2dGridEval_Line&) = delete;
|
||||
Geom2dGridEval_Line& operator=(const Geom2dGridEval_Line&) = delete;
|
||||
Geom2dGridEval_Line(Geom2dGridEval_Line&&) = delete;
|
||||
Geom2dGridEval_Line& operator=(Geom2dGridEval_Line&&) = delete;
|
||||
|
||||
//! Returns the geometry handle.
|
||||
const occ::handle<Geom2d_Line>& Geometry() const { return myGeom; }
|
||||
|
||||
//! Evaluate all grid points.
|
||||
//! @param theParams array of parameter values
|
||||
//! @return array of evaluated points (1-based indexing),
|
||||
//! or empty array if geometry is null or no parameters
|
||||
NCollection_Array1<gp_Pnt2d> EvaluateGrid(const NCollection_Array1<double>& theParams) const
|
||||
{
|
||||
if (myGeom.IsNull() || theParams.IsEmpty())
|
||||
{
|
||||
return NCollection_Array1<gp_Pnt2d>();
|
||||
}
|
||||
|
||||
NCollection_Array1<gp_Pnt2d> aResult(1, theParams.Size());
|
||||
|
||||
const gp_Lin2d& aLin = myGeom->Lin2d();
|
||||
const gp_Pnt2d& aLoc = aLin.Location();
|
||||
const gp_Dir2d& aDir = aLin.Direction();
|
||||
|
||||
const double aLocX = aLoc.X();
|
||||
const double aLocY = aLoc.Y();
|
||||
const double aDirX = aDir.X();
|
||||
const double aDirY = aDir.Y();
|
||||
|
||||
for (int i = theParams.Lower(); i <= theParams.Upper(); ++i)
|
||||
{
|
||||
const double t = theParams.Value(i);
|
||||
aResult.SetValue(i - theParams.Lower() + 1, gp_Pnt2d(aLocX + t * aDirX, aLocY + t * aDirY));
|
||||
}
|
||||
return aResult;
|
||||
}
|
||||
|
||||
//! Evaluate all grid points with first derivative.
|
||||
//! For a line, D1 is constant (the direction vector).
|
||||
//! @param theParams array of parameter values
|
||||
//! @return array of CurveD1 (1-based indexing),
|
||||
//! or empty array if geometry is null or no parameters
|
||||
NCollection_Array1<Geom2dGridEval::CurveD1> EvaluateGridD1(
|
||||
const NCollection_Array1<double>& theParams) const
|
||||
{
|
||||
if (myGeom.IsNull() || theParams.IsEmpty())
|
||||
{
|
||||
return NCollection_Array1<Geom2dGridEval::CurveD1>();
|
||||
}
|
||||
|
||||
NCollection_Array1<Geom2dGridEval::CurveD1> aResult(1, theParams.Size());
|
||||
|
||||
const gp_Lin2d& aLin = myGeom->Lin2d();
|
||||
const gp_Pnt2d& aLoc = aLin.Location();
|
||||
const gp_Dir2d& aDir = aLin.Direction();
|
||||
|
||||
const double aLocX = aLoc.X();
|
||||
const double aLocY = aLoc.Y();
|
||||
const double aDirX = aDir.X();
|
||||
const double aDirY = aDir.Y();
|
||||
|
||||
const gp_Vec2d aD1(aDirX, aDirY);
|
||||
|
||||
for (int i = theParams.Lower(); i <= theParams.Upper(); ++i)
|
||||
{
|
||||
const double t = theParams.Value(i);
|
||||
aResult.ChangeValue(i - theParams.Lower()
|
||||
+ 1) = {gp_Pnt2d(aLocX + t * aDirX, aLocY + t * aDirY), aD1};
|
||||
}
|
||||
return aResult;
|
||||
}
|
||||
|
||||
//! Evaluate all grid points with first and second derivatives.
|
||||
//! For a line, D1 is constant and D2 is zero.
|
||||
//! @param theParams array of parameter values
|
||||
//! @return array of CurveD2 (1-based indexing),
|
||||
//! or empty array if geometry is null or no parameters
|
||||
NCollection_Array1<Geom2dGridEval::CurveD2> EvaluateGridD2(
|
||||
const NCollection_Array1<double>& theParams) const
|
||||
{
|
||||
if (myGeom.IsNull() || theParams.IsEmpty())
|
||||
{
|
||||
return NCollection_Array1<Geom2dGridEval::CurveD2>();
|
||||
}
|
||||
|
||||
NCollection_Array1<Geom2dGridEval::CurveD2> aResult(1, theParams.Size());
|
||||
|
||||
const gp_Lin2d& aLin = myGeom->Lin2d();
|
||||
const gp_Pnt2d& aLoc = aLin.Location();
|
||||
const gp_Dir2d& aDir = aLin.Direction();
|
||||
|
||||
const double aLocX = aLoc.X();
|
||||
const double aLocY = aLoc.Y();
|
||||
const double aDirX = aDir.X();
|
||||
const double aDirY = aDir.Y();
|
||||
|
||||
const gp_Vec2d aD1(aDirX, aDirY);
|
||||
const gp_Vec2d aD2(0, 0);
|
||||
|
||||
for (int i = theParams.Lower(); i <= theParams.Upper(); ++i)
|
||||
{
|
||||
const double t = theParams.Value(i);
|
||||
aResult.ChangeValue(i - theParams.Lower()
|
||||
+ 1) = {gp_Pnt2d(aLocX + t * aDirX, aLocY + t * aDirY), aD1, aD2};
|
||||
}
|
||||
return aResult;
|
||||
}
|
||||
|
||||
//! Evaluate all grid points with first, second, and third derivatives.
|
||||
//! For a line, D1 is constant, D2 and D3 are zero.
|
||||
//! @param theParams array of parameter values
|
||||
//! @return array of CurveD3 (1-based indexing),
|
||||
//! or empty array if geometry is null or no parameters
|
||||
NCollection_Array1<Geom2dGridEval::CurveD3> EvaluateGridD3(
|
||||
const NCollection_Array1<double>& theParams) const
|
||||
{
|
||||
if (myGeom.IsNull() || theParams.IsEmpty())
|
||||
{
|
||||
return NCollection_Array1<Geom2dGridEval::CurveD3>();
|
||||
}
|
||||
|
||||
NCollection_Array1<Geom2dGridEval::CurveD3> aResult(1, theParams.Size());
|
||||
|
||||
const gp_Lin2d& aLin = myGeom->Lin2d();
|
||||
const gp_Pnt2d& aLoc = aLin.Location();
|
||||
const gp_Dir2d& aDir = aLin.Direction();
|
||||
|
||||
const double aLocX = aLoc.X();
|
||||
const double aLocY = aLoc.Y();
|
||||
const double aDirX = aDir.X();
|
||||
const double aDirY = aDir.Y();
|
||||
|
||||
const gp_Vec2d aD1(aDirX, aDirY);
|
||||
const gp_Vec2d aZero(0, 0);
|
||||
|
||||
for (int i = theParams.Lower(); i <= theParams.Upper(); ++i)
|
||||
{
|
||||
const double t = theParams.Value(i);
|
||||
aResult.ChangeValue(
|
||||
i - theParams.Lower()
|
||||
+ 1) = {gp_Pnt2d(aLocX + t * aDirX, aLocY + t * aDirY), aD1, aZero, aZero};
|
||||
}
|
||||
return aResult;
|
||||
}
|
||||
|
||||
//! Evaluate Nth derivative at all grid points.
|
||||
//! For a line: D1 = Direction, DN = 0 for N > 1.
|
||||
//! @param theParams array of parameter values
|
||||
//! @param theN derivative order (N >= 1)
|
||||
//! @return array of derivative vectors (1-based indexing),
|
||||
//! or empty array if geometry is null or no parameters
|
||||
NCollection_Array1<gp_Vec2d> EvaluateGridDN(const NCollection_Array1<double>& theParams,
|
||||
int theN) const
|
||||
{
|
||||
if (myGeom.IsNull() || theParams.IsEmpty() || theN < 1)
|
||||
{
|
||||
return NCollection_Array1<gp_Vec2d>();
|
||||
}
|
||||
|
||||
NCollection_Array1<gp_Vec2d> aResult(1, theParams.Size());
|
||||
|
||||
if (theN == 1)
|
||||
{
|
||||
const gp_Dir2d aDir = myGeom->Lin2d().Direction();
|
||||
const gp_Vec2d aD1(aDir.X(), aDir.Y());
|
||||
for (int i = 1; i <= theParams.Size(); ++i)
|
||||
{
|
||||
aResult.SetValue(i, aD1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const gp_Vec2d aZero(0, 0);
|
||||
for (int i = 1; i <= theParams.Size(); ++i)
|
||||
{
|
||||
aResult.SetValue(i, aZero);
|
||||
}
|
||||
}
|
||||
return aResult;
|
||||
}
|
||||
|
||||
private:
|
||||
occ::handle<Geom2d_Line> myGeom;
|
||||
};
|
||||
|
||||
#endif // _Geom2dGridEval_Line_HeaderFile
|
||||
@@ -0,0 +1,282 @@
|
||||
// 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 <Geom2dGridEval_OffsetCurve.hxx>
|
||||
|
||||
#include <Geom2d_OffsetCurveUtils.pxx>
|
||||
#include <Geom2dGridEval_Curve.hxx>
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
NCollection_Array1<gp_Pnt2d> Geom2dGridEval_OffsetCurve::EvaluateGrid(
|
||||
const NCollection_Array1<double>& theParams) const
|
||||
{
|
||||
if (myBasis.IsNull() || theParams.IsEmpty())
|
||||
{
|
||||
return NCollection_Array1<gp_Pnt2d>();
|
||||
}
|
||||
|
||||
// Offset D0 requires basis D1 to compute offset normal direction
|
||||
Geom2dGridEval_Curve aBasisEval;
|
||||
aBasisEval.Initialize(myBasis);
|
||||
|
||||
NCollection_Array1<Geom2dGridEval::CurveD1> aBasisD1 = aBasisEval.EvaluateGridD1(theParams);
|
||||
if (aBasisD1.IsEmpty())
|
||||
{
|
||||
return NCollection_Array1<gp_Pnt2d>();
|
||||
}
|
||||
|
||||
const int aNbParams = theParams.Size();
|
||||
NCollection_Array1<gp_Pnt2d> aResult(1, aNbParams);
|
||||
|
||||
for (int i = 1; i <= aNbParams; ++i)
|
||||
{
|
||||
const Geom2dGridEval::CurveD1& aBasis = aBasisD1.Value(i);
|
||||
gp_Pnt2d aP = aBasis.Point;
|
||||
if (!Geom2d_OffsetCurveUtils::CalculateD0(aP, aBasis.D1, myOffset))
|
||||
{
|
||||
return NCollection_Array1<gp_Pnt2d>();
|
||||
}
|
||||
aResult.SetValue(i, aP);
|
||||
}
|
||||
|
||||
return aResult;
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
NCollection_Array1<Geom2dGridEval::CurveD1> Geom2dGridEval_OffsetCurve::EvaluateGridD1(
|
||||
const NCollection_Array1<double>& theParams) const
|
||||
{
|
||||
if (myBasis.IsNull() || theParams.IsEmpty())
|
||||
{
|
||||
return NCollection_Array1<Geom2dGridEval::CurveD1>();
|
||||
}
|
||||
|
||||
// Offset D1 requires basis D2
|
||||
Geom2dGridEval_Curve aBasisEval;
|
||||
aBasisEval.Initialize(myBasis);
|
||||
|
||||
NCollection_Array1<Geom2dGridEval::CurveD2> aBasisD2 = aBasisEval.EvaluateGridD2(theParams);
|
||||
if (aBasisD2.IsEmpty())
|
||||
{
|
||||
return NCollection_Array1<Geom2dGridEval::CurveD1>();
|
||||
}
|
||||
|
||||
const int aNbParams = theParams.Size();
|
||||
NCollection_Array1<Geom2dGridEval::CurveD1> aResult(1, aNbParams);
|
||||
|
||||
for (int i = 1; i <= aNbParams; ++i)
|
||||
{
|
||||
const Geom2dGridEval::CurveD2& aBasis = aBasisD2.Value(i);
|
||||
gp_Pnt2d aP = aBasis.Point;
|
||||
gp_Vec2d aD1 = aBasis.D1;
|
||||
if (!Geom2d_OffsetCurveUtils::CalculateD1(aP, aD1, aBasis.D2, myOffset))
|
||||
{
|
||||
return NCollection_Array1<Geom2dGridEval::CurveD1>();
|
||||
}
|
||||
aResult.ChangeValue(i) = {aP, aD1};
|
||||
}
|
||||
|
||||
return aResult;
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
NCollection_Array1<Geom2dGridEval::CurveD2> Geom2dGridEval_OffsetCurve::EvaluateGridD2(
|
||||
const NCollection_Array1<double>& theParams) const
|
||||
{
|
||||
if (myBasis.IsNull() || theParams.IsEmpty())
|
||||
{
|
||||
return NCollection_Array1<Geom2dGridEval::CurveD2>();
|
||||
}
|
||||
|
||||
// Offset D2 requires basis D3
|
||||
Geom2dGridEval_Curve aBasisEval;
|
||||
aBasisEval.Initialize(myBasis);
|
||||
|
||||
NCollection_Array1<Geom2dGridEval::CurveD3> aBasisD3 = aBasisEval.EvaluateGridD3(theParams);
|
||||
if (aBasisD3.IsEmpty())
|
||||
{
|
||||
return NCollection_Array1<Geom2dGridEval::CurveD2>();
|
||||
}
|
||||
|
||||
const int aNbParams = theParams.Size();
|
||||
NCollection_Array1<Geom2dGridEval::CurveD2> aResult(1, aNbParams);
|
||||
|
||||
for (int i = 1; i <= aNbParams; ++i)
|
||||
{
|
||||
const Geom2dGridEval::CurveD3& aBasis = aBasisD3.Value(i);
|
||||
gp_Pnt2d aP = aBasis.Point;
|
||||
gp_Vec2d aD1 = aBasis.D1;
|
||||
gp_Vec2d aD2 = aBasis.D2;
|
||||
gp_Vec2d aD3 = aBasis.D3;
|
||||
|
||||
// Check for direction change at singular points
|
||||
bool isDirectionChange = false;
|
||||
if (aD1.SquareMagnitude() <= gp::Resolution())
|
||||
{
|
||||
gp_Vec2d aDummyD4;
|
||||
if (!Geom2d_OffsetCurveUtils::AdjustDerivative(*myBasis,
|
||||
3,
|
||||
theParams.Value(theParams.Lower() + i - 1),
|
||||
aD1,
|
||||
aD2,
|
||||
aD3,
|
||||
aDummyD4,
|
||||
isDirectionChange))
|
||||
{
|
||||
return NCollection_Array1<Geom2dGridEval::CurveD2>();
|
||||
}
|
||||
}
|
||||
|
||||
if (!Geom2d_OffsetCurveUtils::CalculateD2(aP, aD1, aD2, aD3, isDirectionChange, myOffset))
|
||||
{
|
||||
return NCollection_Array1<Geom2dGridEval::CurveD2>();
|
||||
}
|
||||
aResult.ChangeValue(i) = {aP, aD1, aD2};
|
||||
}
|
||||
|
||||
return aResult;
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
NCollection_Array1<Geom2dGridEval::CurveD3> Geom2dGridEval_OffsetCurve::EvaluateGridD3(
|
||||
const NCollection_Array1<double>& theParams) const
|
||||
{
|
||||
if (myBasis.IsNull() || theParams.IsEmpty())
|
||||
{
|
||||
return NCollection_Array1<Geom2dGridEval::CurveD3>();
|
||||
}
|
||||
|
||||
// Offset D3 requires basis D3 + D4
|
||||
Geom2dGridEval_Curve aBasisEval;
|
||||
aBasisEval.Initialize(myBasis);
|
||||
|
||||
NCollection_Array1<Geom2dGridEval::CurveD3> aBasisD3 = aBasisEval.EvaluateGridD3(theParams);
|
||||
if (aBasisD3.IsEmpty())
|
||||
{
|
||||
return NCollection_Array1<Geom2dGridEval::CurveD3>();
|
||||
}
|
||||
|
||||
const int aNbParams = theParams.Size();
|
||||
NCollection_Array1<Geom2dGridEval::CurveD3> aResult(1, aNbParams);
|
||||
|
||||
for (int i = 1; i <= aNbParams; ++i)
|
||||
{
|
||||
const double aParam = theParams.Value(theParams.Lower() + i - 1);
|
||||
|
||||
const Geom2dGridEval::CurveD3& aBasis = aBasisD3.Value(i);
|
||||
gp_Pnt2d aP = aBasis.Point;
|
||||
gp_Vec2d aD1 = aBasis.D1;
|
||||
gp_Vec2d aD2 = aBasis.D2;
|
||||
gp_Vec2d aD3 = aBasis.D3;
|
||||
std::optional<gp_Vec2d> aD4Opt = myBasis->EvalDN(aParam, 4);
|
||||
if (!aD4Opt)
|
||||
{
|
||||
return NCollection_Array1<Geom2dGridEval::CurveD3>();
|
||||
}
|
||||
gp_Vec2d aD4 = *aD4Opt;
|
||||
|
||||
// Check for direction change at singular points
|
||||
bool isDirectionChange = false;
|
||||
if (aD1.SquareMagnitude() <= gp::Resolution())
|
||||
{
|
||||
if (!Geom2d_OffsetCurveUtils::AdjustDerivative(*myBasis,
|
||||
4,
|
||||
aParam,
|
||||
aD1,
|
||||
aD2,
|
||||
aD3,
|
||||
aD4,
|
||||
isDirectionChange))
|
||||
{
|
||||
return NCollection_Array1<Geom2dGridEval::CurveD3>();
|
||||
}
|
||||
}
|
||||
|
||||
if (!Geom2d_OffsetCurveUtils::CalculateD3(aP, aD1, aD2, aD3, aD4, isDirectionChange, myOffset))
|
||||
{
|
||||
return NCollection_Array1<Geom2dGridEval::CurveD3>();
|
||||
}
|
||||
aResult.ChangeValue(i) = {aP, aD1, aD2, aD3};
|
||||
}
|
||||
|
||||
return aResult;
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
NCollection_Array1<gp_Vec2d> Geom2dGridEval_OffsetCurve::EvaluateGridDN(
|
||||
const NCollection_Array1<double>& theParams,
|
||||
int theN) const
|
||||
{
|
||||
if (myBasis.IsNull() || theParams.IsEmpty() || theN < 1)
|
||||
{
|
||||
return NCollection_Array1<gp_Vec2d>();
|
||||
}
|
||||
|
||||
const int aNbParams = theParams.Size();
|
||||
|
||||
// Reuse optimized grid evaluators for orders 1-3
|
||||
if (theN == 1)
|
||||
{
|
||||
NCollection_Array1<Geom2dGridEval::CurveD1> aD1Grid = EvaluateGridD1(theParams);
|
||||
if (aD1Grid.IsEmpty())
|
||||
{
|
||||
return NCollection_Array1<gp_Vec2d>();
|
||||
}
|
||||
NCollection_Array1<gp_Vec2d> aResult(1, aNbParams);
|
||||
for (int i = 1; i <= aNbParams; ++i)
|
||||
{
|
||||
aResult.SetValue(i, aD1Grid.Value(i).D1);
|
||||
}
|
||||
return aResult;
|
||||
}
|
||||
else if (theN == 2)
|
||||
{
|
||||
NCollection_Array1<Geom2dGridEval::CurveD2> aD2Grid = EvaluateGridD2(theParams);
|
||||
if (aD2Grid.IsEmpty())
|
||||
{
|
||||
return NCollection_Array1<gp_Vec2d>();
|
||||
}
|
||||
NCollection_Array1<gp_Vec2d> aResult(1, aNbParams);
|
||||
for (int i = 1; i <= aNbParams; ++i)
|
||||
{
|
||||
aResult.SetValue(i, aD2Grid.Value(i).D2);
|
||||
}
|
||||
return aResult;
|
||||
}
|
||||
else if (theN == 3)
|
||||
{
|
||||
NCollection_Array1<Geom2dGridEval::CurveD3> aD3Grid = EvaluateGridD3(theParams);
|
||||
if (aD3Grid.IsEmpty())
|
||||
{
|
||||
return NCollection_Array1<gp_Vec2d>();
|
||||
}
|
||||
NCollection_Array1<gp_Vec2d> aResult(1, aNbParams);
|
||||
for (int i = 1; i <= aNbParams; ++i)
|
||||
{
|
||||
aResult.SetValue(i, aD3Grid.Value(i).D3);
|
||||
}
|
||||
return aResult;
|
||||
}
|
||||
else
|
||||
{
|
||||
// For orders > 3, batch evaluate basis curve DN
|
||||
Geom2dGridEval_Curve aBasisEval;
|
||||
aBasisEval.Initialize(myBasis);
|
||||
return aBasisEval.EvaluateGridDN(theParams, theN);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
// 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 _Geom2dGridEval_OffsetCurve_HeaderFile
|
||||
#define _Geom2dGridEval_OffsetCurve_HeaderFile
|
||||
|
||||
#include <Geom2d_Curve.hxx>
|
||||
#include <Geom2d_OffsetCurve.hxx>
|
||||
#include <Geom2dGridEval.hxx>
|
||||
#include <NCollection_Array1.hxx>
|
||||
#include <Standard.hxx>
|
||||
#include <Standard_DefineAlloc.hxx>
|
||||
|
||||
//! @brief Batch evaluator for 2D offset curve grid points.
|
||||
//!
|
||||
//! Evaluates the 2D offset curve formula:
|
||||
//! P(u) = C(u) + Offset * N / ||N||
|
||||
//! where N = (D1.Y, -D1.X) is the normal (tangent rotated 90 degrees).
|
||||
//!
|
||||
//! Uses Geom2dGridEval_Curve for batch evaluation of the basis curve,
|
||||
//! then applies offset transformation.
|
||||
//!
|
||||
//! Usage:
|
||||
//! @code
|
||||
//! Geom2dGridEval_OffsetCurve anEvaluator(myGeom2dOffset);
|
||||
//! NCollection_Array1<gp_Pnt2d> aGrid = anEvaluator.EvaluateGrid(myParams);
|
||||
//! @endcode
|
||||
class Geom2dGridEval_OffsetCurve
|
||||
{
|
||||
public:
|
||||
DEFINE_STANDARD_ALLOC
|
||||
|
||||
//! Constructor with geometry.
|
||||
//! @param theOffset the 2D offset curve geometry to evaluate
|
||||
Geom2dGridEval_OffsetCurve(const occ::handle<Geom2d_OffsetCurve>& theOffset)
|
||||
: myGeom(theOffset),
|
||||
myOffset(0.0)
|
||||
{
|
||||
if (!myGeom.IsNull())
|
||||
{
|
||||
myOffset = myGeom->Offset();
|
||||
myBasis = myGeom->BasisCurve();
|
||||
}
|
||||
}
|
||||
|
||||
//! Non-copyable and non-movable.
|
||||
Geom2dGridEval_OffsetCurve(const Geom2dGridEval_OffsetCurve&) = delete;
|
||||
Geom2dGridEval_OffsetCurve& operator=(const Geom2dGridEval_OffsetCurve&) = delete;
|
||||
Geom2dGridEval_OffsetCurve(Geom2dGridEval_OffsetCurve&&) = delete;
|
||||
Geom2dGridEval_OffsetCurve& operator=(Geom2dGridEval_OffsetCurve&&) = delete;
|
||||
|
||||
//! Returns the geometry handle.
|
||||
const occ::handle<Geom2d_OffsetCurve>& Geometry() const { return myGeom; }
|
||||
|
||||
//! Evaluate all grid points.
|
||||
//! @param theParams array of parameter values
|
||||
//! @return array of evaluated points (1-based indexing),
|
||||
//! or empty array if geometry is null or no parameters
|
||||
Standard_EXPORT NCollection_Array1<gp_Pnt2d> EvaluateGrid(
|
||||
const NCollection_Array1<double>& theParams) const;
|
||||
|
||||
//! Evaluate all grid points with first derivative.
|
||||
//! @param theParams array of parameter values
|
||||
//! @return array of CurveD1 (1-based indexing),
|
||||
//! or empty array if geometry is null or no parameters
|
||||
Standard_EXPORT NCollection_Array1<Geom2dGridEval::CurveD1> EvaluateGridD1(
|
||||
const NCollection_Array1<double>& theParams) const;
|
||||
|
||||
//! Evaluate all grid points with first and second derivatives.
|
||||
//! @param theParams array of parameter values
|
||||
//! @return array of CurveD2 (1-based indexing),
|
||||
//! or empty array if geometry is null or no parameters
|
||||
Standard_EXPORT NCollection_Array1<Geom2dGridEval::CurveD2> EvaluateGridD2(
|
||||
const NCollection_Array1<double>& theParams) const;
|
||||
|
||||
//! Evaluate all grid points with derivatives up to third order.
|
||||
//! @param theParams array of parameter values
|
||||
//! @return array of CurveD3 (1-based indexing),
|
||||
//! or empty array if geometry is null or no parameters
|
||||
Standard_EXPORT NCollection_Array1<Geom2dGridEval::CurveD3> EvaluateGridD3(
|
||||
const NCollection_Array1<double>& theParams) const;
|
||||
|
||||
//! Evaluate Nth derivative at all grid points.
|
||||
//! For orders 1-3, reuses EvaluateGridD1/D2/D3.
|
||||
//! For orders > 3, uses basis curve DN method.
|
||||
//! @param theParams array of parameter values
|
||||
//! @param theN derivative order (N >= 1)
|
||||
//! @return array of derivative vectors (1-based indexing)
|
||||
Standard_EXPORT NCollection_Array1<gp_Vec2d> EvaluateGridDN(
|
||||
const NCollection_Array1<double>& theParams,
|
||||
int theN) const;
|
||||
|
||||
private:
|
||||
occ::handle<Geom2d_OffsetCurve> myGeom;
|
||||
occ::handle<Geom2d_Curve> myBasis;
|
||||
double myOffset;
|
||||
};
|
||||
|
||||
#endif // _Geom2dGridEval_OffsetCurve_HeaderFile
|
||||
@@ -0,0 +1,185 @@
|
||||
// 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 <Geom2dGridEval_OtherCurve.hxx>
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
NCollection_Array1<gp_Pnt2d> Geom2dGridEval_OtherCurve::EvaluateGrid(
|
||||
const NCollection_Array1<double>& theParams) const
|
||||
{
|
||||
if (theParams.IsEmpty())
|
||||
{
|
||||
return NCollection_Array1<gp_Pnt2d>();
|
||||
}
|
||||
|
||||
const int aNb = theParams.Size();
|
||||
NCollection_Array1<gp_Pnt2d> aResult(1, aNb);
|
||||
|
||||
for (int i = theParams.Lower(); i <= theParams.Upper(); ++i)
|
||||
{
|
||||
std::optional<gp_Pnt2d> aP = myCurve.get().EvalD0(theParams.Value(i));
|
||||
if (!aP)
|
||||
{
|
||||
return NCollection_Array1<gp_Pnt2d>();
|
||||
}
|
||||
aResult.SetValue(i - theParams.Lower() + 1, *aP);
|
||||
}
|
||||
|
||||
return aResult;
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
NCollection_Array1<Geom2dGridEval::CurveD1> Geom2dGridEval_OtherCurve::EvaluateGridD1(
|
||||
const NCollection_Array1<double>& theParams) const
|
||||
{
|
||||
if (theParams.IsEmpty())
|
||||
{
|
||||
return NCollection_Array1<Geom2dGridEval::CurveD1>();
|
||||
}
|
||||
|
||||
const int aNb = theParams.Size();
|
||||
NCollection_Array1<Geom2dGridEval::CurveD1> aResult(1, aNb);
|
||||
|
||||
for (int i = theParams.Lower(); i <= theParams.Upper(); ++i)
|
||||
{
|
||||
std::optional<Geom2d_Curve::ResD1> aD1 = myCurve.get().EvalD1(theParams.Value(i));
|
||||
if (!aD1)
|
||||
{
|
||||
return NCollection_Array1<Geom2dGridEval::CurveD1>();
|
||||
}
|
||||
aResult.ChangeValue(i - theParams.Lower() + 1) = {aD1->Point, aD1->D1};
|
||||
}
|
||||
|
||||
return aResult;
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
NCollection_Array1<Geom2dGridEval::CurveD2> Geom2dGridEval_OtherCurve::EvaluateGridD2(
|
||||
const NCollection_Array1<double>& theParams) const
|
||||
{
|
||||
if (theParams.IsEmpty())
|
||||
{
|
||||
return NCollection_Array1<Geom2dGridEval::CurveD2>();
|
||||
}
|
||||
|
||||
const int aNb = theParams.Size();
|
||||
NCollection_Array1<Geom2dGridEval::CurveD2> aResult(1, aNb);
|
||||
|
||||
for (int i = theParams.Lower(); i <= theParams.Upper(); ++i)
|
||||
{
|
||||
std::optional<Geom2d_Curve::ResD2> aD2 = myCurve.get().EvalD2(theParams.Value(i));
|
||||
if (!aD2)
|
||||
{
|
||||
return NCollection_Array1<Geom2dGridEval::CurveD2>();
|
||||
}
|
||||
aResult.ChangeValue(i - theParams.Lower() + 1) = {aD2->Point, aD2->D1, aD2->D2};
|
||||
}
|
||||
|
||||
return aResult;
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
NCollection_Array1<Geom2dGridEval::CurveD3> Geom2dGridEval_OtherCurve::EvaluateGridD3(
|
||||
const NCollection_Array1<double>& theParams) const
|
||||
{
|
||||
if (theParams.IsEmpty())
|
||||
{
|
||||
return NCollection_Array1<Geom2dGridEval::CurveD3>();
|
||||
}
|
||||
|
||||
const int aNb = theParams.Size();
|
||||
NCollection_Array1<Geom2dGridEval::CurveD3> aResult(1, aNb);
|
||||
|
||||
for (int i = theParams.Lower(); i <= theParams.Upper(); ++i)
|
||||
{
|
||||
std::optional<Geom2d_Curve::ResD3> aD3 = myCurve.get().EvalD3(theParams.Value(i));
|
||||
if (!aD3)
|
||||
{
|
||||
return NCollection_Array1<Geom2dGridEval::CurveD3>();
|
||||
}
|
||||
aResult.ChangeValue(i - theParams.Lower() + 1) = {aD3->Point, aD3->D1, aD3->D2, aD3->D3};
|
||||
}
|
||||
|
||||
return aResult;
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
NCollection_Array1<gp_Vec2d> Geom2dGridEval_OtherCurve::EvaluateGridDN(
|
||||
const NCollection_Array1<double>& theParams,
|
||||
int theN) const
|
||||
{
|
||||
if (theParams.IsEmpty() || theN < 1)
|
||||
{
|
||||
return NCollection_Array1<gp_Vec2d>();
|
||||
}
|
||||
|
||||
const int aNb = theParams.Size();
|
||||
NCollection_Array1<gp_Vec2d> aResult(1, aNb);
|
||||
|
||||
// Reuse existing grid evaluators for orders 1-3
|
||||
if (theN == 1)
|
||||
{
|
||||
NCollection_Array1<Geom2dGridEval::CurveD1> aD1Grid = EvaluateGridD1(theParams);
|
||||
if (aD1Grid.IsEmpty())
|
||||
{
|
||||
return NCollection_Array1<gp_Vec2d>();
|
||||
}
|
||||
for (int i = 1; i <= aNb; ++i)
|
||||
{
|
||||
aResult.SetValue(i, aD1Grid.Value(i).D1);
|
||||
}
|
||||
}
|
||||
else if (theN == 2)
|
||||
{
|
||||
NCollection_Array1<Geom2dGridEval::CurveD2> aD2Grid = EvaluateGridD2(theParams);
|
||||
if (aD2Grid.IsEmpty())
|
||||
{
|
||||
return NCollection_Array1<gp_Vec2d>();
|
||||
}
|
||||
for (int i = 1; i <= aNb; ++i)
|
||||
{
|
||||
aResult.SetValue(i, aD2Grid.Value(i).D2);
|
||||
}
|
||||
}
|
||||
else if (theN == 3)
|
||||
{
|
||||
NCollection_Array1<Geom2dGridEval::CurveD3> aD3Grid = EvaluateGridD3(theParams);
|
||||
if (aD3Grid.IsEmpty())
|
||||
{
|
||||
return NCollection_Array1<gp_Vec2d>();
|
||||
}
|
||||
for (int i = 1; i <= aNb; ++i)
|
||||
{
|
||||
aResult.SetValue(i, aD3Grid.Value(i).D3);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// For orders > 3, use adaptor EvalDN method
|
||||
for (int i = theParams.Lower(); i <= theParams.Upper(); ++i)
|
||||
{
|
||||
std::optional<gp_Vec2d> aDN = myCurve.get().EvalDN(theParams.Value(i), theN);
|
||||
if (!aDN)
|
||||
{
|
||||
return NCollection_Array1<gp_Vec2d>();
|
||||
}
|
||||
aResult.SetValue(i - theParams.Lower() + 1, *aDN);
|
||||
}
|
||||
}
|
||||
return aResult;
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
// 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 _Geom2dGridEval_OtherCurve_HeaderFile
|
||||
#define _Geom2dGridEval_OtherCurve_HeaderFile
|
||||
|
||||
#include <Adaptor2d_Curve2d.hxx>
|
||||
#include <Geom2dGridEval.hxx>
|
||||
#include <NCollection_Array1.hxx>
|
||||
#include <Standard.hxx>
|
||||
#include <Standard_DefineAlloc.hxx>
|
||||
|
||||
#include <functional>
|
||||
|
||||
//! @brief Fallback evaluator for unknown 2D curve types.
|
||||
//!
|
||||
//! Uses Adaptor2d_Curve2d::D0 for point-by-point evaluation.
|
||||
//! This is the slowest evaluator but handles any 2D curve type.
|
||||
//!
|
||||
//! @note The curve adaptor reference must remain valid during the lifetime
|
||||
//! of this evaluator. The evaluator does not take ownership.
|
||||
//!
|
||||
//! Usage:
|
||||
//! @code
|
||||
//! Geom2dGridEval_OtherCurve anEvaluator(myCurveAdaptor2d);
|
||||
//! NCollection_Array1<gp_Pnt2d> aGrid = anEvaluator.EvaluateGrid(myParams);
|
||||
//! @endcode
|
||||
class Geom2dGridEval_OtherCurve
|
||||
{
|
||||
public:
|
||||
DEFINE_STANDARD_ALLOC
|
||||
|
||||
//! Constructor with curve adaptor reference.
|
||||
//! @param theCurve reference to 2D curve adaptor (must remain valid)
|
||||
Geom2dGridEval_OtherCurve(const Adaptor2d_Curve2d& theCurve)
|
||||
: myCurve(theCurve)
|
||||
{
|
||||
}
|
||||
|
||||
//! Non-copyable and non-movable.
|
||||
Geom2dGridEval_OtherCurve(const Geom2dGridEval_OtherCurve&) = delete;
|
||||
Geom2dGridEval_OtherCurve& operator=(const Geom2dGridEval_OtherCurve&) = delete;
|
||||
Geom2dGridEval_OtherCurve(Geom2dGridEval_OtherCurve&&) = delete;
|
||||
Geom2dGridEval_OtherCurve& operator=(Geom2dGridEval_OtherCurve&&) = delete;
|
||||
|
||||
//! Returns the curve adaptor reference.
|
||||
const Adaptor2d_Curve2d& Curve() const { return myCurve.get(); }
|
||||
|
||||
//! Evaluate all grid points.
|
||||
//! @param theParams array of parameter values
|
||||
//! @return array of evaluated points (1-based indexing),
|
||||
//! or empty array if no parameters
|
||||
Standard_EXPORT NCollection_Array1<gp_Pnt2d> EvaluateGrid(
|
||||
const NCollection_Array1<double>& theParams) const;
|
||||
|
||||
//! Evaluate all grid points with first derivative.
|
||||
//! @param theParams array of parameter values
|
||||
//! @return array of CurveD1 (1-based indexing),
|
||||
//! or empty array if no parameters
|
||||
Standard_EXPORT NCollection_Array1<Geom2dGridEval::CurveD1> EvaluateGridD1(
|
||||
const NCollection_Array1<double>& theParams) const;
|
||||
|
||||
//! Evaluate all grid points with first and second derivatives.
|
||||
//! @param theParams array of parameter values
|
||||
//! @return array of CurveD2 (1-based indexing),
|
||||
//! or empty array if no parameters
|
||||
Standard_EXPORT NCollection_Array1<Geom2dGridEval::CurveD2> EvaluateGridD2(
|
||||
const NCollection_Array1<double>& theParams) const;
|
||||
|
||||
//! Evaluate all grid points with first, second, and third derivatives.
|
||||
//! @param theParams array of parameter values
|
||||
//! @return array of CurveD3 (1-based indexing),
|
||||
//! or empty array if no parameters
|
||||
Standard_EXPORT NCollection_Array1<Geom2dGridEval::CurveD3> EvaluateGridD3(
|
||||
const NCollection_Array1<double>& theParams) const;
|
||||
|
||||
//! Evaluate Nth derivative at all grid points.
|
||||
//! For orders 1-3, reuses EvaluateGridD1/D2/D3.
|
||||
//! For orders > 3, uses adaptor DN method.
|
||||
//! @param theParams array of parameter values
|
||||
//! @param theN derivative order (N >= 1)
|
||||
//! @return array of derivative vectors (1-based indexing)
|
||||
Standard_EXPORT NCollection_Array1<gp_Vec2d> EvaluateGridDN(
|
||||
const NCollection_Array1<double>& theParams,
|
||||
int theN) const;
|
||||
|
||||
private:
|
||||
std::reference_wrapper<const Adaptor2d_Curve2d> myCurve;
|
||||
};
|
||||
|
||||
#endif // _Geom2dGridEval_OtherCurve_HeaderFile
|
||||
@@ -0,0 +1,255 @@
|
||||
// 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 <Geom2dGridEval_Parabola.hxx>
|
||||
|
||||
#include <gp_Parab2d.hxx>
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
NCollection_Array1<gp_Pnt2d> Geom2dGridEval_Parabola::EvaluateGrid(
|
||||
const NCollection_Array1<double>& theParams) const
|
||||
{
|
||||
if (myGeom.IsNull() || theParams.IsEmpty())
|
||||
{
|
||||
return NCollection_Array1<gp_Pnt2d>();
|
||||
}
|
||||
|
||||
const int aNb = theParams.Size();
|
||||
NCollection_Array1<gp_Pnt2d> aResult(1, aNb);
|
||||
|
||||
const gp_Parab2d& aParab = myGeom->Parab2d();
|
||||
const gp_Pnt2d& aCenter = aParab.Location();
|
||||
const gp_Dir2d aXDir = aParab.MirrorAxis().Direction();
|
||||
const gp_Dir2d aYDir(-aXDir.Y(), aXDir.X());
|
||||
const double aFocal = aParab.Focal();
|
||||
|
||||
const double aCX = aCenter.X();
|
||||
const double aCY = aCenter.Y();
|
||||
const double aXX = aXDir.X();
|
||||
const double aXY = aXDir.Y();
|
||||
const double aYX = aYDir.X();
|
||||
const double aYY = aYDir.Y();
|
||||
|
||||
const double aCoeff = 1.0 / (4.0 * aFocal);
|
||||
|
||||
for (int i = theParams.Lower(); i <= theParams.Upper(); ++i)
|
||||
{
|
||||
const double u = theParams.Value(i);
|
||||
|
||||
// P = Center + (u^2 / 4F) * XDir + u * YDir
|
||||
const double u2Term = u * u * aCoeff;
|
||||
|
||||
aResult.SetValue(i - theParams.Lower() + 1,
|
||||
gp_Pnt2d(aCX + u2Term * aXX + u * aYX, aCY + u2Term * aXY + u * aYY));
|
||||
}
|
||||
return aResult;
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
NCollection_Array1<Geom2dGridEval::CurveD1> Geom2dGridEval_Parabola::EvaluateGridD1(
|
||||
const NCollection_Array1<double>& theParams) const
|
||||
{
|
||||
if (myGeom.IsNull() || theParams.IsEmpty())
|
||||
{
|
||||
return NCollection_Array1<Geom2dGridEval::CurveD1>();
|
||||
}
|
||||
|
||||
const int aNb = theParams.Size();
|
||||
NCollection_Array1<Geom2dGridEval::CurveD1> aResult(1, aNb);
|
||||
|
||||
const gp_Parab2d& aParab = myGeom->Parab2d();
|
||||
const gp_Pnt2d& aCenter = aParab.Location();
|
||||
const gp_Dir2d aXDir = aParab.MirrorAxis().Direction();
|
||||
const gp_Dir2d aYDir(-aXDir.Y(), aXDir.X());
|
||||
const double aFocal = aParab.Focal();
|
||||
|
||||
const double aCX = aCenter.X();
|
||||
const double aCY = aCenter.Y();
|
||||
const double aXX = aXDir.X();
|
||||
const double aXY = aXDir.Y();
|
||||
const double aYX = aYDir.X();
|
||||
const double aYY = aYDir.Y();
|
||||
|
||||
const double aCoeff = 1.0 / (4.0 * aFocal);
|
||||
const double aCoeff2 = 1.0 / (2.0 * aFocal);
|
||||
|
||||
for (int i = theParams.Lower(); i <= theParams.Upper(); ++i)
|
||||
{
|
||||
const double u = theParams.Value(i);
|
||||
|
||||
// P = Center + (u^2 / 4F) * XDir + u * YDir
|
||||
// D1 = (u / 2F) * XDir + YDir
|
||||
|
||||
const double u2Term = u * u * aCoeff;
|
||||
const double d1Term = u * aCoeff2;
|
||||
|
||||
aResult.ChangeValue(i - theParams.Lower() + 1) = {
|
||||
gp_Pnt2d(aCX + u2Term * aXX + u * aYX, aCY + u2Term * aXY + u * aYY),
|
||||
gp_Vec2d(d1Term * aXX + aYX, d1Term * aXY + aYY)};
|
||||
}
|
||||
return aResult;
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
NCollection_Array1<Geom2dGridEval::CurveD2> Geom2dGridEval_Parabola::EvaluateGridD2(
|
||||
const NCollection_Array1<double>& theParams) const
|
||||
{
|
||||
if (myGeom.IsNull() || theParams.IsEmpty())
|
||||
{
|
||||
return NCollection_Array1<Geom2dGridEval::CurveD2>();
|
||||
}
|
||||
|
||||
const int aNb = theParams.Size();
|
||||
NCollection_Array1<Geom2dGridEval::CurveD2> aResult(1, aNb);
|
||||
|
||||
const gp_Parab2d& aParab = myGeom->Parab2d();
|
||||
const gp_Pnt2d& aCenter = aParab.Location();
|
||||
const gp_Dir2d aXDir = aParab.MirrorAxis().Direction();
|
||||
const gp_Dir2d aYDir(-aXDir.Y(), aXDir.X());
|
||||
const double aFocal = aParab.Focal();
|
||||
|
||||
const double aCX = aCenter.X();
|
||||
const double aCY = aCenter.Y();
|
||||
const double aXX = aXDir.X();
|
||||
const double aXY = aXDir.Y();
|
||||
const double aYX = aYDir.X();
|
||||
const double aYY = aYDir.Y();
|
||||
|
||||
const double aCoeff = 1.0 / (4.0 * aFocal);
|
||||
const double aCoeff2 = 1.0 / (2.0 * aFocal);
|
||||
|
||||
// D2 is constant for parabola: (1/2F) * XDir
|
||||
const gp_Vec2d aD2(aCoeff2 * aXX, aCoeff2 * aXY);
|
||||
|
||||
for (int i = theParams.Lower(); i <= theParams.Upper(); ++i)
|
||||
{
|
||||
const double u = theParams.Value(i);
|
||||
|
||||
const double u2Term = u * u * aCoeff;
|
||||
const double d1Term = u * aCoeff2;
|
||||
|
||||
aResult.ChangeValue(i - theParams.Lower() + 1) = {
|
||||
gp_Pnt2d(aCX + u2Term * aXX + u * aYX, aCY + u2Term * aXY + u * aYY),
|
||||
gp_Vec2d(d1Term * aXX + aYX, d1Term * aXY + aYY),
|
||||
aD2};
|
||||
}
|
||||
return aResult;
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
NCollection_Array1<Geom2dGridEval::CurveD3> Geom2dGridEval_Parabola::EvaluateGridD3(
|
||||
const NCollection_Array1<double>& theParams) const
|
||||
{
|
||||
if (myGeom.IsNull() || theParams.IsEmpty())
|
||||
{
|
||||
return NCollection_Array1<Geom2dGridEval::CurveD3>();
|
||||
}
|
||||
|
||||
const int aNb = theParams.Size();
|
||||
NCollection_Array1<Geom2dGridEval::CurveD3> aResult(1, aNb);
|
||||
|
||||
const gp_Parab2d& aParab = myGeom->Parab2d();
|
||||
const gp_Pnt2d& aCenter = aParab.Location();
|
||||
const gp_Dir2d aXDir = aParab.MirrorAxis().Direction();
|
||||
const gp_Dir2d aYDir(-aXDir.Y(), aXDir.X());
|
||||
const double aFocal = aParab.Focal();
|
||||
|
||||
const double aCX = aCenter.X();
|
||||
const double aCY = aCenter.Y();
|
||||
const double aXX = aXDir.X();
|
||||
const double aXY = aXDir.Y();
|
||||
const double aYX = aYDir.X();
|
||||
const double aYY = aYDir.Y();
|
||||
|
||||
const double aCoeff = 1.0 / (4.0 * aFocal);
|
||||
const double aCoeff2 = 1.0 / (2.0 * aFocal);
|
||||
|
||||
const gp_Vec2d aD2(aCoeff2 * aXX, aCoeff2 * aXY);
|
||||
const gp_Vec2d aD3(0.0, 0.0);
|
||||
|
||||
for (int i = theParams.Lower(); i <= theParams.Upper(); ++i)
|
||||
{
|
||||
const double u = theParams.Value(i);
|
||||
|
||||
const double u2Term = u * u * aCoeff;
|
||||
const double d1Term = u * aCoeff2;
|
||||
|
||||
aResult.ChangeValue(i - theParams.Lower() + 1) = {
|
||||
gp_Pnt2d(aCX + u2Term * aXX + u * aYX, aCY + u2Term * aXY + u * aYY),
|
||||
gp_Vec2d(d1Term * aXX + aYX, d1Term * aXY + aYY),
|
||||
aD2,
|
||||
aD3};
|
||||
}
|
||||
return aResult;
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
NCollection_Array1<gp_Vec2d> Geom2dGridEval_Parabola::EvaluateGridDN(
|
||||
const NCollection_Array1<double>& theParams,
|
||||
int theN) const
|
||||
{
|
||||
if (myGeom.IsNull() || theParams.IsEmpty() || theN < 1)
|
||||
{
|
||||
return NCollection_Array1<gp_Vec2d>();
|
||||
}
|
||||
|
||||
const int aNb = theParams.Size();
|
||||
NCollection_Array1<gp_Vec2d> aResult(1, aNb);
|
||||
|
||||
const gp_Parab2d& aParab = myGeom->Parab2d();
|
||||
const gp_Dir2d aXDir = aParab.MirrorAxis().Direction();
|
||||
const gp_Dir2d aYDir(-aXDir.Y(), aXDir.X());
|
||||
const double aFocal = aParab.Focal();
|
||||
|
||||
const double aXX = aXDir.X();
|
||||
const double aXY = aXDir.Y();
|
||||
const double aYX = aYDir.X();
|
||||
const double aYY = aYDir.Y();
|
||||
|
||||
const double aCoeff2 = 1.0 / (2.0 * aFocal);
|
||||
|
||||
if (theN == 1)
|
||||
{
|
||||
// D1 = (u/2F) * X + Y (depends on u)
|
||||
for (int i = theParams.Lower(); i <= theParams.Upper(); ++i)
|
||||
{
|
||||
const double u = theParams.Value(i);
|
||||
const double d1Term = u * aCoeff2;
|
||||
aResult.SetValue(i - theParams.Lower() + 1, gp_Vec2d(d1Term * aXX + aYX, d1Term * aXY + aYY));
|
||||
}
|
||||
}
|
||||
else if (theN == 2)
|
||||
{
|
||||
// D2 = (1/2F) * X (constant)
|
||||
const gp_Vec2d aD2(aCoeff2 * aXX, aCoeff2 * aXY);
|
||||
for (int i = 1; i <= aNb; ++i)
|
||||
{
|
||||
aResult.SetValue(i, aD2);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// DN = 0 for N >= 3
|
||||
const gp_Vec2d aZero(0.0, 0.0);
|
||||
for (int i = 1; i <= aNb; ++i)
|
||||
{
|
||||
aResult.SetValue(i, aZero);
|
||||
}
|
||||
}
|
||||
return aResult;
|
||||
}
|
||||
@@ -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 _Geom2dGridEval_Parabola_HeaderFile
|
||||
#define _Geom2dGridEval_Parabola_HeaderFile
|
||||
|
||||
#include <Geom2d_Parabola.hxx>
|
||||
#include <Geom2dGridEval.hxx>
|
||||
#include <NCollection_Array1.hxx>
|
||||
#include <Standard.hxx>
|
||||
#include <Standard_DefineAlloc.hxx>
|
||||
|
||||
//! @brief Efficient batch evaluator for 2D parabola grid points.
|
||||
//!
|
||||
//! Uses analytical formula:
|
||||
//! P(u) = Center + (u^2 / (4*Focal)) * XDir + u * YDir
|
||||
//!
|
||||
//! Usage:
|
||||
//! @code
|
||||
//! Geom2dGridEval_Parabola anEvaluator(myGeom2dParabola);
|
||||
//! NCollection_Array1<gp_Pnt2d> aGrid = anEvaluator.EvaluateGrid(myParams);
|
||||
//! @endcode
|
||||
class Geom2dGridEval_Parabola
|
||||
{
|
||||
public:
|
||||
DEFINE_STANDARD_ALLOC
|
||||
|
||||
//! Constructor with geometry.
|
||||
//! @param theParabola the 2D parabola geometry to evaluate
|
||||
Geom2dGridEval_Parabola(const occ::handle<Geom2d_Parabola>& theParabola)
|
||||
: myGeom(theParabola)
|
||||
{
|
||||
}
|
||||
|
||||
//! Non-copyable and non-movable.
|
||||
Geom2dGridEval_Parabola(const Geom2dGridEval_Parabola&) = delete;
|
||||
Geom2dGridEval_Parabola& operator=(const Geom2dGridEval_Parabola&) = delete;
|
||||
Geom2dGridEval_Parabola(Geom2dGridEval_Parabola&&) = delete;
|
||||
Geom2dGridEval_Parabola& operator=(Geom2dGridEval_Parabola&&) = delete;
|
||||
|
||||
//! Returns the geometry handle.
|
||||
const occ::handle<Geom2d_Parabola>& Geometry() const { return myGeom; }
|
||||
|
||||
//! Evaluate all grid points.
|
||||
//! @param theParams array of parameter values
|
||||
//! @return array of evaluated points (1-based indexing),
|
||||
//! or empty array if geometry is null or no parameters
|
||||
Standard_EXPORT NCollection_Array1<gp_Pnt2d> EvaluateGrid(
|
||||
const NCollection_Array1<double>& theParams) const;
|
||||
|
||||
//! Evaluate all grid points with first derivative.
|
||||
//! @param theParams array of parameter values
|
||||
//! @return array of CurveD1 (1-based indexing)
|
||||
Standard_EXPORT NCollection_Array1<Geom2dGridEval::CurveD1> EvaluateGridD1(
|
||||
const NCollection_Array1<double>& theParams) const;
|
||||
|
||||
//! Evaluate all grid points with first and second derivatives.
|
||||
//! @param theParams array of parameter values
|
||||
//! @return array of CurveD2 (1-based indexing)
|
||||
Standard_EXPORT NCollection_Array1<Geom2dGridEval::CurveD2> EvaluateGridD2(
|
||||
const NCollection_Array1<double>& theParams) const;
|
||||
|
||||
//! Evaluate all grid points with first, second, and third derivatives.
|
||||
//! @param theParams array of parameter values
|
||||
//! @return array of CurveD3 (1-based indexing)
|
||||
Standard_EXPORT NCollection_Array1<Geom2dGridEval::CurveD3> EvaluateGridD3(
|
||||
const NCollection_Array1<double>& theParams) const;
|
||||
|
||||
//! Evaluate Nth derivative at all grid points.
|
||||
//! Parabola: P = Center + (u^2/4F) * X + u * Y
|
||||
//! D1 = (u/2F) * X + Y (depends on u)
|
||||
//! D2 = (1/2F) * X (constant)
|
||||
//! DN = 0 for N >= 3
|
||||
//! @param theParams array of parameter values
|
||||
//! @param theN derivative order (N >= 1)
|
||||
//! @return array of derivative vectors (1-based indexing)
|
||||
Standard_EXPORT NCollection_Array1<gp_Vec2d> EvaluateGridDN(
|
||||
const NCollection_Array1<double>& theParams,
|
||||
int theN) const;
|
||||
|
||||
private:
|
||||
occ::handle<Geom2d_Parabola> myGeom;
|
||||
};
|
||||
|
||||
#endif // _Geom2dGridEval_Parabola_HeaderFile
|
||||
@@ -7,4 +7,5 @@ set(OCCT_TKG2d_LIST_OF_PACKAGES
|
||||
Geom2dLProp
|
||||
Geom2dAdaptor
|
||||
Geom2dHash
|
||||
Geom2dGridEval
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user