diff --git a/src/ModelingAlgorithms/TKGeomAlgo/IntCurveSurface/IntCurveSurface_PolyhedronUtils.pxx b/src/ModelingAlgorithms/TKGeomAlgo/IntCurveSurface/IntCurveSurface_PolyhedronUtils.pxx index c882b90773..8a97bf2d90 100644 --- a/src/ModelingAlgorithms/TKGeomAlgo/IntCurveSurface/IntCurveSurface_PolyhedronUtils.pxx +++ b/src/ModelingAlgorithms/TKGeomAlgo/IntCurveSurface/IntCurveSurface_PolyhedronUtils.pxx @@ -79,8 +79,7 @@ inline void InitUniform(GeomGridEval_Surface& theEval, } // Evaluate grid - theEval.SetUVParams(aUParams, aVParams); - const NCollection_Array2 aGrid = theEval.EvaluateGrid(); + const NCollection_Array2 aGrid = theEval.EvaluateGrid(aUParams, aVParams); // Copy results to output arrays (convert from 2D grid to 1D linear indexing) int Index = 1; @@ -122,8 +121,7 @@ inline void InitWithParams(GeomGridEval_Surface& theEval, Bnd_Box& theBnd) { // Evaluate grid using provided parameters - theEval.SetUVParams(theUpars, theVpars); - const NCollection_Array2 aGrid = theEval.EvaluateGrid(); + const NCollection_Array2 aGrid = theEval.EvaluateGrid(theUpars, theVpars); const int i0 = theUpars.Lower(); const int j0 = theVpars.Lower(); @@ -144,61 +142,6 @@ inline void InitWithParams(GeomGridEval_Surface& theEval, } } -//! Calculate deflection on a single triangle. -//! Evaluates the center point on the surface and computes deflection. -//! @tparam SurfaceType Type of surface (e.g., Handle(Adaptor3d_Surface) or pointer) -//! @param[in] theSurface The surface (accessed via ->Value()) -//! @param[in] theP1 First vertex point -//! @param[in] theP2 Second vertex point -//! @param[in] theP3 Third vertex point -//! @param[in] theU1 U parameter at first vertex -//! @param[in] theV1 V parameter at first vertex -//! @param[in] theU2 U parameter at second vertex -//! @param[in] theV2 V parameter at second vertex -//! @param[in] theU3 U parameter at third vertex -//! @param[in] theV3 V parameter at third vertex -//! @return Deflection value (distance from triangle center to surface) -template -double DeflectionOnTriangle(const SurfaceType& theSurface, - const gp_Pnt& theP1, - const gp_Pnt& theP2, - const gp_Pnt& theP3, - const double theU1, - const double theV1, - const double theU2, - const double theV2, - const double theU3, - const double theV3) -{ - // Check for degenerate triangles - if (theP1.SquareDistance(theP2) <= THE_MIN_EDGE_LENGTH_SQUARED) - return 0.0; - if (theP1.SquareDistance(theP3) <= THE_MIN_EDGE_LENGTH_SQUARED) - return 0.0; - if (theP2.SquareDistance(theP3) <= THE_MIN_EDGE_LENGTH_SQUARED) - return 0.0; - - // Compute normal vector - const gp_XYZ XYZ1 = theP2.XYZ() - theP1.XYZ(); - const gp_XYZ XYZ2 = theP3.XYZ() - theP2.XYZ(); - const gp_XYZ XYZ3 = theP1.XYZ() - theP3.XYZ(); - gp_Vec NormalVector((XYZ1 ^ XYZ2) + (XYZ2 ^ XYZ3) + (XYZ3 ^ XYZ1)); - - const double aNormLen = NormalVector.Magnitude(); - if (aNormLen < gp::Resolution()) - return 0.0; - - NormalVector.Divide(aNormLen); - - // Calculate center point on surface and compute distance to triangle plane - const double u = (theU1 + theU2 + theU3) / 3.0; - const double v = (theV1 + theV2 + theV3) / 3.0; - const gp_Pnt aCenter = theSurface->Value(u, v); - const gp_Vec P1P(theP1, aCenter); - - return std::abs(P1P.Dot(NormalVector)); -} - //! Compute border deflection for a boundary isoline using grid evaluation. //! Uses batch evaluation for better performance on complex surfaces. //! @param[in,out] theEval Grid evaluator (will be reused for isoline evaluation) @@ -238,16 +181,9 @@ inline double ComputeBorderDeflection(GeomGridEval_Surface& theEval, } // Evaluate grid: 1xN or Nx1 depending on isoline direction - if (theIsUIso) - { - theEval.SetUVParams(aFixedParams, aVaryingParams); - } - else - { - theEval.SetUVParams(aVaryingParams, aFixedParams); - } - - const NCollection_Array2 aGrid = theEval.EvaluateGrid(); + const NCollection_Array2 aGrid = theIsUIso + ? theEval.EvaluateGrid(aFixedParams, aVaryingParams) + : theEval.EvaluateGrid(aVaryingParams, aFixedParams); // Compute max deflection from pre-evaluated points double aDeflection = RealFirst(); @@ -650,30 +586,93 @@ inline void FillBounding(const gp_Pnt* thePnts, } } -//! Compute the maximum deflection over all triangles. -//! @tparam SurfaceType Type of surface (e.g., Handle(Adaptor3d_Surface) or pointer) +//! Compute deflection for a single triangle given a pre-evaluated center point. +//! @param[in] theP1 First vertex +//! @param[in] theP2 Second vertex +//! @param[in] theP3 Third vertex +//! @param[in] theCenter Pre-evaluated center point on surface +//! @return Deflection value (distance from triangle center to surface) +inline double ComputeDeflectionWithCenter(const gp_Pnt& theP1, + const gp_Pnt& theP2, + const gp_Pnt& theP3, + const gp_Pnt& theCenter) +{ + // Check for degenerate triangles + if (theP1.SquareDistance(theP2) <= THE_MIN_EDGE_LENGTH_SQUARED) + return 0.0; + if (theP1.SquareDistance(theP3) <= THE_MIN_EDGE_LENGTH_SQUARED) + return 0.0; + if (theP2.SquareDistance(theP3) <= THE_MIN_EDGE_LENGTH_SQUARED) + return 0.0; + + // Compute normal vector + const gp_XYZ XYZ1 = theP2.XYZ() - theP1.XYZ(); + const gp_XYZ XYZ2 = theP3.XYZ() - theP2.XYZ(); + const gp_XYZ XYZ3 = theP1.XYZ() - theP3.XYZ(); + gp_Vec NormalVector((XYZ1 ^ XYZ2) + (XYZ2 ^ XYZ3) + (XYZ3 ^ XYZ1)); + + const double aNormLen = NormalVector.Magnitude(); + if (aNormLen < gp::Resolution()) + return 0.0; + + NormalVector.Divide(aNormLen); + + // Compute distance from center to triangle plane + const gp_Vec P1P(theP1, theCenter); + return std::abs(P1P.Dot(NormalVector)); +} + +//! Compute the maximum deflection over all triangles using batch evaluation. +//! Uses GeomGridEval_Surface::EvaluatePoints() to batch-evaluate all triangle centroids. //! @tparam PolyhedronType Type of polyhedron class -//! @param[in] theSurface The surface (accessed via ->Value()) +//! @param[in] theEval Pre-initialized grid evaluator //! @param[in] thePolyhedron The polyhedron object (provides Triangle/Point access) //! @param[in] theNbTriangles Number of triangles //! @return Maximum deflection value -template -double ComputeMaxDeflection(const SurfaceType& theSurface, +template +double ComputeMaxDeflection(GeomGridEval_Surface& theEval, const PolyhedronType& thePolyhedron, const int theNbTriangles) { - double tol = 0.0; + if (theNbTriangles <= 0) + return 0.0; + + // Collect all triangle centroid UV pairs + NCollection_Array1 aCentroidUVs(1, theNbTriangles); + for (int i = 1; i <= theNbTriangles; ++i) { int i1, i2, i3; thePolyhedron.Triangle(i, i1, i2, i3); double u1, v1, u2, v2, u3, v3; - gp_Pnt P1 = thePolyhedron.Point(i1, u1, v1); - gp_Pnt P2 = thePolyhedron.Point(i2, u2, v2); - gp_Pnt P3 = thePolyhedron.Point(i3, u3, v3); + thePolyhedron.Point(i1, u1, v1); + thePolyhedron.Point(i2, u2, v2); + thePolyhedron.Point(i3, u3, v3); - double tol1 = DeflectionOnTriangle(theSurface, P1, P2, P3, u1, v1, u2, v2, u3, v3); + const double uCenter = (u1 + u2 + u3) / 3.0; + const double vCenter = (v1 + v2 + v3) / 3.0; + aCentroidUVs.SetValue(i, gp_Pnt2d(uCenter, vCenter)); + } + + // Batch evaluate all centroids + NCollection_Array1 aCenterPoints = theEval.EvaluatePoints(aCentroidUVs); + if (aCenterPoints.IsEmpty()) + return 0.0; + + // Compute max deflection using pre-evaluated center points + double tol = 0.0; + for (int i = 1; i <= theNbTriangles; ++i) + { + int i1, i2, i3; + thePolyhedron.Triangle(i, i1, i2, i3); + + double u1, v1, u2, v2, u3, v3; + const gp_Pnt P1 = thePolyhedron.Point(i1, u1, v1); + const gp_Pnt P2 = thePolyhedron.Point(i2, u2, v2); + const gp_Pnt P3 = thePolyhedron.Point(i3, u3, v3); + + const double tol1 = ComputeDeflectionWithCenter(P1, P2, P3, aCenterPoints.Value(i)); if (tol1 > tol) tol = tol1; } diff --git a/src/ModelingAlgorithms/TKGeomAlgo/IntCurveSurface/IntCurveSurface_ThePolyhedronOfHInter.cxx b/src/ModelingAlgorithms/TKGeomAlgo/IntCurveSurface/IntCurveSurface_ThePolyhedronOfHInter.cxx index 3d9badccd5..00ce8810e9 100644 --- a/src/ModelingAlgorithms/TKGeomAlgo/IntCurveSurface/IntCurveSurface_ThePolyhedronOfHInter.cxx +++ b/src/ModelingAlgorithms/TKGeomAlgo/IntCurveSurface/IntCurveSurface_ThePolyhedronOfHInter.cxx @@ -103,7 +103,7 @@ void IntCurveSurface_ThePolyhedronOfHInter::Init(const Handle(Adaptor3d_Surface) static_cast(C_MyIsOnBounds), TheBnd); - Standard_Real tol = PolyUtils::ComputeMaxDeflection(Surface, *this, NbTriangles()); + Standard_Real tol = PolyUtils::ComputeMaxDeflection(anEval, *this, NbTriangles()); DeflectionOverEstimation(tol * 1.2); FillBounding(); @@ -132,7 +132,7 @@ void IntCurveSurface_ThePolyhedronOfHInter::Init(const Handle(Adaptor3d_Surface) static_cast(C_MyIsOnBounds), TheBnd); - Standard_Real tol = PolyUtils::ComputeMaxDeflection(Surface, *this, NbTriangles()); + Standard_Real tol = PolyUtils::ComputeMaxDeflection(anEval, *this, NbTriangles()); DeflectionOverEstimation(tol * 1.2); FillBounding(); @@ -147,19 +147,6 @@ void IntCurveSurface_ThePolyhedronOfHInter::Init(const Handle(Adaptor3d_Surface) //================================================================================================== -Standard_Real IntCurveSurface_ThePolyhedronOfHInter::DeflectionOnTriangle( - const Handle(Adaptor3d_Surface)& Surface, - const Standard_Integer Triang) const -{ - Standard_Integer i1, i2, i3; - Triangle(Triang, i1, i2, i3); - Standard_Real u1, v1, u2, v2, u3, v3; - gp_Pnt P1 = Point(i1, u1, v1), P2 = Point(i2, u2, v2), P3 = Point(i3, u3, v3); - return PolyUtils::DeflectionOnTriangle(Surface, P1, P2, P3, u1, v1, u2, v2, u3, v3); -} - -//================================================================================================== - void IntCurveSurface_ThePolyhedronOfHInter::Parameters(const Standard_Integer Index, Standard_Real& U, Standard_Real& V) const diff --git a/src/ModelingAlgorithms/TKGeomAlgo/IntCurveSurface/IntCurveSurface_ThePolyhedronOfHInter.hxx b/src/ModelingAlgorithms/TKGeomAlgo/IntCurveSurface/IntCurveSurface_ThePolyhedronOfHInter.hxx index 11c5cd177e..97566f06bf 100644 --- a/src/ModelingAlgorithms/TKGeomAlgo/IntCurveSurface/IntCurveSurface_ThePolyhedronOfHInter.hxx +++ b/src/ModelingAlgorithms/TKGeomAlgo/IntCurveSurface/IntCurveSurface_ThePolyhedronOfHInter.hxx @@ -47,9 +47,6 @@ public: Standard_EXPORT void DeflectionOverEstimation(const Standard_Real flec); - Standard_EXPORT Standard_Real DeflectionOnTriangle(const Handle(Adaptor3d_Surface)& Surface, - const Standard_Integer Index) const; - Standard_EXPORT void UMinSingularity(const Standard_Boolean Sing); Standard_EXPORT void UMaxSingularity(const Standard_Boolean Sing); diff --git a/src/ModelingAlgorithms/TKGeomAlgo/IntPatch/IntPatch_Polyhedron.cxx b/src/ModelingAlgorithms/TKGeomAlgo/IntPatch/IntPatch_Polyhedron.cxx index 53f59dbfac..958c156822 100644 --- a/src/ModelingAlgorithms/TKGeomAlgo/IntPatch/IntPatch_Polyhedron.cxx +++ b/src/ModelingAlgorithms/TKGeomAlgo/IntPatch/IntPatch_Polyhedron.cxx @@ -15,11 +15,14 @@ // commercial license or contractual agreement. #include +#include #include #include #include +#include #include #include +#include #include #include @@ -29,6 +32,8 @@ #define DEFLECTION_COEFF 1.1 #define NBMAXUV 30 +namespace PolyUtils = IntCurveSurface_PolyhedronUtils; + //================================================================================ static Standard_Integer NbPOnU(const Handle(Adaptor3d_Surface)& S) { @@ -90,34 +95,42 @@ IntPatch_Polyhedron::IntPatch_Polyhedron(const Handle(Adaptor3d_Surface)& Surfac const Standard_Real v0 = Surface->FirstVParameter(); const Standard_Real v1 = Surface->LastVParameter(); - const Standard_Real U1mU0sNbdeltaU = (u1 - u0) / (Standard_Real)nbdeltaU; - const Standard_Real V1mV0sNbdeltaV = (v1 - v0) / (Standard_Real)nbdeltaV; + // Build UV parameter arrays + TColStd_Array1OfReal aUParams(0, nbdeltaU); + TColStd_Array1OfReal aVParams(0, nbdeltaV); + const Standard_Real U1mU0sNbdeltaU = (u1 - u0) / (Standard_Real)nbdeltaU; + const Standard_Real V1mV0sNbdeltaV = (v1 - v0) / (Standard_Real)nbdeltaV; - gp_Pnt TP; - Standard_Real U, V; - Standard_Integer i1, i2, Index = 1; - for (i1 = 0, U = u0; i1 <= nbdeltaU; i1++, U += U1mU0sNbdeltaU) + for (Standard_Integer i = 0; i <= nbdeltaU; ++i) { - for (i2 = 0, V = v0; i2 <= nbdeltaV; i2++, V += V1mV0sNbdeltaV) + aUParams.SetValue(i, u0 + i * U1mU0sNbdeltaU); + } + for (Standard_Integer j = 0; j <= nbdeltaV; ++j) + { + aVParams.SetValue(j, v0 + j * V1mV0sNbdeltaV); + } + + // Use grid evaluator for batch point evaluation + GeomGridEval_Surface anEval; + anEval.Initialize(*Surface); + NCollection_Array2 aGridPnts = anEval.EvaluateGrid(aUParams, aVParams); + + // Copy to internal arrays and build bounding box + Standard_Integer Index = 1; + for (Standard_Integer i1 = 0; i1 <= nbdeltaU; ++i1) + { + for (Standard_Integer i2 = 0; i2 <= nbdeltaV; ++i2) { - Surface->D0(U, V, TP); - CMyPnts[Index] = TP; - CMyU[Index] = U; - CMyV[Index] = V; - TheBnd.Add(TP); + CMyPnts[Index] = aGridPnts.Value(i1 + 1, i2 + 1); + CMyU[Index] = aUParams.Value(i1); + CMyV[Index] = aVParams.Value(i2); + TheBnd.Add(CMyPnts[Index]); Index++; } } - Standard_Real tol = 0.0; - const Standard_Integer nbtriangles = NbTriangles(); - for (i1 = 1; i1 <= nbtriangles; i1++) - { - const Standard_Real tol1 = DeflectionOnTriangle(Surface, i1); - if (tol1 > tol) - tol = tol1; - } - + // Compute max deflection using batch evaluation + Standard_Real tol = PolyUtils::ComputeMaxDeflection(anEval, *this, NbTriangles()); tol *= DEFLECTION_COEFF; DeflectionOverEstimation(tol); @@ -153,34 +166,42 @@ IntPatch_Polyhedron::IntPatch_Polyhedron(const Handle(Adaptor3d_Surface)& Surfac const Standard_Real v0 = Surface->FirstVParameter(); const Standard_Real v1 = Surface->LastVParameter(); - const Standard_Real U1mU0sNbdeltaU = (u1 - u0) / (Standard_Real)nbdeltaU; - const Standard_Real V1mV0sNbdeltaV = (v1 - v0) / (Standard_Real)nbdeltaV; + // Build UV parameter arrays + TColStd_Array1OfReal aUParams(0, nbdeltaU); + TColStd_Array1OfReal aVParams(0, nbdeltaV); + const Standard_Real U1mU0sNbdeltaU = (u1 - u0) / (Standard_Real)nbdeltaU; + const Standard_Real V1mV0sNbdeltaV = (v1 - v0) / (Standard_Real)nbdeltaV; - gp_Pnt TP; - Standard_Real U, V; - Standard_Integer i1, i2, Index = 1; - for (i1 = 0, U = u0; i1 <= nbdeltaU; i1++, U += U1mU0sNbdeltaU) + for (Standard_Integer i = 0; i <= nbdeltaU; ++i) { - for (i2 = 0, V = v0; i2 <= nbdeltaV; i2++, V += V1mV0sNbdeltaV) + aUParams.SetValue(i, u0 + i * U1mU0sNbdeltaU); + } + for (Standard_Integer j = 0; j <= nbdeltaV; ++j) + { + aVParams.SetValue(j, v0 + j * V1mV0sNbdeltaV); + } + + // Use grid evaluator for batch point evaluation + GeomGridEval_Surface anEval; + anEval.Initialize(*Surface); + NCollection_Array2 aGridPnts = anEval.EvaluateGrid(aUParams, aVParams); + + // Copy to internal arrays and build bounding box + Standard_Integer Index = 1; + for (Standard_Integer i1 = 0; i1 <= nbdeltaU; ++i1) + { + for (Standard_Integer i2 = 0; i2 <= nbdeltaV; ++i2) { - Surface->D0(U, V, TP); - CMyPnts[Index] = TP; - CMyU[Index] = U; - CMyV[Index] = V; - TheBnd.Add(TP); + CMyPnts[Index] = aGridPnts.Value(i1 + 1, i2 + 1); + CMyU[Index] = aUParams.Value(i1); + CMyV[Index] = aVParams.Value(i2); + TheBnd.Add(CMyPnts[Index]); Index++; } } - Standard_Real tol = 0.0; - const Standard_Integer nbtriangles = NbTriangles(); - for (i1 = 1; i1 <= nbtriangles; i1++) - { - const Standard_Real tol1 = DeflectionOnTriangle(Surface, i1); - if (tol1 > tol) - tol = tol1; - } - + // Compute max deflection using batch evaluation + Standard_Real tol = PolyUtils::ComputeMaxDeflection(anEval, *this, NbTriangles()); tol *= DEFLECTION_COEFF; DeflectionOverEstimation(tol); @@ -189,44 +210,6 @@ IntPatch_Polyhedron::IntPatch_Polyhedron(const Handle(Adaptor3d_Surface)& Surfac //================================================================================================= -Standard_Real IntPatch_Polyhedron::DeflectionOnTriangle(const Handle(Adaptor3d_Surface)& Surface, - const Standard_Integer Triang) const -{ - Standard_Integer i1, i2, i3; - - Triangle(Triang, i1, i2, i3); - //-- Calcul de l eqution du plan - Standard_Real u1, v1, u2, v2, u3, v3; - gp_Pnt P1, P2, P3; - P1 = Point(i1, u1, v1); - P2 = Point(i2, u2, v2); - P3 = Point(i3, u3, v3); - if (P1.SquareDistance(P2) <= LONGUEUR_MINI_EDGE_TRIANGLE) - return (0); - if (P1.SquareDistance(P3) <= LONGUEUR_MINI_EDGE_TRIANGLE) - return (0); - if (P2.SquareDistance(P3) <= LONGUEUR_MINI_EDGE_TRIANGLE) - return (0); - gp_XYZ XYZ1 = P2.XYZ() - P1.XYZ(); - gp_XYZ XYZ2 = P3.XYZ() - P2.XYZ(); - gp_XYZ XYZ3 = P1.XYZ() - P3.XYZ(); - gp_Vec NormalVector((XYZ1 ^ XYZ2) + (XYZ2 ^ XYZ3) + (XYZ3 ^ XYZ1)); - Standard_Real aNormLen = NormalVector.Magnitude(); - if (aNormLen < gp::Resolution()) - { - return 0.; - } - // - NormalVector.Divide(aNormLen); - //-- Calcul du point u,v au centre du triangle - Standard_Real u = (u1 + u2 + u3) / 3.0; - Standard_Real v = (v1 + v2 + v3) / 3.0; - gp_Vec P1P(P1, Surface->Value(u, v)); - return (std::abs(P1P.Dot(NormalVector))); -} - -//================================================================================================= - void IntPatch_Polyhedron::Parameters(const Standard_Integer Index, Standard_Real& U, Standard_Real& V) const diff --git a/src/ModelingAlgorithms/TKGeomAlgo/IntPatch/IntPatch_Polyhedron.hxx b/src/ModelingAlgorithms/TKGeomAlgo/IntPatch/IntPatch_Polyhedron.hxx index 8133773540..4155dac749 100644 --- a/src/ModelingAlgorithms/TKGeomAlgo/IntPatch/IntPatch_Polyhedron.hxx +++ b/src/ModelingAlgorithms/TKGeomAlgo/IntPatch/IntPatch_Polyhedron.hxx @@ -45,9 +45,6 @@ public: Standard_EXPORT void DeflectionOverEstimation(const Standard_Real flec); - Standard_EXPORT Standard_Real DeflectionOnTriangle(const Handle(Adaptor3d_Surface)& Surface, - const Standard_Integer Index) const; - Standard_EXPORT void UMinSingularity(const Standard_Boolean Sing); Standard_EXPORT void UMaxSingularity(const Standard_Boolean Sing); diff --git a/src/ModelingAlgorithms/TKHLR/HLRBRep/HLRBRep_ThePolyhedronOfInterCSurf.cxx b/src/ModelingAlgorithms/TKHLR/HLRBRep/HLRBRep_ThePolyhedronOfInterCSurf.cxx index 5b22e845ff..5115532f64 100644 --- a/src/ModelingAlgorithms/TKHLR/HLRBRep/HLRBRep_ThePolyhedronOfInterCSurf.cxx +++ b/src/ModelingAlgorithms/TKHLR/HLRBRep/HLRBRep_ThePolyhedronOfInterCSurf.cxx @@ -102,7 +102,7 @@ void HLRBRep_ThePolyhedronOfInterCSurf::Init(HLRBRep_Surface* Surface, static_cast(C_MyIsOnBounds), TheBnd); - Standard_Real tol = PolyUtils::ComputeMaxDeflection(Surface, *this, NbTriangles()); + Standard_Real tol = PolyUtils::ComputeMaxDeflection(anEval, *this, NbTriangles()); DeflectionOverEstimation(tol * 1.2); FillBounding(); @@ -131,7 +131,7 @@ void HLRBRep_ThePolyhedronOfInterCSurf::Init(HLRBRep_Surface* Surface static_cast(C_MyIsOnBounds), TheBnd); - Standard_Real tol = PolyUtils::ComputeMaxDeflection(Surface, *this, NbTriangles()); + Standard_Real tol = PolyUtils::ComputeMaxDeflection(anEval, *this, NbTriangles()); DeflectionOverEstimation(tol * 1.2); FillBounding(); @@ -146,19 +146,6 @@ void HLRBRep_ThePolyhedronOfInterCSurf::Init(HLRBRep_Surface* Surface //================================================================================================== -Standard_Real HLRBRep_ThePolyhedronOfInterCSurf::DeflectionOnTriangle( - HLRBRep_Surface* Surface, - const Standard_Integer Triang) const -{ - Standard_Integer i1, i2, i3; - Triangle(Triang, i1, i2, i3); - Standard_Real u1, v1, u2, v2, u3, v3; - gp_Pnt P1 = Point(i1, u1, v1), P2 = Point(i2, u2, v2), P3 = Point(i3, u3, v3); - return PolyUtils::DeflectionOnTriangle(Surface, P1, P2, P3, u1, v1, u2, v2, u3, v3); -} - -//================================================================================================== - void HLRBRep_ThePolyhedronOfInterCSurf::Parameters(const Standard_Integer Index, Standard_Real& U, Standard_Real& V) const diff --git a/src/ModelingAlgorithms/TKHLR/HLRBRep/HLRBRep_ThePolyhedronOfInterCSurf.hxx b/src/ModelingAlgorithms/TKHLR/HLRBRep/HLRBRep_ThePolyhedronOfInterCSurf.hxx index 58c15331bc..7cfd5da845 100644 --- a/src/ModelingAlgorithms/TKHLR/HLRBRep/HLRBRep_ThePolyhedronOfInterCSurf.hxx +++ b/src/ModelingAlgorithms/TKHLR/HLRBRep/HLRBRep_ThePolyhedronOfInterCSurf.hxx @@ -55,9 +55,6 @@ public: Standard_EXPORT void DeflectionOverEstimation(const Standard_Real flec); - Standard_EXPORT Standard_Real DeflectionOnTriangle(HLRBRep_Surface* Surface, - const Standard_Integer Index) const; - Standard_EXPORT void UMinSingularity(const Standard_Boolean Sing); Standard_EXPORT void UMaxSingularity(const Standard_Boolean Sing); diff --git a/src/ModelingData/TKG3d/GTests/FILES.cmake b/src/ModelingData/TKG3d/GTests/FILES.cmake index dcb234e9c4..5b4b37da60 100644 --- a/src/ModelingData/TKG3d/GTests/FILES.cmake +++ b/src/ModelingData/TKG3d/GTests/FILES.cmake @@ -13,6 +13,7 @@ set(OCCT_TKG3d_GTests_FILES GeomAPI_Interpolate_Test.cxx GeomGridEval_Cone_Test.cxx GeomGridEval_Curve_Test.cxx + GeomGridEval_Sphere_Test.cxx GeomGridEval_BezierCurve_Test.cxx GeomGridEval_BezierSurface_Test.cxx GeomGridEval_BSplineSurface_Test.cxx diff --git a/src/ModelingData/TKG3d/GTests/GeomGridEval_BSplineSurface_Test.cxx b/src/ModelingData/TKG3d/GTests/GeomGridEval_BSplineSurface_Test.cxx index 726866080f..1caf0d11dc 100644 --- a/src/ModelingData/TKG3d/GTests/GeomGridEval_BSplineSurface_Test.cxx +++ b/src/ModelingData/TKG3d/GTests/GeomGridEval_BSplineSurface_Test.cxx @@ -148,9 +148,8 @@ TEST(GeomGridEval_BSplineSurfaceTest, BasicEvaluation) TColStd_Array1OfReal aUParams = CreateUniformParams(0.0, 1.0, 5); TColStd_Array1OfReal aVParams = CreateUniformParams(0.0, 1.0, 5); - anEval.SetUVParams(aUParams, aVParams); - NCollection_Array2 aGrid = anEval.EvaluateGrid(); + NCollection_Array2 aGrid = anEval.EvaluateGrid(aUParams, aVParams); for (int iU = 1; iU <= 5; ++iU) { @@ -174,9 +173,8 @@ TEST(GeomGridEval_BSplineSurfaceTest, CornerPoints) aUParams.SetValue(2, 1.0); aVParams.SetValue(1, 0.0); aVParams.SetValue(2, 1.0); - anEval.SetUVParams(aUParams, aVParams); - NCollection_Array2 aGrid = anEval.EvaluateGrid(); + NCollection_Array2 aGrid = anEval.EvaluateGrid(aUParams, aVParams); EXPECT_NEAR(aGrid.Value(1, 1).Distance(gp_Pnt(0, 0, 0)), 0.0, THE_TOLERANCE); EXPECT_NEAR(aGrid.Value(2, 1).Distance(gp_Pnt(1, 0, 0)), 0.0, THE_TOLERANCE); @@ -192,9 +190,8 @@ TEST(GeomGridEval_BSplineSurfaceTest, RationalSurface) TColStd_Array1OfReal aUParams = CreateUniformParams(0.0, 1.0, 11); TColStd_Array1OfReal aVParams = CreateUniformParams(0.0, 1.0, 11); - anEval.SetUVParams(aUParams, aVParams); - NCollection_Array2 aGrid = anEval.EvaluateGrid(); + NCollection_Array2 aGrid = anEval.EvaluateGrid(aUParams, aVParams); for (int iU = 1; iU <= 11; ++iU) { @@ -214,9 +211,8 @@ TEST(GeomGridEval_BSplineSurfaceTest, MultiSpanSurface) TColStd_Array1OfReal aUParams = CreateUniformParams(0.0, 1.0, 21); TColStd_Array1OfReal aVParams = CreateUniformParams(0.0, 1.0, 21); - anEval.SetUVParams(aUParams, aVParams); - NCollection_Array2 aGrid = anEval.EvaluateGrid(); + NCollection_Array2 aGrid = anEval.EvaluateGrid(aUParams, aVParams); for (int iU = 1; iU <= 21; ++iU) { @@ -264,9 +260,8 @@ TEST(GeomGridEval_BSplineSurfaceTest, HigherDegree) TColStd_Array1OfReal aUParams = CreateUniformParams(0.0, 1.0, 17); TColStd_Array1OfReal aVParams = CreateUniformParams(0.0, 1.0, 17); - anEval.SetUVParams(aUParams, aVParams); - NCollection_Array2 aGrid = anEval.EvaluateGrid(); + NCollection_Array2 aGrid = anEval.EvaluateGrid(aUParams, aVParams); for (int iU = 1; iU <= 17; ++iU) { @@ -292,8 +287,7 @@ TEST(GeomGridEval_BSplineSurfaceTest, IsolineU_CompareToGeomD0) aUParams.SetValue(1, 0.5); TColStd_Array1OfReal aVParams = CreateUniformParams(0.0, 1.0, 15); - anEval.SetUVParams(aUParams, aVParams); - NCollection_Array2 aGrid = anEval.EvaluateGrid(); + NCollection_Array2 aGrid = anEval.EvaluateGrid(aUParams, aVParams); // Compare against Geom_BSplineSurface::D0 // Note: ColLength() = number of U params (rows), RowLength() = number of V params (columns) @@ -320,8 +314,7 @@ TEST(GeomGridEval_BSplineSurfaceTest, IsolineV_CompareToGeomD0) TColStd_Array1OfReal aVParams(1, 1); aVParams.SetValue(1, 0.7); - anEval.SetUVParams(aUParams, aVParams); - NCollection_Array2 aGrid = anEval.EvaluateGrid(); + NCollection_Array2 aGrid = anEval.EvaluateGrid(aUParams, aVParams); // Compare against Geom_BSplineSurface::D0 const int aNbU = aGrid.ColLength(); @@ -347,8 +340,7 @@ TEST(GeomGridEval_BSplineSurfaceTest, IsolineMultiSpan_CompareToGeomD0) aUParams.SetValue(1, 0.35); TColStd_Array1OfReal aVParams = CreateUniformParams(0.0, 1.0, 20); - anEval.SetUVParams(aUParams, aVParams); - NCollection_Array2 aGrid = anEval.EvaluateGrid(); + NCollection_Array2 aGrid = anEval.EvaluateGrid(aUParams, aVParams); // Compare against Geom_BSplineSurface::D0 const int aNbU = aGrid.ColLength(); @@ -374,8 +366,7 @@ TEST(GeomGridEval_BSplineSurfaceTest, IsolineRational_CompareToGeomD0) TColStd_Array1OfReal aVParams(1, 1); aVParams.SetValue(1, 0.3); - anEval.SetUVParams(aUParams, aVParams); - NCollection_Array2 aGrid = anEval.EvaluateGrid(); + NCollection_Array2 aGrid = anEval.EvaluateGrid(aUParams, aVParams); // Compare against Geom_BSplineSurface::D0 const int aNbU = aGrid.ColLength(); @@ -402,9 +393,8 @@ TEST(GeomGridEval_BSplineSurfaceTest, DerivativeD1) TColStd_Array1OfReal aUParams = CreateUniformParams(0.0, 1.0, 5); TColStd_Array1OfReal aVParams = CreateUniformParams(0.0, 1.0, 5); - anEval.SetUVParams(aUParams, aVParams); - NCollection_Array2 aGrid = anEval.EvaluateGridD1(); + NCollection_Array2 aGrid = anEval.EvaluateGridD1(aUParams, aVParams); for (int iU = 1; iU <= 5; ++iU) { @@ -427,9 +417,8 @@ TEST(GeomGridEval_BSplineSurfaceTest, DerivativeD2) TColStd_Array1OfReal aUParams = CreateUniformParams(0.0, 1.0, 5); TColStd_Array1OfReal aVParams = CreateUniformParams(0.0, 1.0, 5); - anEval.SetUVParams(aUParams, aVParams); - NCollection_Array2 aGrid = anEval.EvaluateGridD2(); + NCollection_Array2 aGrid = anEval.EvaluateGridD2(aUParams, aVParams); for (int iU = 1; iU <= 5; ++iU) { @@ -455,9 +444,8 @@ TEST(GeomGridEval_BSplineSurfaceTest, DerivativeD3) TColStd_Array1OfReal aUParams = CreateUniformParams(0.0, 1.0, 11); TColStd_Array1OfReal aVParams = CreateUniformParams(0.0, 1.0, 11); - anEval.SetUVParams(aUParams, aVParams); - NCollection_Array2 aGrid = anEval.EvaluateGridD3(); + NCollection_Array2 aGrid = anEval.EvaluateGridD3(aUParams, aVParams); GeomAdaptor_Surface anAdaptor(aSurf); for (int iU = 1; iU <= 11; ++iU) @@ -503,9 +491,8 @@ TEST(GeomGridEval_BSplineSurfaceTest, DerivativeDN_U1V0) TColStd_Array1OfReal aUParams = CreateUniformParams(0.0, 1.0, 5); TColStd_Array1OfReal aVParams = CreateUniformParams(0.0, 1.0, 5); - anEval.SetUVParams(aUParams, aVParams); - NCollection_Array2 aGrid = anEval.EvaluateGridDN(1, 0); + NCollection_Array2 aGrid = anEval.EvaluateGridDN(aUParams, aVParams, 1, 0); for (int iU = 1; iU <= 5; ++iU) { @@ -524,9 +511,8 @@ TEST(GeomGridEval_BSplineSurfaceTest, DerivativeDN_U0V1) TColStd_Array1OfReal aUParams = CreateUniformParams(0.0, 1.0, 5); TColStd_Array1OfReal aVParams = CreateUniformParams(0.0, 1.0, 5); - anEval.SetUVParams(aUParams, aVParams); - NCollection_Array2 aGrid = anEval.EvaluateGridDN(0, 1); + NCollection_Array2 aGrid = anEval.EvaluateGridDN(aUParams, aVParams, 0, 1); for (int iU = 1; iU <= 5; ++iU) { @@ -545,9 +531,8 @@ TEST(GeomGridEval_BSplineSurfaceTest, DerivativeDN_U1V1) TColStd_Array1OfReal aUParams = CreateUniformParams(0.0, 1.0, 5); TColStd_Array1OfReal aVParams = CreateUniformParams(0.0, 1.0, 5); - anEval.SetUVParams(aUParams, aVParams); - NCollection_Array2 aGrid = anEval.EvaluateGridDN(1, 1); + NCollection_Array2 aGrid = anEval.EvaluateGridDN(aUParams, aVParams, 1, 1); for (int iU = 1; iU <= 5; ++iU) { @@ -566,9 +551,8 @@ TEST(GeomGridEval_BSplineSurfaceTest, DerivativeDN_BeyondDegree) TColStd_Array1OfReal aUParams = CreateUniformParams(0.0, 1.0, 5); TColStd_Array1OfReal aVParams = CreateUniformParams(0.0, 1.0, 5); - anEval.SetUVParams(aUParams, aVParams); - NCollection_Array2 aGrid = anEval.EvaluateGridDN(2, 0); + NCollection_Array2 aGrid = anEval.EvaluateGridDN(aUParams, aVParams, 2, 0); for (int iU = 1; iU <= 5; ++iU) { @@ -586,7 +570,6 @@ TEST(GeomGridEval_BSplineSurfaceTest, DerivativeDN_MultiSpan) TColStd_Array1OfReal aUParams = CreateUniformParams(0.0, 1.0, 11); TColStd_Array1OfReal aVParams = CreateUniformParams(0.0, 1.0, 11); - anEval.SetUVParams(aUParams, aVParams); const int aTestCases[][2] = {{1, 0}, {0, 1}, {1, 1}, {2, 0}, {0, 2}, {2, 1}, {1, 2}}; @@ -595,7 +578,7 @@ TEST(GeomGridEval_BSplineSurfaceTest, DerivativeDN_MultiSpan) const int aNU = aCase[0]; const int aNV = aCase[1]; - NCollection_Array2 aGrid = anEval.EvaluateGridDN(aNU, aNV); + NCollection_Array2 aGrid = anEval.EvaluateGridDN(aUParams, aVParams, aNU, aNV); for (int iU = 1; iU <= 11; ++iU) { @@ -615,7 +598,6 @@ TEST(GeomGridEval_BSplineSurfaceTest, DerivativeDN_RationalSurface) TColStd_Array1OfReal aUParams = CreateUniformParams(0.0, 1.0, 7); TColStd_Array1OfReal aVParams = CreateUniformParams(0.0, 1.0, 7); - anEval.SetUVParams(aUParams, aVParams); for (int aNU = 0; aNU <= 2; ++aNU) { @@ -626,7 +608,7 @@ TEST(GeomGridEval_BSplineSurfaceTest, DerivativeDN_RationalSurface) continue; } - NCollection_Array2 aGrid = anEval.EvaluateGridDN(aNU, aNV); + NCollection_Array2 aGrid = anEval.EvaluateGridDN(aUParams, aVParams, aNU, aNV); for (int iU = 1; iU <= 7; ++iU) { @@ -639,3 +621,259 @@ TEST(GeomGridEval_BSplineSurfaceTest, DerivativeDN_RationalSurface) } } } + +//================================================================================================== +// UV Pairs Evaluation Tests +//================================================================================================== + +TEST(GeomGridEval_BSplineSurfaceTest, UVPairs_BasicEvaluation) +{ + Handle(Geom_BSplineSurface) aSurf = CreateSimpleBSplineSurface(); + GeomGridEval_BSplineSurface anEval(aSurf); + + // Create arbitrary UV pairs + NCollection_Array1 aUVPairs(1, 5); + aUVPairs.SetValue(1, gp_Pnt2d(0.0, 0.0)); + aUVPairs.SetValue(2, gp_Pnt2d(0.5, 0.25)); + aUVPairs.SetValue(3, gp_Pnt2d(1.0, 1.0)); + aUVPairs.SetValue(4, gp_Pnt2d(0.3, 0.7)); + aUVPairs.SetValue(5, gp_Pnt2d(0.8, 0.2)); + + NCollection_Array1 aPoints = anEval.EvaluatePoints(aUVPairs); + EXPECT_EQ(aPoints.Size(), 5); + + // Verify results against Geom_BSplineSurface::D0 + for (int i = 1; i <= 5; ++i) + { + gp_Pnt aExpected; + aSurf->D0(aUVPairs.Value(i).X(), aUVPairs.Value(i).Y(), aExpected); + EXPECT_NEAR(aPoints.Value(i).Distance(aExpected), 0.0, THE_TOLERANCE); + } +} + +TEST(GeomGridEval_BSplineSurfaceTest, UVPairs_MultiSpan) +{ + Handle(Geom_BSplineSurface) aSurf = CreateMultiSpanBSplineSurface(); + GeomGridEval_BSplineSurface anEval(aSurf); + + // Create UV pairs that span multiple knot spans + NCollection_Array1 aUVPairs(1, 10); + aUVPairs.SetValue(1, gp_Pnt2d(0.1, 0.1)); + aUVPairs.SetValue(2, gp_Pnt2d(0.6, 0.3)); // Different U span + aUVPairs.SetValue(3, gp_Pnt2d(0.2, 0.7)); // Different V span + aUVPairs.SetValue(4, gp_Pnt2d(0.8, 0.9)); // Both different + aUVPairs.SetValue(5, gp_Pnt2d(0.45, 0.45)); + aUVPairs.SetValue(6, gp_Pnt2d(0.55, 0.55)); + aUVPairs.SetValue(7, gp_Pnt2d(0.3, 0.4)); + aUVPairs.SetValue(8, gp_Pnt2d(0.7, 0.2)); + aUVPairs.SetValue(9, gp_Pnt2d(0.9, 0.1)); + aUVPairs.SetValue(10, gp_Pnt2d(0.05, 0.95)); + + NCollection_Array1 aPoints = anEval.EvaluatePoints(aUVPairs); + + for (int i = 1; i <= 10; ++i) + { + gp_Pnt aExpected; + aSurf->D0(aUVPairs.Value(i).X(), aUVPairs.Value(i).Y(), aExpected); + EXPECT_NEAR(aPoints.Value(i).Distance(aExpected), 0.0, THE_TOLERANCE); + } +} + +TEST(GeomGridEval_BSplineSurfaceTest, UVPairs_Rational) +{ + Handle(Geom_BSplineSurface) aSurf = CreateRationalBSplineSurface(); + GeomGridEval_BSplineSurface anEval(aSurf); + + NCollection_Array1 aUVPairs(1, 7); + aUVPairs.SetValue(1, gp_Pnt2d(0.0, 0.0)); + aUVPairs.SetValue(2, gp_Pnt2d(0.5, 0.5)); + aUVPairs.SetValue(3, gp_Pnt2d(1.0, 1.0)); + aUVPairs.SetValue(4, gp_Pnt2d(0.25, 0.75)); + aUVPairs.SetValue(5, gp_Pnt2d(0.75, 0.25)); + aUVPairs.SetValue(6, gp_Pnt2d(0.33, 0.67)); + aUVPairs.SetValue(7, gp_Pnt2d(0.67, 0.33)); + + NCollection_Array1 aPoints = anEval.EvaluatePoints(aUVPairs); + + for (int i = 1; i <= 7; ++i) + { + gp_Pnt aExpected; + aSurf->D0(aUVPairs.Value(i).X(), aUVPairs.Value(i).Y(), aExpected); + EXPECT_NEAR(aPoints.Value(i).Distance(aExpected), 0.0, THE_TOLERANCE); + } +} + +TEST(GeomGridEval_BSplineSurfaceTest, UVPairs_DerivativeD1) +{ + Handle(Geom_BSplineSurface) aSurf = CreateSimpleBSplineSurface(); + GeomGridEval_BSplineSurface anEval(aSurf); + + NCollection_Array1 aUVPairs(1, 4); + aUVPairs.SetValue(1, gp_Pnt2d(0.2, 0.3)); + aUVPairs.SetValue(2, gp_Pnt2d(0.5, 0.5)); + aUVPairs.SetValue(3, gp_Pnt2d(0.8, 0.1)); + aUVPairs.SetValue(4, gp_Pnt2d(0.4, 0.9)); + + NCollection_Array1 aResults = anEval.EvaluatePointsD1(aUVPairs); + + for (int i = 1; i <= 4; ++i) + { + gp_Pnt aPnt; + gp_Vec aD1U, aD1V; + aSurf->D1(aUVPairs.Value(i).X(), aUVPairs.Value(i).Y(), aPnt, aD1U, aD1V); + EXPECT_NEAR(aResults.Value(i).Point.Distance(aPnt), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aResults.Value(i).D1U - aD1U).Magnitude(), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aResults.Value(i).D1V - aD1V).Magnitude(), 0.0, THE_TOLERANCE); + } +} + +TEST(GeomGridEval_BSplineSurfaceTest, UVPairs_DerivativeD2) +{ + Handle(Geom_BSplineSurface) aSurf = CreateMultiSpanBSplineSurface(); + GeomGridEval_BSplineSurface anEval(aSurf); + + NCollection_Array1 aUVPairs(1, 5); + aUVPairs.SetValue(1, gp_Pnt2d(0.1, 0.2)); + aUVPairs.SetValue(2, gp_Pnt2d(0.6, 0.7)); + aUVPairs.SetValue(3, gp_Pnt2d(0.3, 0.8)); + aUVPairs.SetValue(4, gp_Pnt2d(0.9, 0.4)); + aUVPairs.SetValue(5, gp_Pnt2d(0.45, 0.55)); + + NCollection_Array1 aResults = anEval.EvaluatePointsD2(aUVPairs); + + for (int i = 1; i <= 5; ++i) + { + gp_Pnt aPnt; + gp_Vec aD1U, aD1V, aD2U, aD2V, aD2UV; + aSurf->D2(aUVPairs.Value(i).X(), aUVPairs.Value(i).Y(), aPnt, aD1U, aD1V, aD2U, aD2V, aD2UV); + EXPECT_NEAR(aResults.Value(i).Point.Distance(aPnt), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aResults.Value(i).D1U - aD1U).Magnitude(), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aResults.Value(i).D1V - aD1V).Magnitude(), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aResults.Value(i).D2U - aD2U).Magnitude(), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aResults.Value(i).D2V - aD2V).Magnitude(), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aResults.Value(i).D2UV - aD2UV).Magnitude(), 0.0, THE_TOLERANCE); + } +} + +TEST(GeomGridEval_BSplineSurfaceTest, UVPairs_DerivativeD3) +{ + Handle(Geom_BSplineSurface) aSurf = CreateMultiSpanBSplineSurface(); + GeomGridEval_BSplineSurface anEval(aSurf); + GeomAdaptor_Surface anAdaptor(aSurf); + + NCollection_Array1 aUVPairs(1, 4); + aUVPairs.SetValue(1, gp_Pnt2d(0.15, 0.25)); + aUVPairs.SetValue(2, gp_Pnt2d(0.65, 0.75)); + aUVPairs.SetValue(3, gp_Pnt2d(0.35, 0.85)); + aUVPairs.SetValue(4, gp_Pnt2d(0.85, 0.35)); + + NCollection_Array1 aResults = anEval.EvaluatePointsD3(aUVPairs); + + for (int i = 1; i <= 4; ++i) + { + gp_Pnt aPnt; + gp_Vec aD1U, aD1V, aD2U, aD2V, aD2UV, aD3U, aD3V, aD3UUV, aD3UVV; + anAdaptor.D3(aUVPairs.Value(i).X(), + aUVPairs.Value(i).Y(), + aPnt, + aD1U, + aD1V, + aD2U, + aD2V, + aD2UV, + aD3U, + aD3V, + aD3UUV, + aD3UVV); + EXPECT_NEAR(aResults.Value(i).Point.Distance(aPnt), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aResults.Value(i).D3U - aD3U).Magnitude(), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aResults.Value(i).D3V - aD3V).Magnitude(), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aResults.Value(i).D3UUV - aD3UUV).Magnitude(), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aResults.Value(i).D3UVV - aD3UVV).Magnitude(), 0.0, THE_TOLERANCE); + } +} + +TEST(GeomGridEval_BSplineSurfaceTest, UVPairs_DerivativeDN) +{ + Handle(Geom_BSplineSurface) aSurf = CreateMultiSpanBSplineSurface(); + GeomGridEval_BSplineSurface anEval(aSurf); + + NCollection_Array1 aUVPairs(1, 6); + aUVPairs.SetValue(1, gp_Pnt2d(0.1, 0.1)); + aUVPairs.SetValue(2, gp_Pnt2d(0.3, 0.5)); + aUVPairs.SetValue(3, gp_Pnt2d(0.6, 0.2)); + aUVPairs.SetValue(4, gp_Pnt2d(0.8, 0.8)); + aUVPairs.SetValue(5, gp_Pnt2d(0.4, 0.9)); + aUVPairs.SetValue(6, gp_Pnt2d(0.9, 0.3)); + + const int aTestCases[][2] = {{1, 0}, {0, 1}, {1, 1}, {2, 0}, {0, 2}}; + + for (const auto& aCase : aTestCases) + { + const int aNU = aCase[0]; + const int aNV = aCase[1]; + + NCollection_Array1 aResults = anEval.EvaluatePointsDN(aUVPairs, aNU, aNV); + + for (int i = 1; i <= 6; ++i) + { + gp_Vec aExpected = aSurf->DN(aUVPairs.Value(i).X(), aUVPairs.Value(i).Y(), aNU, aNV); + EXPECT_NEAR((aResults.Value(i) - aExpected).Magnitude(), 0.0, THE_TOLERANCE); + } + } +} + +TEST(GeomGridEval_BSplineSurfaceTest, UVPairs_OrderPreservation) +{ + // Verify that results are returned in original input order regardless of sorting + Handle(Geom_BSplineSurface) aSurf = CreateMultiSpanBSplineSurface(); + GeomGridEval_BSplineSurface anEval(aSurf); + + // Create UV pairs in a specific order that will be reordered during sorting + NCollection_Array1 aUVPairs(1, 6); + aUVPairs.SetValue(1, gp_Pnt2d(0.9, 0.1)); // High U span + aUVPairs.SetValue(2, gp_Pnt2d(0.1, 0.9)); // Low U span + aUVPairs.SetValue(3, gp_Pnt2d(0.5, 0.5)); // Middle + aUVPairs.SetValue(4, gp_Pnt2d(0.2, 0.2)); // Low spans + aUVPairs.SetValue(5, gp_Pnt2d(0.8, 0.8)); // High spans + aUVPairs.SetValue(6, gp_Pnt2d(0.4, 0.6)); // Mixed + + NCollection_Array1 aPoints = anEval.EvaluatePoints(aUVPairs); + + // Verify each result corresponds to its original input index + for (int i = 1; i <= 6; ++i) + { + gp_Pnt aExpected; + aSurf->D0(aUVPairs.Value(i).X(), aUVPairs.Value(i).Y(), aExpected); + EXPECT_NEAR(aPoints.Value(i).Distance(aExpected), 0.0, THE_TOLERANCE) + << "Mismatch at index " << i; + } +} + +TEST(GeomGridEval_BSplineSurfaceTest, UVPairs_EmptyInput) +{ + Handle(Geom_BSplineSurface) aSurf = CreateSimpleBSplineSurface(); + GeomGridEval_BSplineSurface anEval(aSurf); + + NCollection_Array1 aEmptyPairs; + + NCollection_Array1 aPoints = anEval.EvaluatePoints(aEmptyPairs); + EXPECT_TRUE(aPoints.IsEmpty()); +} + +TEST(GeomGridEval_BSplineSurfaceTest, UVPairs_SinglePoint) +{ + Handle(Geom_BSplineSurface) aSurf = CreateSimpleBSplineSurface(); + GeomGridEval_BSplineSurface anEval(aSurf); + + NCollection_Array1 aUVPairs(1, 1); + aUVPairs.SetValue(1, gp_Pnt2d(0.5, 0.5)); + + NCollection_Array1 aPoints = anEval.EvaluatePoints(aUVPairs); + + EXPECT_EQ(aPoints.Size(), 1); + + gp_Pnt aExpected; + aSurf->D0(0.5, 0.5, aExpected); + EXPECT_NEAR(aPoints.Value(1).Distance(aExpected), 0.0, THE_TOLERANCE); +} diff --git a/src/ModelingData/TKG3d/GTests/GeomGridEval_BezierCurve_Test.cxx b/src/ModelingData/TKG3d/GTests/GeomGridEval_BezierCurve_Test.cxx index 1410ce85d4..95475e0e7b 100644 --- a/src/ModelingData/TKG3d/GTests/GeomGridEval_BezierCurve_Test.cxx +++ b/src/ModelingData/TKG3d/GTests/GeomGridEval_BezierCurve_Test.cxx @@ -56,9 +56,8 @@ TEST(GeomGridEval_BezierCurveTest, BasicEvaluation) aParams.SetValue(1, 0.0); aParams.SetValue(2, 0.5); aParams.SetValue(3, 1.0); - anEval.SetParams(aParams); - NCollection_Array1 aGrid = anEval.EvaluateGrid(); + NCollection_Array1 aGrid = anEval.EvaluateGrid(aParams); EXPECT_EQ(aGrid.Size(), 3); // Verify points @@ -81,9 +80,8 @@ TEST(GeomGridEval_BezierCurveTest, DerivativeD1) GeomGridEval_BezierCurve anEval(aBezier); TColStd_Array1OfReal aParams = CreateUniformParams(0.0, 1.0, 5); - anEval.SetParams(aParams); - NCollection_Array1 aGrid = anEval.EvaluateGridD1(); + NCollection_Array1 aGrid = anEval.EvaluateGridD1(aParams); for (int i = 1; i <= 5; ++i) { @@ -107,9 +105,8 @@ TEST(GeomGridEval_BezierCurveTest, DerivativeD2) GeomGridEval_BezierCurve anEval(aBezier); TColStd_Array1OfReal aParams = CreateUniformParams(0.0, 1.0, 5); - anEval.SetParams(aParams); - NCollection_Array1 aGrid = anEval.EvaluateGridD2(); + NCollection_Array1 aGrid = anEval.EvaluateGridD2(aParams); for (int i = 1; i <= 5; ++i) { @@ -134,9 +131,8 @@ TEST(GeomGridEval_BezierCurveTest, DerivativeD3) GeomGridEval_BezierCurve anEval(aBezier); TColStd_Array1OfReal aParams = CreateUniformParams(0.0, 1.0, 5); - anEval.SetParams(aParams); - NCollection_Array1 aGrid = anEval.EvaluateGridD3(); + NCollection_Array1 aGrid = anEval.EvaluateGridD3(aParams); for (int i = 1; i <= 5; ++i) { @@ -168,9 +164,8 @@ TEST(GeomGridEval_BezierCurveTest, RationalEvaluation) GeomGridEval_BezierCurve anEval(aBezier); TColStd_Array1OfReal aParams = CreateUniformParams(0.0, 1.0, 11); - anEval.SetParams(aParams); - NCollection_Array1 aGrid = anEval.EvaluateGrid(); + NCollection_Array1 aGrid = anEval.EvaluateGrid(aParams); for (int i = 1; i <= 11; ++i) { @@ -191,9 +186,8 @@ TEST(GeomGridEval_BezierCurveTest, DerivativeDN_Order1) GeomGridEval_BezierCurve anEval(aBezier); TColStd_Array1OfReal aParams = CreateUniformParams(0.0, 1.0, 5); - anEval.SetParams(aParams); - NCollection_Array1 aGrid = anEval.EvaluateGridDN(1); + NCollection_Array1 aGrid = anEval.EvaluateGridDN(aParams, 1); for (int i = 1; i <= 5; ++i) { @@ -214,9 +208,8 @@ TEST(GeomGridEval_BezierCurveTest, DerivativeDN_Order2) GeomGridEval_BezierCurve anEval(aBezier); TColStd_Array1OfReal aParams = CreateUniformParams(0.0, 1.0, 5); - anEval.SetParams(aParams); - NCollection_Array1 aGrid = anEval.EvaluateGridDN(2); + NCollection_Array1 aGrid = anEval.EvaluateGridDN(aParams, 2); for (int i = 1; i <= 5; ++i) { @@ -237,9 +230,8 @@ TEST(GeomGridEval_BezierCurveTest, DerivativeDN_Order3) GeomGridEval_BezierCurve anEval(aBezier); TColStd_Array1OfReal aParams = CreateUniformParams(0.0, 1.0, 5); - anEval.SetParams(aParams); - NCollection_Array1 aGrid = anEval.EvaluateGridDN(3); + NCollection_Array1 aGrid = anEval.EvaluateGridDN(aParams, 3); for (int i = 1; i <= 5; ++i) { @@ -261,10 +253,9 @@ TEST(GeomGridEval_BezierCurveTest, DerivativeDN_BeyondDegree) GeomGridEval_BezierCurve anEval(aBezier); TColStd_Array1OfReal aParams = CreateUniformParams(0.0, 1.0, 5); - anEval.SetParams(aParams); // 4th derivative of cubic Bezier should be zero - NCollection_Array1 aGrid = anEval.EvaluateGridDN(4); + NCollection_Array1 aGrid = anEval.EvaluateGridDN(aParams, 4); for (int i = 1; i <= 5; ++i) { @@ -290,12 +281,11 @@ TEST(GeomGridEval_BezierCurveTest, DerivativeDN_RationalCurve) GeomGridEval_BezierCurve anEval(aBezier); TColStd_Array1OfReal aParams = CreateUniformParams(0.0, 1.0, 11); - anEval.SetParams(aParams); // Test DN for orders 1, 2 for (int aOrder = 1; aOrder <= 2; ++aOrder) { - NCollection_Array1 aGrid = anEval.EvaluateGridDN(aOrder); + NCollection_Array1 aGrid = anEval.EvaluateGridDN(aParams, aOrder); for (int i = 1; i <= 11; ++i) { diff --git a/src/ModelingData/TKG3d/GTests/GeomGridEval_BezierSurface_Test.cxx b/src/ModelingData/TKG3d/GTests/GeomGridEval_BezierSurface_Test.cxx index 498a99b011..2543d90899 100644 --- a/src/ModelingData/TKG3d/GTests/GeomGridEval_BezierSurface_Test.cxx +++ b/src/ModelingData/TKG3d/GTests/GeomGridEval_BezierSurface_Test.cxx @@ -53,9 +53,8 @@ TEST(GeomGridEval_BezierSurfaceTest, BasicEvaluation) EXPECT_FALSE(anEval.Geometry().IsNull()); TColStd_Array1OfReal aParams = CreateUniformParams(0.0, 1.0, 3); - anEval.SetUVParams(aParams, aParams); - NCollection_Array2 aGrid = anEval.EvaluateGrid(); + NCollection_Array2 aGrid = anEval.EvaluateGrid(aParams, aParams); EXPECT_EQ(aGrid.RowLength(), 3); EXPECT_EQ(aGrid.ColLength(), 3); @@ -90,9 +89,8 @@ TEST(GeomGridEval_BezierSurfaceTest, RationalEvaluation) GeomGridEval_BezierSurface anEval(aBezier); TColStd_Array1OfReal aParams = CreateUniformParams(0.0, 1.0, 5); - anEval.SetUVParams(aParams, aParams); - NCollection_Array2 aGrid = anEval.EvaluateGrid(); + NCollection_Array2 aGrid = anEval.EvaluateGrid(aParams, aParams); for (int i = 1; i <= 5; ++i) { @@ -116,9 +114,8 @@ TEST(GeomGridEval_BezierSurfaceTest, DerivativeD1) GeomGridEval_BezierSurface anEval(aBezier); TColStd_Array1OfReal aParams = CreateUniformParams(0.0, 1.0, 5); - anEval.SetUVParams(aParams, aParams); - NCollection_Array2 aGrid = anEval.EvaluateGridD1(); + NCollection_Array2 aGrid = anEval.EvaluateGridD1(aParams, aParams); for (int i = 1; i <= 5; ++i) { @@ -145,9 +142,8 @@ TEST(GeomGridEval_BezierSurfaceTest, DerivativeD2) GeomGridEval_BezierSurface anEval(aBezier); TColStd_Array1OfReal aParams = CreateUniformParams(0.0, 1.0, 5); - anEval.SetUVParams(aParams, aParams); - NCollection_Array2 aGrid = anEval.EvaluateGridD2(); + NCollection_Array2 aGrid = anEval.EvaluateGridD2(aParams, aParams); for (int i = 1; i <= 5; ++i) { @@ -177,9 +173,8 @@ TEST(GeomGridEval_BezierSurfaceTest, DerivativeD3) GeomGridEval_BezierSurface anEval(aBezier); TColStd_Array1OfReal aParams = CreateUniformParams(0.0, 1.0, 5); - anEval.SetUVParams(aParams, aParams); - NCollection_Array2 aGrid = anEval.EvaluateGridD3(); + NCollection_Array2 aGrid = anEval.EvaluateGridD3(aParams, aParams); for (int i = 1; i <= 5; ++i) { @@ -219,9 +214,8 @@ TEST(GeomGridEval_BezierSurfaceTest, DerivativeDN_U1V0) GeomGridEval_BezierSurface anEval(aBezier); TColStd_Array1OfReal aParams = CreateUniformParams(0.0, 1.0, 5); - anEval.SetUVParams(aParams, aParams); - NCollection_Array2 aGrid = anEval.EvaluateGridDN(1, 0); + NCollection_Array2 aGrid = anEval.EvaluateGridDN(aParams, aParams, 1, 0); for (int i = 1; i <= 5; ++i) { @@ -244,9 +238,8 @@ TEST(GeomGridEval_BezierSurfaceTest, DerivativeDN_U0V1) GeomGridEval_BezierSurface anEval(aBezier); TColStd_Array1OfReal aParams = CreateUniformParams(0.0, 1.0, 5); - anEval.SetUVParams(aParams, aParams); - NCollection_Array2 aGrid = anEval.EvaluateGridDN(0, 1); + NCollection_Array2 aGrid = anEval.EvaluateGridDN(aParams, aParams, 0, 1); for (int i = 1; i <= 5; ++i) { @@ -269,9 +262,8 @@ TEST(GeomGridEval_BezierSurfaceTest, DerivativeDN_U2V0) GeomGridEval_BezierSurface anEval(aBezier); TColStd_Array1OfReal aParams = CreateUniformParams(0.0, 1.0, 5); - anEval.SetUVParams(aParams, aParams); - NCollection_Array2 aGrid = anEval.EvaluateGridDN(2, 0); + NCollection_Array2 aGrid = anEval.EvaluateGridDN(aParams, aParams, 2, 0); for (int i = 1; i <= 5; ++i) { @@ -294,9 +286,8 @@ TEST(GeomGridEval_BezierSurfaceTest, DerivativeDN_U1V1) GeomGridEval_BezierSurface anEval(aBezier); TColStd_Array1OfReal aParams = CreateUniformParams(0.0, 1.0, 5); - anEval.SetUVParams(aParams, aParams); - NCollection_Array2 aGrid = anEval.EvaluateGridDN(1, 1); + NCollection_Array2 aGrid = anEval.EvaluateGridDN(aParams, aParams, 1, 1); for (int i = 1; i <= 5; ++i) { @@ -320,10 +311,9 @@ TEST(GeomGridEval_BezierSurfaceTest, DerivativeDN_BeyondDegree) GeomGridEval_BezierSurface anEval(aBezier); TColStd_Array1OfReal aParams = CreateUniformParams(0.0, 1.0, 5); - anEval.SetUVParams(aParams, aParams); // 3rd derivative in U direction (beyond degree 2) should be zero - NCollection_Array2 aGrid = anEval.EvaluateGridDN(3, 0); + NCollection_Array2 aGrid = anEval.EvaluateGridDN(aParams, aParams, 3, 0); for (int i = 1; i <= 5; ++i) { @@ -354,7 +344,6 @@ TEST(GeomGridEval_BezierSurfaceTest, DerivativeDN_RationalSurface) GeomGridEval_BezierSurface anEval(aBezier); TColStd_Array1OfReal aParams = CreateUniformParams(0.0, 1.0, 5); - anEval.SetUVParams(aParams, aParams); // Test DN(1,0), DN(0,1), and DN(1,1) for (int aNU = 0; aNU <= 1; ++aNU) @@ -364,7 +353,7 @@ TEST(GeomGridEval_BezierSurfaceTest, DerivativeDN_RationalSurface) if (aNU + aNV == 0) continue; - NCollection_Array2 aGrid = anEval.EvaluateGridDN(aNU, aNV); + NCollection_Array2 aGrid = anEval.EvaluateGridDN(aParams, aParams, aNU, aNV); for (int i = 1; i <= 5; ++i) { @@ -398,8 +387,7 @@ TEST(GeomGridEval_BezierSurfaceTest, IsolineU_CompareToGeomD0) aUParams.SetValue(1, 0.5); TColStd_Array1OfReal aVParams = CreateUniformParams(0.0, 1.0, 10); - anEval.SetUVParams(aUParams, aVParams); - NCollection_Array2 aGrid = anEval.EvaluateGrid(); + NCollection_Array2 aGrid = anEval.EvaluateGrid(aUParams, aVParams); // Note: RowLength() = V count (columns), ColLength() = U count (rows) EXPECT_EQ(aGrid.RowLength(), 10); @@ -434,8 +422,7 @@ TEST(GeomGridEval_BezierSurfaceTest, IsolineV_CompareToGeomD0) TColStd_Array1OfReal aVParams(1, 1); aVParams.SetValue(1, 0.7); - anEval.SetUVParams(aUParams, aVParams); - NCollection_Array2 aGrid = anEval.EvaluateGrid(); + NCollection_Array2 aGrid = anEval.EvaluateGrid(aUParams, aVParams); // Note: RowLength() = V count (columns), ColLength() = U count (rows) EXPECT_EQ(aGrid.RowLength(), 1); @@ -473,8 +460,7 @@ TEST(GeomGridEval_BezierSurfaceTest, IsolineRational_CompareToGeomD0) aUParams.SetValue(1, 0.3); TColStd_Array1OfReal aVParams = CreateUniformParams(0.0, 1.0, 15); - anEval.SetUVParams(aUParams, aVParams); - NCollection_Array2 aGrid = anEval.EvaluateGrid(); + NCollection_Array2 aGrid = anEval.EvaluateGrid(aUParams, aVParams); for (int j = 1; j <= 15; ++j) { diff --git a/src/ModelingData/TKG3d/GTests/GeomGridEval_Cone_Test.cxx b/src/ModelingData/TKG3d/GTests/GeomGridEval_Cone_Test.cxx index ec8b538781..541792b516 100644 --- a/src/ModelingData/TKG3d/GTests/GeomGridEval_Cone_Test.cxx +++ b/src/ModelingData/TKG3d/GTests/GeomGridEval_Cone_Test.cxx @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -37,7 +38,11 @@ TColStd_Array1OfReal CreateUniformParams(double theFirst, double theLast, int th } } // namespace -TEST(GeomGridEval_ConeTest, BasicEvaluation) +//================================================================================================== +// Grid evaluation tests +//================================================================================================== + +TEST(GeomGridEval_ConeTest, GridBasicEvaluation) { // Cone: SemiAngle=PI/4, Radius=1.0 at origin, Center(0,0,0), Z-axis Handle(Geom_ConicalSurface) aCone = @@ -48,12 +53,8 @@ TEST(GeomGridEval_ConeTest, BasicEvaluation) TColStd_Array1OfReal aUParams = CreateUniformParams(0.0, 2 * M_PI, 9); // Angle TColStd_Array1OfReal aVParams = CreateUniformParams(0.0, 5.0, 6); // Linear param - anEval.SetUVParams(aUParams, aVParams); - EXPECT_EQ(anEval.NbUParams(), 9); - EXPECT_EQ(anEval.NbVParams(), 6); - - NCollection_Array2 aGrid = anEval.EvaluateGrid(); + NCollection_Array2 aGrid = anEval.EvaluateGrid(aUParams, aVParams); EXPECT_EQ(aGrid.RowLength(), 6); EXPECT_EQ(aGrid.ColLength(), 9); @@ -68,7 +69,7 @@ TEST(GeomGridEval_ConeTest, BasicEvaluation) } } -TEST(GeomGridEval_ConeTest, DerivativeD1) +TEST(GeomGridEval_ConeTest, GridDerivativeD1) { Handle(Geom_ConicalSurface) aCone = new Geom_ConicalSurface(gp_Ax3(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), M_PI / 4, 1.0); @@ -76,9 +77,8 @@ TEST(GeomGridEval_ConeTest, DerivativeD1) TColStd_Array1OfReal aUParams = CreateUniformParams(0.0, 2 * M_PI, 9); TColStd_Array1OfReal aVParams = CreateUniformParams(0.0, 5.0, 6); - anEval.SetUVParams(aUParams, aVParams); - NCollection_Array2 aGrid = anEval.EvaluateGridD1(); + NCollection_Array2 aGrid = anEval.EvaluateGridD1(aUParams, aVParams); for (int iU = 1; iU <= 9; ++iU) { @@ -94,7 +94,7 @@ TEST(GeomGridEval_ConeTest, DerivativeD1) } } -TEST(GeomGridEval_ConeTest, DerivativeD2) +TEST(GeomGridEval_ConeTest, GridDerivativeD2) { Handle(Geom_ConicalSurface) aCone = new Geom_ConicalSurface(gp_Ax3(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), M_PI / 4, 1.0); @@ -102,9 +102,8 @@ TEST(GeomGridEval_ConeTest, DerivativeD2) TColStd_Array1OfReal aUParams = CreateUniformParams(0.0, 2 * M_PI, 9); TColStd_Array1OfReal aVParams = CreateUniformParams(0.0, 5.0, 6); - anEval.SetUVParams(aUParams, aVParams); - NCollection_Array2 aGrid = anEval.EvaluateGridD2(); + NCollection_Array2 aGrid = anEval.EvaluateGridD2(aUParams, aVParams); for (int iU = 1; iU <= 9; ++iU) { @@ -122,3 +121,260 @@ TEST(GeomGridEval_ConeTest, DerivativeD2) } } } + +TEST(GeomGridEval_ConeTest, GridDerivativeD3) +{ + Handle(Geom_ConicalSurface) aCone = + new Geom_ConicalSurface(gp_Ax3(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), M_PI / 4, 1.0); + GeomGridEval_Cone anEval(aCone); + + TColStd_Array1OfReal aUParams = CreateUniformParams(0.0, 2 * M_PI, 9); + TColStd_Array1OfReal aVParams = CreateUniformParams(0.0, 5.0, 6); + + NCollection_Array2 aGrid = anEval.EvaluateGridD3(aUParams, aVParams); + + for (int iU = 1; iU <= 9; ++iU) + { + for (int iV = 1; iV <= 6; ++iV) + { + gp_Pnt aPnt; + gp_Vec aD1U, aD1V, aD2U, aD2V, aD2UV, aD3U, aD3V, aD3UUV, aD3UVV; + aCone->D3(aUParams.Value(iU), + aVParams.Value(iV), + aPnt, + aD1U, + aD1V, + aD2U, + aD2V, + aD2UV, + aD3U, + aD3V, + aD3UUV, + aD3UVV); + EXPECT_NEAR(aGrid.Value(iU, iV).Point.Distance(aPnt), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aGrid.Value(iU, iV).D1U - aD1U).Magnitude(), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aGrid.Value(iU, iV).D1V - aD1V).Magnitude(), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aGrid.Value(iU, iV).D2U - aD2U).Magnitude(), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aGrid.Value(iU, iV).D2V - aD2V).Magnitude(), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aGrid.Value(iU, iV).D2UV - aD2UV).Magnitude(), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aGrid.Value(iU, iV).D3U - aD3U).Magnitude(), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aGrid.Value(iU, iV).D3V - aD3V).Magnitude(), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aGrid.Value(iU, iV).D3UUV - aD3UUV).Magnitude(), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aGrid.Value(iU, iV).D3UVV - aD3UVV).Magnitude(), 0.0, THE_TOLERANCE); + } + } +} + +TEST(GeomGridEval_ConeTest, GridDerivativeDN) +{ + Handle(Geom_ConicalSurface) aCone = + new Geom_ConicalSurface(gp_Ax3(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), M_PI / 4, 1.0); + GeomGridEval_Cone anEval(aCone); + + TColStd_Array1OfReal aUParams = CreateUniformParams(0.0, 2 * M_PI, 5); + TColStd_Array1OfReal aVParams = CreateUniformParams(0.0, 5.0, 4); + + // Test D4U (4th derivative in U) + NCollection_Array2 aD4U = anEval.EvaluateGridDN(aUParams, aVParams, 4, 0); + for (int iU = 1; iU <= 5; ++iU) + { + for (int iV = 1; iV <= 4; ++iV) + { + gp_Vec aExpected = aCone->DN(aUParams.Value(iU), aVParams.Value(iV), 4, 0); + EXPECT_NEAR((aD4U.Value(iU, iV) - aExpected).Magnitude(), 0.0, THE_TOLERANCE); + } + } +} + +//================================================================================================== +// Points evaluation tests +//================================================================================================== + +TEST(GeomGridEval_ConeTest, PointsBasicEvaluation) +{ + Handle(Geom_ConicalSurface) aCone = + new Geom_ConicalSurface(gp_Ax3(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), M_PI / 4, 1.0); + GeomGridEval_Cone anEval(aCone); + + // Create arbitrary UV pairs + NCollection_Array1 aUVPairs(1, 10); + aUVPairs.SetValue(1, gp_Pnt2d(0.0, 0.0)); + aUVPairs.SetValue(2, gp_Pnt2d(M_PI / 4, 1.0)); + aUVPairs.SetValue(3, gp_Pnt2d(M_PI / 2, 2.0)); + aUVPairs.SetValue(4, gp_Pnt2d(M_PI, 3.0)); + aUVPairs.SetValue(5, gp_Pnt2d(3 * M_PI / 2, 4.0)); + aUVPairs.SetValue(6, gp_Pnt2d(2 * M_PI, 5.0)); + aUVPairs.SetValue(7, gp_Pnt2d(0.5, 0.5)); + aUVPairs.SetValue(8, gp_Pnt2d(1.5, 1.5)); + aUVPairs.SetValue(9, gp_Pnt2d(2.5, 2.5)); + aUVPairs.SetValue(10, gp_Pnt2d(3.5, 3.5)); + + NCollection_Array1 aPoints = anEval.EvaluatePoints(aUVPairs); + EXPECT_EQ(aPoints.Length(), 10); + + for (int i = 1; i <= 10; ++i) + { + const gp_Pnt2d& aUV = aUVPairs.Value(i); + gp_Pnt aExpected = aCone->Value(aUV.X(), aUV.Y()); + EXPECT_NEAR(aPoints.Value(i).Distance(aExpected), 0.0, THE_TOLERANCE); + } +} + +TEST(GeomGridEval_ConeTest, PointsDerivativeD1) +{ + Handle(Geom_ConicalSurface) aCone = + new Geom_ConicalSurface(gp_Ax3(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), M_PI / 4, 1.0); + GeomGridEval_Cone anEval(aCone); + + NCollection_Array1 aUVPairs(1, 5); + aUVPairs.SetValue(1, gp_Pnt2d(0.0, 0.0)); + aUVPairs.SetValue(2, gp_Pnt2d(M_PI / 4, 1.0)); + aUVPairs.SetValue(3, gp_Pnt2d(M_PI / 2, 2.0)); + aUVPairs.SetValue(4, gp_Pnt2d(M_PI, 3.0)); + aUVPairs.SetValue(5, gp_Pnt2d(3 * M_PI / 2, 4.0)); + + NCollection_Array1 aResults = anEval.EvaluatePointsD1(aUVPairs); + + for (int i = 1; i <= 5; ++i) + { + const gp_Pnt2d& aUV = aUVPairs.Value(i); + gp_Pnt aPnt; + gp_Vec aD1U, aD1V; + aCone->D1(aUV.X(), aUV.Y(), aPnt, aD1U, aD1V); + EXPECT_NEAR(aResults.Value(i).Point.Distance(aPnt), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aResults.Value(i).D1U - aD1U).Magnitude(), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aResults.Value(i).D1V - aD1V).Magnitude(), 0.0, THE_TOLERANCE); + } +} + +TEST(GeomGridEval_ConeTest, PointsDerivativeD2) +{ + Handle(Geom_ConicalSurface) aCone = + new Geom_ConicalSurface(gp_Ax3(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), M_PI / 4, 1.0); + GeomGridEval_Cone anEval(aCone); + + NCollection_Array1 aUVPairs(1, 5); + aUVPairs.SetValue(1, gp_Pnt2d(0.0, 0.0)); + aUVPairs.SetValue(2, gp_Pnt2d(M_PI / 4, 1.0)); + aUVPairs.SetValue(3, gp_Pnt2d(M_PI / 2, 2.0)); + aUVPairs.SetValue(4, gp_Pnt2d(M_PI, 3.0)); + aUVPairs.SetValue(5, gp_Pnt2d(3 * M_PI / 2, 4.0)); + + NCollection_Array1 aResults = anEval.EvaluatePointsD2(aUVPairs); + + for (int i = 1; i <= 5; ++i) + { + const gp_Pnt2d& aUV = aUVPairs.Value(i); + gp_Pnt aPnt; + gp_Vec aD1U, aD1V, aD2U, aD2V, aD2UV; + aCone->D2(aUV.X(), aUV.Y(), aPnt, aD1U, aD1V, aD2U, aD2V, aD2UV); + EXPECT_NEAR(aResults.Value(i).Point.Distance(aPnt), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aResults.Value(i).D1U - aD1U).Magnitude(), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aResults.Value(i).D1V - aD1V).Magnitude(), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aResults.Value(i).D2U - aD2U).Magnitude(), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aResults.Value(i).D2V - aD2V).Magnitude(), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aResults.Value(i).D2UV - aD2UV).Magnitude(), 0.0, THE_TOLERANCE); + } +} + +TEST(GeomGridEval_ConeTest, PointsDerivativeD3) +{ + Handle(Geom_ConicalSurface) aCone = + new Geom_ConicalSurface(gp_Ax3(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), M_PI / 4, 1.0); + GeomGridEval_Cone anEval(aCone); + + NCollection_Array1 aUVPairs(1, 5); + aUVPairs.SetValue(1, gp_Pnt2d(0.0, 0.0)); + aUVPairs.SetValue(2, gp_Pnt2d(M_PI / 4, 1.0)); + aUVPairs.SetValue(3, gp_Pnt2d(M_PI / 2, 2.0)); + aUVPairs.SetValue(4, gp_Pnt2d(M_PI, 3.0)); + aUVPairs.SetValue(5, gp_Pnt2d(3 * M_PI / 2, 4.0)); + + NCollection_Array1 aResults = anEval.EvaluatePointsD3(aUVPairs); + + for (int i = 1; i <= 5; ++i) + { + const gp_Pnt2d& aUV = aUVPairs.Value(i); + gp_Pnt aPnt; + gp_Vec aD1U, aD1V, aD2U, aD2V, aD2UV, aD3U, aD3V, aD3UUV, aD3UVV; + aCone->D3(aUV.X(), aUV.Y(), aPnt, aD1U, aD1V, aD2U, aD2V, aD2UV, aD3U, aD3V, aD3UUV, aD3UVV); + EXPECT_NEAR(aResults.Value(i).Point.Distance(aPnt), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aResults.Value(i).D1U - aD1U).Magnitude(), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aResults.Value(i).D1V - aD1V).Magnitude(), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aResults.Value(i).D2U - aD2U).Magnitude(), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aResults.Value(i).D2V - aD2V).Magnitude(), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aResults.Value(i).D2UV - aD2UV).Magnitude(), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aResults.Value(i).D3U - aD3U).Magnitude(), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aResults.Value(i).D3V - aD3V).Magnitude(), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aResults.Value(i).D3UUV - aD3UUV).Magnitude(), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aResults.Value(i).D3UVV - aD3UVV).Magnitude(), 0.0, THE_TOLERANCE); + } +} + +TEST(GeomGridEval_ConeTest, PointsDerivativeDN) +{ + Handle(Geom_ConicalSurface) aCone = + new Geom_ConicalSurface(gp_Ax3(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), M_PI / 4, 1.0); + GeomGridEval_Cone anEval(aCone); + + NCollection_Array1 aUVPairs(1, 5); + aUVPairs.SetValue(1, gp_Pnt2d(0.0, 0.0)); + aUVPairs.SetValue(2, gp_Pnt2d(M_PI / 4, 1.0)); + aUVPairs.SetValue(3, gp_Pnt2d(M_PI / 2, 2.0)); + aUVPairs.SetValue(4, gp_Pnt2d(M_PI, 3.0)); + aUVPairs.SetValue(5, gp_Pnt2d(3 * M_PI / 2, 4.0)); + + // Test D4U + NCollection_Array1 aD4U = anEval.EvaluatePointsDN(aUVPairs, 4, 0); + for (int i = 1; i <= 5; ++i) + { + const gp_Pnt2d& aUV = aUVPairs.Value(i); + gp_Vec aExpected = aCone->DN(aUV.X(), aUV.Y(), 4, 0); + EXPECT_NEAR((aD4U.Value(i) - aExpected).Magnitude(), 0.0, THE_TOLERANCE); + } +} + +TEST(GeomGridEval_ConeTest, PointsTransformedCone) +{ + // Cone with offset center and tilted axis + gp_Ax3 anAxis(gp_Pnt(5, 3, 2), gp_Dir(1, 1, 1)); + Handle(Geom_ConicalSurface) aCone = new Geom_ConicalSurface(anAxis, M_PI / 6, 2.0); + GeomGridEval_Cone anEval(aCone); + + NCollection_Array1 aUVPairs(1, 8); + for (int i = 1; i <= 8; ++i) + { + aUVPairs.SetValue(i, gp_Pnt2d((i - 1) * M_PI / 4, (i - 1) * 0.5)); + } + + NCollection_Array1 aPoints = anEval.EvaluatePoints(aUVPairs); + + for (int i = 1; i <= 8; ++i) + { + const gp_Pnt2d& aUV = aUVPairs.Value(i); + gp_Pnt aExpected = aCone->Value(aUV.X(), aUV.Y()); + EXPECT_NEAR(aPoints.Value(i).Distance(aExpected), 0.0, THE_TOLERANCE); + } +} + +TEST(GeomGridEval_ConeTest, PointsAtApex) +{ + // Test evaluation at cone apex (V=0 when RefRadius=0) + Handle(Geom_ConicalSurface) aCone = + new Geom_ConicalSurface(gp_Ax3(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), M_PI / 4, 0.0); + GeomGridEval_Cone anEval(aCone); + + NCollection_Array1 aUVPairs(1, 4); + aUVPairs.SetValue(1, gp_Pnt2d(0.0, 0.0)); + aUVPairs.SetValue(2, gp_Pnt2d(M_PI / 2, 0.0)); + aUVPairs.SetValue(3, gp_Pnt2d(M_PI, 0.0)); + aUVPairs.SetValue(4, gp_Pnt2d(3 * M_PI / 2, 0.0)); + + NCollection_Array1 aPoints = anEval.EvaluatePoints(aUVPairs); + + // All points at apex should be the same (origin) + for (int i = 1; i <= 4; ++i) + { + EXPECT_NEAR(aPoints.Value(i).Distance(gp_Pnt(0, 0, 0)), 0.0, THE_TOLERANCE); + } +} diff --git a/src/ModelingData/TKG3d/GTests/GeomGridEval_Curve_Test.cxx b/src/ModelingData/TKG3d/GTests/GeomGridEval_Curve_Test.cxx index 4a1fb01d52..b3650180a4 100644 --- a/src/ModelingData/TKG3d/GTests/GeomGridEval_Curve_Test.cxx +++ b/src/ModelingData/TKG3d/GTests/GeomGridEval_Curve_Test.cxx @@ -85,10 +85,8 @@ TEST(GeomGridEval_LineTest, BasicEvaluation) EXPECT_FALSE(anEval.Geometry().IsNull()); TColStd_Array1OfReal aParams = CreateUniformParams(0.0, 10.0, 11); - anEval.SetParams(aParams); - EXPECT_EQ(anEval.NbParams(), 11); - NCollection_Array1 aGrid = anEval.EvaluateGrid(); + NCollection_Array1 aGrid = anEval.EvaluateGrid(aParams); EXPECT_EQ(aGrid.Size(), 11); // Verify points @@ -110,9 +108,8 @@ TEST(GeomGridEval_LineTest, NonOriginLine) GeomGridEval_Line anEval(aGeomLine); TColStd_Array1OfReal aParams = CreateUniformParams(0.0, 5.0, 6); - anEval.SetParams(aParams); - NCollection_Array1 aGrid = anEval.EvaluateGrid(); + NCollection_Array1 aGrid = anEval.EvaluateGrid(aParams); // Verify first and last point EXPECT_NEAR(aGrid.Value(1).Distance(gp_Pnt(1, 2, 3)), 0.0, THE_TOLERANCE); @@ -142,9 +139,8 @@ TEST(GeomGridEval_CircleTest, BasicEvaluation) aParams.SetValue(3, M_PI); aParams.SetValue(4, 3 * M_PI / 2); aParams.SetValue(5, 2 * M_PI); - anEval.SetParams(aParams); - NCollection_Array1 aGrid = anEval.EvaluateGrid(); + NCollection_Array1 aGrid = anEval.EvaluateGrid(aParams); // u=0: (2, 0, 0) EXPECT_NEAR(aGrid.Value(1).X(), 2.0, THE_TOLERANCE); @@ -175,9 +171,8 @@ TEST(GeomGridEval_CircleTest, NonStandardCircle) GeomGridEval_Circle anEval(aGeomCircle); TColStd_Array1OfReal aParams = CreateUniformParams(0.0, 2 * M_PI, 9); - anEval.SetParams(aParams); - NCollection_Array1 aGrid = anEval.EvaluateGrid(); + NCollection_Array1 aGrid = anEval.EvaluateGrid(aParams); // All points should be at distance 3 from center (1, 0, 0) const gp_Pnt aCenter(1, 0, 0); @@ -200,9 +195,8 @@ TEST(GeomGridEval_BSplineCurveTest, BasicEvaluation) EXPECT_FALSE(anEval.Geometry().IsNull()); TColStd_Array1OfReal aParams = CreateUniformParams(0.0, 1.0, 11); - anEval.SetParams(aParams); - NCollection_Array1 aGrid = anEval.EvaluateGrid(); + NCollection_Array1 aGrid = anEval.EvaluateGrid(aParams); EXPECT_EQ(aGrid.Size(), 11); // Verify against direct evaluation @@ -222,9 +216,8 @@ TEST(GeomGridEval_BSplineCurveTest, EndpointsMatch) TColStd_Array1OfReal aParams(1, 2); aParams.SetValue(1, 0.0); aParams.SetValue(2, 1.0); - anEval.SetParams(aParams); - NCollection_Array1 aGrid = anEval.EvaluateGrid(); + NCollection_Array1 aGrid = anEval.EvaluateGrid(aParams); // First point should match first pole EXPECT_NEAR(aGrid.Value(1).Distance(gp_Pnt(0, 0, 0)), 0.0, THE_TOLERANCE); @@ -246,9 +239,8 @@ TEST(GeomGridEval_OtherCurveTest, EllipseFallback) GeomGridEval_OtherCurve anEval(anAdaptor); TColStd_Array1OfReal aParams = CreateUniformParams(0.0, 2 * M_PI, 9); - anEval.SetParams(aParams); - NCollection_Array1 aGrid = anEval.EvaluateGrid(); + NCollection_Array1 aGrid = anEval.EvaluateGrid(aParams); // Verify against direct evaluation for (int i = 1; i <= 9; ++i) @@ -273,9 +265,8 @@ TEST(GeomGridEval_CurveTest, LineDispatch) EXPECT_EQ(anEval.GetType(), GeomAbs_Line); TColStd_Array1OfReal aParams = CreateUniformParams(0.0, 10.0, 11); - anEval.SetParams(aParams); - NCollection_Array1 aGrid = anEval.EvaluateGrid(); + NCollection_Array1 aGrid = anEval.EvaluateGrid(aParams); EXPECT_EQ(aGrid.Size(), 11); // Verify against direct evaluation @@ -297,9 +288,8 @@ TEST(GeomGridEval_CurveTest, CircleDispatch) EXPECT_EQ(anEval.GetType(), GeomAbs_Circle); TColStd_Array1OfReal aParams = CreateUniformParams(0.0, 2 * M_PI, 17); - anEval.SetParams(aParams); - NCollection_Array1 aGrid = anEval.EvaluateGrid(); + NCollection_Array1 aGrid = anEval.EvaluateGrid(aParams); // Verify against direct evaluation for (int i = 1; i <= 17; ++i) @@ -320,9 +310,8 @@ TEST(GeomGridEval_CurveTest, BSplineDispatch) EXPECT_EQ(anEval.GetType(), GeomAbs_BSplineCurve); TColStd_Array1OfReal aParams = CreateUniformParams(0.0, 1.0, 21); - anEval.SetParams(aParams); - NCollection_Array1 aGrid = anEval.EvaluateGrid(); + NCollection_Array1 aGrid = anEval.EvaluateGrid(aParams); // Verify against direct evaluation for (int i = 1; i <= 21; ++i) @@ -344,9 +333,8 @@ TEST(GeomGridEval_CurveTest, EllipseDispatch) EXPECT_EQ(anEval.GetType(), GeomAbs_Ellipse); TColStd_Array1OfReal aParams = CreateUniformParams(0.0, 2 * M_PI, 13); - anEval.SetParams(aParams); - NCollection_Array1 aGrid = anEval.EvaluateGrid(); + NCollection_Array1 aGrid = anEval.EvaluateGrid(aParams); // Verify against direct evaluation for (int i = 1; i <= 13; ++i) @@ -368,9 +356,8 @@ TEST(GeomGridEval_CurveTest, HyperbolaDispatch) EXPECT_EQ(anEval.GetType(), GeomAbs_Hyperbola); TColStd_Array1OfReal aParams = CreateUniformParams(-2.0, 2.0, 11); - anEval.SetParams(aParams); - NCollection_Array1 aGrid = anEval.EvaluateGrid(); + NCollection_Array1 aGrid = anEval.EvaluateGrid(aParams); // Verify against direct evaluation for (int i = 1; i <= 11; ++i) @@ -391,9 +378,8 @@ TEST(GeomGridEval_CurveTest, ParabolaDispatch) EXPECT_EQ(anEval.GetType(), GeomAbs_Parabola); TColStd_Array1OfReal aParams = CreateUniformParams(-2.0, 2.0, 11); - anEval.SetParams(aParams); - NCollection_Array1 aGrid = anEval.EvaluateGrid(); + NCollection_Array1 aGrid = anEval.EvaluateGrid(aParams); // Verify against direct evaluation for (int i = 1; i <= 11; ++i) @@ -420,9 +406,8 @@ TEST(GeomGridEval_CurveTest, BezierCurveDispatch) EXPECT_EQ(anEval.GetType(), GeomAbs_BezierCurve); TColStd_Array1OfReal aParams = CreateUniformParams(0.0, 1.0, 11); - anEval.SetParams(aParams); - NCollection_Array1 aGrid = anEval.EvaluateGrid(); + NCollection_Array1 aGrid = anEval.EvaluateGrid(aParams); // Verify against direct evaluation for (int i = 1; i <= 11; ++i) @@ -445,9 +430,8 @@ TEST(GeomGridEval_CurveTest, OffsetCurveFallbackDispatch) EXPECT_EQ(anEval.GetType(), GeomAbs_OffsetCurve); TColStd_Array1OfReal aParams = CreateUniformParams(0.0, 5.0, 6); - anEval.SetParams(aParams); - NCollection_Array1 aGrid = anEval.EvaluateGrid(); + NCollection_Array1 aGrid = anEval.EvaluateGrid(aParams); // Verify against direct evaluation for (int i = 1; i <= 6; ++i) @@ -467,9 +451,8 @@ TEST(GeomGridEval_CurveTest, DirectHandleInit) EXPECT_EQ(anEval.GetType(), GeomAbs_Line); TColStd_Array1OfReal aParams = CreateUniformParams(0.0, 10.0, 11); - anEval.SetParams(aParams); - NCollection_Array1 aGrid = anEval.EvaluateGrid(); + NCollection_Array1 aGrid = anEval.EvaluateGrid(aParams); EXPECT_EQ(aGrid.Size(), 11); EXPECT_NEAR(aGrid.Value(1).X(), 0.0, THE_TOLERANCE); } @@ -478,9 +461,9 @@ TEST(GeomGridEval_CurveTest, UninitializedState) { GeomGridEval_Curve anEval; EXPECT_FALSE(anEval.IsInitialized()); - EXPECT_EQ(anEval.NbParams(), 0); - NCollection_Array1 aGrid = anEval.EvaluateGrid(); + TColStd_Array1OfReal aEmptyParams; + NCollection_Array1 aGrid = anEval.EvaluateGrid(aEmptyParams); EXPECT_TRUE(aGrid.IsEmpty()); } @@ -492,10 +475,10 @@ TEST(GeomGridEval_CurveTest, EmptyParams) GeomGridEval_Curve anEval; anEval.Initialize(anAdaptor); EXPECT_TRUE(anEval.IsInitialized()); - EXPECT_EQ(anEval.NbParams(), 0); - // EvaluateGrid without setting params should return empty - NCollection_Array1 aGrid = anEval.EvaluateGrid(); + // EvaluateGrid with empty params should return empty + TColStd_Array1OfReal aEmptyParams; + NCollection_Array1 aGrid = anEval.EvaluateGrid(aEmptyParams); EXPECT_TRUE(aGrid.IsEmpty()); } @@ -531,9 +514,8 @@ TEST(GeomGridEval_BSplineCurveTest, RationalBSpline) GeomGridEval_BSplineCurve anEval(aCurve); TColStd_Array1OfReal aParams = CreateUniformParams(0.0, 1.0, 21); - anEval.SetParams(aParams); - NCollection_Array1 aGrid = anEval.EvaluateGrid(); + NCollection_Array1 aGrid = anEval.EvaluateGrid(aParams); EXPECT_EQ(aGrid.Size(), 21); // Verify against direct evaluation @@ -570,9 +552,8 @@ TEST(GeomGridEval_BSplineCurveTest, MultiSpanBSpline) GeomGridEval_BSplineCurve anEval(aCurve); TColStd_Array1OfReal aParams = CreateUniformParams(0.0, 1.0, 31); - anEval.SetParams(aParams); - NCollection_Array1 aGrid = anEval.EvaluateGrid(); + NCollection_Array1 aGrid = anEval.EvaluateGrid(aParams); // Verify against direct evaluation - should match exactly for (int i = 1; i <= 31; ++i) @@ -605,9 +586,8 @@ TEST(GeomGridEval_BSplineCurveTest, HighDegree) GeomGridEval_BSplineCurve anEval(aCurve); TColStd_Array1OfReal aParams = CreateUniformParams(0.0, 1.0, 51); - anEval.SetParams(aParams); - NCollection_Array1 aGrid = anEval.EvaluateGrid(); + NCollection_Array1 aGrid = anEval.EvaluateGrid(aParams); // Verify against direct evaluation for (int i = 1; i <= 51; ++i) @@ -628,9 +608,8 @@ TEST(GeomGridEval_LineTest, DerivativeD1) GeomGridEval_Line anEval(aGeomLine); TColStd_Array1OfReal aParams = CreateUniformParams(0.0, 5.0, 6); - anEval.SetParams(aParams); - NCollection_Array1 aGrid = anEval.EvaluateGridD1(); + NCollection_Array1 aGrid = anEval.EvaluateGridD1(aParams); EXPECT_EQ(aGrid.Size(), 6); // For a line, D1 is constant (the direction vector) @@ -650,10 +629,9 @@ TEST(GeomGridEval_LineTest, DerivativeD2D3) GeomGridEval_Line anEval(aGeomLine); TColStd_Array1OfReal aParams = CreateUniformParams(0.0, 5.0, 6); - anEval.SetParams(aParams); - NCollection_Array1 aGridD2 = anEval.EvaluateGridD2(); - NCollection_Array1 aGridD3 = anEval.EvaluateGridD3(); + NCollection_Array1 aGridD2 = anEval.EvaluateGridD2(aParams); + NCollection_Array1 aGridD3 = anEval.EvaluateGridD3(aParams); // For a line, D2 and D3 are zero for (int i = 1; i <= 6; ++i) @@ -675,9 +653,8 @@ TEST(GeomGridEval_CircleTest, DerivativeD1) aParams.SetValue(3, M_PI); aParams.SetValue(4, 3 * M_PI / 2); aParams.SetValue(5, 2 * M_PI); - anEval.SetParams(aParams); - NCollection_Array1 aGrid = anEval.EvaluateGridD1(); + NCollection_Array1 aGrid = anEval.EvaluateGridD1(aParams); // Verify D1 against direct evaluation for (int i = 1; i <= 5; ++i) @@ -696,9 +673,8 @@ TEST(GeomGridEval_CircleTest, DerivativeD2) GeomGridEval_Circle anEval(aGeomCircle); TColStd_Array1OfReal aParams = CreateUniformParams(0.0, 2 * M_PI, 9); - anEval.SetParams(aParams); - NCollection_Array1 aGrid = anEval.EvaluateGridD2(); + NCollection_Array1 aGrid = anEval.EvaluateGridD2(aParams); // Verify D2 against direct evaluation for (int i = 1; i <= 9; ++i) @@ -718,9 +694,8 @@ TEST(GeomGridEval_BSplineCurveTest, DerivativeD1) GeomGridEval_BSplineCurve anEval(aCurve); TColStd_Array1OfReal aParams = CreateUniformParams(0.0, 1.0, 11); - anEval.SetParams(aParams); - NCollection_Array1 aGrid = anEval.EvaluateGridD1(); + NCollection_Array1 aGrid = anEval.EvaluateGridD1(aParams); // Verify against direct evaluation for (int i = 1; i <= 11; ++i) @@ -739,9 +714,8 @@ TEST(GeomGridEval_BSplineCurveTest, DerivativeD2) GeomGridEval_BSplineCurve anEval(aCurve); TColStd_Array1OfReal aParams = CreateUniformParams(0.0, 1.0, 11); - anEval.SetParams(aParams); - NCollection_Array1 aGrid = anEval.EvaluateGridD2(); + NCollection_Array1 aGrid = anEval.EvaluateGridD2(aParams); // Verify against direct evaluation for (int i = 1; i <= 11; ++i) @@ -761,9 +735,8 @@ TEST(GeomGridEval_BSplineCurveTest, DerivativeD3) GeomGridEval_BSplineCurve anEval(aCurve); TColStd_Array1OfReal aParams = CreateUniformParams(0.0, 1.0, 11); - anEval.SetParams(aParams); - NCollection_Array1 aGrid = anEval.EvaluateGridD3(); + NCollection_Array1 aGrid = anEval.EvaluateGridD3(aParams); // Verify against direct evaluation for (int i = 1; i <= 11; ++i) @@ -787,9 +760,8 @@ TEST(GeomGridEval_CurveTest, UnifiedDerivativeD1) anEval.Initialize(anAdaptor); TColStd_Array1OfReal aParams = CreateUniformParams(0.0, 2 * M_PI, 9); - anEval.SetParams(aParams); - NCollection_Array1 aGrid = anEval.EvaluateGridD1(); + NCollection_Array1 aGrid = anEval.EvaluateGridD1(aParams); // Verify against direct evaluation for (int i = 1; i <= 9; ++i) @@ -811,9 +783,8 @@ TEST(GeomGridEval_CurveTest, UnifiedDerivativeD2) anEval.Initialize(anAdaptor); TColStd_Array1OfReal aParams = CreateUniformParams(0.0, 1.0, 11); - anEval.SetParams(aParams); - NCollection_Array1 aGrid = anEval.EvaluateGridD2(); + NCollection_Array1 aGrid = anEval.EvaluateGridD2(aParams); // Verify against direct evaluation for (int i = 1; i <= 11; ++i) @@ -837,9 +808,8 @@ TEST(GeomGridEval_CircleTest, DerivativeD3) GeomGridEval_Circle anEval(aGeomCircle); TColStd_Array1OfReal aParams = CreateUniformParams(0.0, 2 * M_PI, 9); - anEval.SetParams(aParams); - NCollection_Array1 aGrid = anEval.EvaluateGridD3(); + NCollection_Array1 aGrid = anEval.EvaluateGridD3(aParams); // Verify D3 against direct evaluation for (int i = 1; i <= 9; ++i) @@ -864,9 +834,8 @@ TEST(GeomGridEval_OffsetCurveTest, DerivativeD3) GeomGridEval_OtherCurve anEval(anAdaptor); TColStd_Array1OfReal aParams = CreateUniformParams(0.0, 2 * M_PI, 9); - anEval.SetParams(aParams); - NCollection_Array1 aGrid = anEval.EvaluateGridD3(); + NCollection_Array1 aGrid = anEval.EvaluateGridD3(aParams); // Verify D3 against adaptor evaluation for (int i = 1; i <= 9; ++i) @@ -893,9 +862,8 @@ TEST(GeomGridEval_CurveTest, OffsetCurveDerivativeD3) EXPECT_EQ(anEval.GetType(), GeomAbs_OffsetCurve); TColStd_Array1OfReal aParams = CreateUniformParams(0.0, 5.0, 6); - anEval.SetParams(aParams); - NCollection_Array1 aGrid = anEval.EvaluateGridD3(); + NCollection_Array1 aGrid = anEval.EvaluateGridD3(aParams); // Verify D3 against adaptor evaluation for (int i = 1; i <= 6; ++i) @@ -919,9 +887,8 @@ TEST(GeomGridEval_CurveTest, UnifiedDerivativeD3) anEval.Initialize(anAdaptor); TColStd_Array1OfReal aParams = CreateUniformParams(0.0, 1.0, 11); - anEval.SetParams(aParams); - NCollection_Array1 aGrid = anEval.EvaluateGridD3(); + NCollection_Array1 aGrid = anEval.EvaluateGridD3(aParams); // Verify against direct evaluation for (int i = 1; i <= 11; ++i) @@ -946,9 +913,8 @@ TEST(GeomGridEval_BSplineCurveTest, DerivativeDN_Order1) GeomGridEval_BSplineCurve anEval(aCurve); TColStd_Array1OfReal aParams = CreateUniformParams(0.0, 1.0, 11); - anEval.SetParams(aParams); - NCollection_Array1 aGrid = anEval.EvaluateGridDN(1); + NCollection_Array1 aGrid = anEval.EvaluateGridDN(aParams, 1); for (int i = 1; i <= 11; ++i) { @@ -963,9 +929,8 @@ TEST(GeomGridEval_BSplineCurveTest, DerivativeDN_Order2) GeomGridEval_BSplineCurve anEval(aCurve); TColStd_Array1OfReal aParams = CreateUniformParams(0.0, 1.0, 11); - anEval.SetParams(aParams); - NCollection_Array1 aGrid = anEval.EvaluateGridDN(2); + NCollection_Array1 aGrid = anEval.EvaluateGridDN(aParams, 2); for (int i = 1; i <= 11; ++i) { @@ -980,9 +945,8 @@ TEST(GeomGridEval_BSplineCurveTest, DerivativeDN_Order3) GeomGridEval_BSplineCurve anEval(aCurve); TColStd_Array1OfReal aParams = CreateUniformParams(0.0, 1.0, 11); - anEval.SetParams(aParams); - NCollection_Array1 aGrid = anEval.EvaluateGridDN(3); + NCollection_Array1 aGrid = anEval.EvaluateGridDN(aParams, 3); for (int i = 1; i <= 11; ++i) { @@ -998,9 +962,8 @@ TEST(GeomGridEval_BSplineCurveTest, DerivativeDN_BeyondDegree) GeomGridEval_BSplineCurve anEval(aCurve); TColStd_Array1OfReal aParams = CreateUniformParams(0.0, 1.0, 11); - anEval.SetParams(aParams); - NCollection_Array1 aGrid = anEval.EvaluateGridDN(4); + NCollection_Array1 aGrid = anEval.EvaluateGridDN(aParams, 4); for (int i = 1; i <= 11; ++i) { @@ -1035,12 +998,11 @@ TEST(GeomGridEval_BSplineCurveTest, DerivativeDN_RationalCurve) GeomGridEval_BSplineCurve anEval(aCurve); TColStd_Array1OfReal aParams = CreateUniformParams(0.0, 1.0, 21); - anEval.SetParams(aParams); // Test DN for orders 1, 2, 3 for (int aOrder = 1; aOrder <= 3; ++aOrder) { - NCollection_Array1 aGrid = anEval.EvaluateGridDN(aOrder); + NCollection_Array1 aGrid = anEval.EvaluateGridDN(aParams, aOrder); for (int i = 1; i <= 21; ++i) { @@ -1074,12 +1036,11 @@ TEST(GeomGridEval_BSplineCurveTest, DerivativeDN_MultiSpan) GeomGridEval_BSplineCurve anEval(aCurve); TColStd_Array1OfReal aParams = CreateUniformParams(0.0, 1.0, 31); - anEval.SetParams(aParams); // Test DN for orders 1, 2, 3 for (int aOrder = 1; aOrder <= 3; ++aOrder) { - NCollection_Array1 aGrid = anEval.EvaluateGridDN(aOrder); + NCollection_Array1 aGrid = anEval.EvaluateGridDN(aParams, aOrder); for (int i = 1; i <= 31; ++i) { diff --git a/src/ModelingData/TKG3d/GTests/GeomGridEval_Cylinder_Test.cxx b/src/ModelingData/TKG3d/GTests/GeomGridEval_Cylinder_Test.cxx index 90d5d77c39..0852d48854 100644 --- a/src/ModelingData/TKG3d/GTests/GeomGridEval_Cylinder_Test.cxx +++ b/src/ModelingData/TKG3d/GTests/GeomGridEval_Cylinder_Test.cxx @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -37,7 +38,11 @@ TColStd_Array1OfReal CreateUniformParams(double theFirst, double theLast, int th } } // namespace -TEST(GeomGridEval_CylinderTest, BasicEvaluation) +//================================================================================================== +// Grid evaluation tests +//================================================================================================== + +TEST(GeomGridEval_CylinderTest, GridBasicEvaluation) { // Cylinder radius 2 along Z axis Handle(Geom_CylindricalSurface) aCyl = @@ -48,12 +53,8 @@ TEST(GeomGridEval_CylinderTest, BasicEvaluation) TColStd_Array1OfReal aUParams = CreateUniformParams(0.0, 2 * M_PI, 9); // Angle TColStd_Array1OfReal aVParams = CreateUniformParams(0.0, 5.0, 6); // Height - anEval.SetUVParams(aUParams, aVParams); - EXPECT_EQ(anEval.NbUParams(), 9); - EXPECT_EQ(anEval.NbVParams(), 6); - - NCollection_Array2 aGrid = anEval.EvaluateGrid(); + NCollection_Array2 aGrid = anEval.EvaluateGrid(aUParams, aVParams); EXPECT_EQ(aGrid.RowLength(), 6); EXPECT_EQ(aGrid.ColLength(), 9); @@ -68,7 +69,7 @@ TEST(GeomGridEval_CylinderTest, BasicEvaluation) } } -TEST(GeomGridEval_CylinderTest, DerivativeD1) +TEST(GeomGridEval_CylinderTest, GridDerivativeD1) { Handle(Geom_CylindricalSurface) aCyl = new Geom_CylindricalSurface(gp_Ax3(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), 2.0); @@ -76,9 +77,8 @@ TEST(GeomGridEval_CylinderTest, DerivativeD1) TColStd_Array1OfReal aUParams = CreateUniformParams(0.0, 2 * M_PI, 9); TColStd_Array1OfReal aVParams = CreateUniformParams(0.0, 5.0, 6); - anEval.SetUVParams(aUParams, aVParams); - NCollection_Array2 aGrid = anEval.EvaluateGridD1(); + NCollection_Array2 aGrid = anEval.EvaluateGridD1(aUParams, aVParams); for (int iU = 1; iU <= 9; ++iU) { @@ -94,7 +94,7 @@ TEST(GeomGridEval_CylinderTest, DerivativeD1) } } -TEST(GeomGridEval_CylinderTest, DerivativeD2) +TEST(GeomGridEval_CylinderTest, GridDerivativeD2) { Handle(Geom_CylindricalSurface) aCyl = new Geom_CylindricalSurface(gp_Ax3(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), 2.0); @@ -102,9 +102,8 @@ TEST(GeomGridEval_CylinderTest, DerivativeD2) TColStd_Array1OfReal aUParams = CreateUniformParams(0.0, 2 * M_PI, 9); TColStd_Array1OfReal aVParams = CreateUniformParams(0.0, 5.0, 6); - anEval.SetUVParams(aUParams, aVParams); - NCollection_Array2 aGrid = anEval.EvaluateGridD2(); + NCollection_Array2 aGrid = anEval.EvaluateGridD2(aUParams, aVParams); for (int iU = 1; iU <= 9; ++iU) { @@ -122,3 +121,238 @@ TEST(GeomGridEval_CylinderTest, DerivativeD2) } } } + +TEST(GeomGridEval_CylinderTest, GridDerivativeD3) +{ + Handle(Geom_CylindricalSurface) aCyl = + new Geom_CylindricalSurface(gp_Ax3(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), 2.0); + GeomGridEval_Cylinder anEval(aCyl); + + TColStd_Array1OfReal aUParams = CreateUniformParams(0.0, 2 * M_PI, 9); + TColStd_Array1OfReal aVParams = CreateUniformParams(0.0, 5.0, 6); + + NCollection_Array2 aGrid = anEval.EvaluateGridD3(aUParams, aVParams); + + for (int iU = 1; iU <= 9; ++iU) + { + for (int iV = 1; iV <= 6; ++iV) + { + gp_Pnt aPnt; + gp_Vec aD1U, aD1V, aD2U, aD2V, aD2UV, aD3U, aD3V, aD3UUV, aD3UVV; + aCyl->D3(aUParams.Value(iU), + aVParams.Value(iV), + aPnt, + aD1U, + aD1V, + aD2U, + aD2V, + aD2UV, + aD3U, + aD3V, + aD3UUV, + aD3UVV); + EXPECT_NEAR(aGrid.Value(iU, iV).Point.Distance(aPnt), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aGrid.Value(iU, iV).D1U - aD1U).Magnitude(), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aGrid.Value(iU, iV).D1V - aD1V).Magnitude(), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aGrid.Value(iU, iV).D2U - aD2U).Magnitude(), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aGrid.Value(iU, iV).D2V - aD2V).Magnitude(), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aGrid.Value(iU, iV).D2UV - aD2UV).Magnitude(), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aGrid.Value(iU, iV).D3U - aD3U).Magnitude(), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aGrid.Value(iU, iV).D3V - aD3V).Magnitude(), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aGrid.Value(iU, iV).D3UUV - aD3UUV).Magnitude(), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aGrid.Value(iU, iV).D3UVV - aD3UVV).Magnitude(), 0.0, THE_TOLERANCE); + } + } +} + +TEST(GeomGridEval_CylinderTest, GridDerivativeDN) +{ + Handle(Geom_CylindricalSurface) aCyl = + new Geom_CylindricalSurface(gp_Ax3(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), 2.0); + GeomGridEval_Cylinder anEval(aCyl); + + TColStd_Array1OfReal aUParams = CreateUniformParams(0.0, 2 * M_PI, 5); + TColStd_Array1OfReal aVParams = CreateUniformParams(0.0, 5.0, 4); + + // Test D4U (4th derivative in U) + NCollection_Array2 aD4U = anEval.EvaluateGridDN(aUParams, aVParams, 4, 0); + for (int iU = 1; iU <= 5; ++iU) + { + for (int iV = 1; iV <= 4; ++iV) + { + gp_Vec aExpected = aCyl->DN(aUParams.Value(iU), aVParams.Value(iV), 4, 0); + EXPECT_NEAR((aD4U.Value(iU, iV) - aExpected).Magnitude(), 0.0, THE_TOLERANCE); + } + } +} + +//================================================================================================== +// Points evaluation tests +//================================================================================================== + +TEST(GeomGridEval_CylinderTest, PointsBasicEvaluation) +{ + Handle(Geom_CylindricalSurface) aCyl = + new Geom_CylindricalSurface(gp_Ax3(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), 2.0); + GeomGridEval_Cylinder anEval(aCyl); + + // Create arbitrary UV pairs + NCollection_Array1 aUVPairs(1, 10); + aUVPairs.SetValue(1, gp_Pnt2d(0.0, 0.0)); + aUVPairs.SetValue(2, gp_Pnt2d(M_PI / 4, 1.0)); + aUVPairs.SetValue(3, gp_Pnt2d(M_PI / 2, 2.0)); + aUVPairs.SetValue(4, gp_Pnt2d(M_PI, 3.0)); + aUVPairs.SetValue(5, gp_Pnt2d(3 * M_PI / 2, 4.0)); + aUVPairs.SetValue(6, gp_Pnt2d(2 * M_PI, 5.0)); + aUVPairs.SetValue(7, gp_Pnt2d(0.5, 0.5)); + aUVPairs.SetValue(8, gp_Pnt2d(1.5, 1.5)); + aUVPairs.SetValue(9, gp_Pnt2d(2.5, 2.5)); + aUVPairs.SetValue(10, gp_Pnt2d(3.5, 3.5)); + + NCollection_Array1 aPoints = anEval.EvaluatePoints(aUVPairs); + EXPECT_EQ(aPoints.Length(), 10); + + for (int i = 1; i <= 10; ++i) + { + const gp_Pnt2d& aUV = aUVPairs.Value(i); + gp_Pnt aExpected = aCyl->Value(aUV.X(), aUV.Y()); + EXPECT_NEAR(aPoints.Value(i).Distance(aExpected), 0.0, THE_TOLERANCE); + } +} + +TEST(GeomGridEval_CylinderTest, PointsDerivativeD1) +{ + Handle(Geom_CylindricalSurface) aCyl = + new Geom_CylindricalSurface(gp_Ax3(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), 2.0); + GeomGridEval_Cylinder anEval(aCyl); + + NCollection_Array1 aUVPairs(1, 5); + aUVPairs.SetValue(1, gp_Pnt2d(0.0, 0.0)); + aUVPairs.SetValue(2, gp_Pnt2d(M_PI / 4, 1.0)); + aUVPairs.SetValue(3, gp_Pnt2d(M_PI / 2, 2.0)); + aUVPairs.SetValue(4, gp_Pnt2d(M_PI, 3.0)); + aUVPairs.SetValue(5, gp_Pnt2d(3 * M_PI / 2, 4.0)); + + NCollection_Array1 aResults = anEval.EvaluatePointsD1(aUVPairs); + + for (int i = 1; i <= 5; ++i) + { + const gp_Pnt2d& aUV = aUVPairs.Value(i); + gp_Pnt aPnt; + gp_Vec aD1U, aD1V; + aCyl->D1(aUV.X(), aUV.Y(), aPnt, aD1U, aD1V); + EXPECT_NEAR(aResults.Value(i).Point.Distance(aPnt), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aResults.Value(i).D1U - aD1U).Magnitude(), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aResults.Value(i).D1V - aD1V).Magnitude(), 0.0, THE_TOLERANCE); + } +} + +TEST(GeomGridEval_CylinderTest, PointsDerivativeD2) +{ + Handle(Geom_CylindricalSurface) aCyl = + new Geom_CylindricalSurface(gp_Ax3(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), 2.0); + GeomGridEval_Cylinder anEval(aCyl); + + NCollection_Array1 aUVPairs(1, 5); + aUVPairs.SetValue(1, gp_Pnt2d(0.0, 0.0)); + aUVPairs.SetValue(2, gp_Pnt2d(M_PI / 4, 1.0)); + aUVPairs.SetValue(3, gp_Pnt2d(M_PI / 2, 2.0)); + aUVPairs.SetValue(4, gp_Pnt2d(M_PI, 3.0)); + aUVPairs.SetValue(5, gp_Pnt2d(3 * M_PI / 2, 4.0)); + + NCollection_Array1 aResults = anEval.EvaluatePointsD2(aUVPairs); + + for (int i = 1; i <= 5; ++i) + { + const gp_Pnt2d& aUV = aUVPairs.Value(i); + gp_Pnt aPnt; + gp_Vec aD1U, aD1V, aD2U, aD2V, aD2UV; + aCyl->D2(aUV.X(), aUV.Y(), aPnt, aD1U, aD1V, aD2U, aD2V, aD2UV); + EXPECT_NEAR(aResults.Value(i).Point.Distance(aPnt), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aResults.Value(i).D1U - aD1U).Magnitude(), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aResults.Value(i).D1V - aD1V).Magnitude(), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aResults.Value(i).D2U - aD2U).Magnitude(), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aResults.Value(i).D2V - aD2V).Magnitude(), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aResults.Value(i).D2UV - aD2UV).Magnitude(), 0.0, THE_TOLERANCE); + } +} + +TEST(GeomGridEval_CylinderTest, PointsDerivativeD3) +{ + Handle(Geom_CylindricalSurface) aCyl = + new Geom_CylindricalSurface(gp_Ax3(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), 2.0); + GeomGridEval_Cylinder anEval(aCyl); + + NCollection_Array1 aUVPairs(1, 5); + aUVPairs.SetValue(1, gp_Pnt2d(0.0, 0.0)); + aUVPairs.SetValue(2, gp_Pnt2d(M_PI / 4, 1.0)); + aUVPairs.SetValue(3, gp_Pnt2d(M_PI / 2, 2.0)); + aUVPairs.SetValue(4, gp_Pnt2d(M_PI, 3.0)); + aUVPairs.SetValue(5, gp_Pnt2d(3 * M_PI / 2, 4.0)); + + NCollection_Array1 aResults = anEval.EvaluatePointsD3(aUVPairs); + + for (int i = 1; i <= 5; ++i) + { + const gp_Pnt2d& aUV = aUVPairs.Value(i); + gp_Pnt aPnt; + gp_Vec aD1U, aD1V, aD2U, aD2V, aD2UV, aD3U, aD3V, aD3UUV, aD3UVV; + aCyl->D3(aUV.X(), aUV.Y(), aPnt, aD1U, aD1V, aD2U, aD2V, aD2UV, aD3U, aD3V, aD3UUV, aD3UVV); + EXPECT_NEAR(aResults.Value(i).Point.Distance(aPnt), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aResults.Value(i).D1U - aD1U).Magnitude(), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aResults.Value(i).D1V - aD1V).Magnitude(), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aResults.Value(i).D2U - aD2U).Magnitude(), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aResults.Value(i).D2V - aD2V).Magnitude(), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aResults.Value(i).D2UV - aD2UV).Magnitude(), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aResults.Value(i).D3U - aD3U).Magnitude(), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aResults.Value(i).D3V - aD3V).Magnitude(), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aResults.Value(i).D3UUV - aD3UUV).Magnitude(), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aResults.Value(i).D3UVV - aD3UVV).Magnitude(), 0.0, THE_TOLERANCE); + } +} + +TEST(GeomGridEval_CylinderTest, PointsDerivativeDN) +{ + Handle(Geom_CylindricalSurface) aCyl = + new Geom_CylindricalSurface(gp_Ax3(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), 2.0); + GeomGridEval_Cylinder anEval(aCyl); + + NCollection_Array1 aUVPairs(1, 5); + aUVPairs.SetValue(1, gp_Pnt2d(0.0, 0.0)); + aUVPairs.SetValue(2, gp_Pnt2d(M_PI / 4, 1.0)); + aUVPairs.SetValue(3, gp_Pnt2d(M_PI / 2, 2.0)); + aUVPairs.SetValue(4, gp_Pnt2d(M_PI, 3.0)); + aUVPairs.SetValue(5, gp_Pnt2d(3 * M_PI / 2, 4.0)); + + // Test D4U + NCollection_Array1 aD4U = anEval.EvaluatePointsDN(aUVPairs, 4, 0); + for (int i = 1; i <= 5; ++i) + { + const gp_Pnt2d& aUV = aUVPairs.Value(i); + gp_Vec aExpected = aCyl->DN(aUV.X(), aUV.Y(), 4, 0); + EXPECT_NEAR((aD4U.Value(i) - aExpected).Magnitude(), 0.0, THE_TOLERANCE); + } +} + +TEST(GeomGridEval_CylinderTest, PointsTransformedCylinder) +{ + // Cylinder with offset center and tilted axis + gp_Ax3 anAxis(gp_Pnt(5, 3, 2), gp_Dir(1, 1, 1)); + Handle(Geom_CylindricalSurface) aCyl = new Geom_CylindricalSurface(anAxis, 3.0); + GeomGridEval_Cylinder anEval(aCyl); + + NCollection_Array1 aUVPairs(1, 8); + for (int i = 1; i <= 8; ++i) + { + aUVPairs.SetValue(i, gp_Pnt2d((i - 1) * M_PI / 4, (i - 1) * 0.5)); + } + + NCollection_Array1 aPoints = anEval.EvaluatePoints(aUVPairs); + + for (int i = 1; i <= 8; ++i) + { + const gp_Pnt2d& aUV = aUVPairs.Value(i); + gp_Pnt aExpected = aCyl->Value(aUV.X(), aUV.Y()); + EXPECT_NEAR(aPoints.Value(i).Distance(aExpected), 0.0, THE_TOLERANCE); + } +} diff --git a/src/ModelingData/TKG3d/GTests/GeomGridEval_Ellipse_Test.cxx b/src/ModelingData/TKG3d/GTests/GeomGridEval_Ellipse_Test.cxx index de21a5c1e0..f7071815ec 100644 --- a/src/ModelingData/TKG3d/GTests/GeomGridEval_Ellipse_Test.cxx +++ b/src/ModelingData/TKG3d/GTests/GeomGridEval_Ellipse_Test.cxx @@ -53,9 +53,8 @@ TEST(GeomGridEval_EllipseTest, BasicEvaluation) aParams.SetValue(3, M_PI); aParams.SetValue(4, 3 * M_PI / 2); aParams.SetValue(5, 2 * M_PI); - anEval.SetParams(aParams); - NCollection_Array1 aGrid = anEval.EvaluateGrid(); + NCollection_Array1 aGrid = anEval.EvaluateGrid(aParams); // u=0: (3, 0, 0) EXPECT_NEAR(aGrid.Value(1).X(), 3.0, THE_TOLERANCE); @@ -85,9 +84,8 @@ TEST(GeomGridEval_EllipseTest, DerivativeD1) GeomGridEval_Ellipse anEval(anEllipse); TColStd_Array1OfReal aParams = CreateUniformParams(0.0, 2 * M_PI, 9); - anEval.SetParams(aParams); - NCollection_Array1 aGrid = anEval.EvaluateGridD1(); + NCollection_Array1 aGrid = anEval.EvaluateGridD1(aParams); for (int i = 1; i <= 9; ++i) { @@ -106,9 +104,8 @@ TEST(GeomGridEval_EllipseTest, DerivativeD2) GeomGridEval_Ellipse anEval(anEllipse); TColStd_Array1OfReal aParams = CreateUniformParams(0.0, 2 * M_PI, 9); - anEval.SetParams(aParams); - NCollection_Array1 aGrid = anEval.EvaluateGridD2(); + NCollection_Array1 aGrid = anEval.EvaluateGridD2(aParams); for (int i = 1; i <= 9; ++i) { @@ -128,9 +125,8 @@ TEST(GeomGridEval_EllipseTest, DerivativeD3) GeomGridEval_Ellipse anEval(anEllipse); TColStd_Array1OfReal aParams = CreateUniformParams(0.0, 2 * M_PI, 9); - anEval.SetParams(aParams); - NCollection_Array1 aGrid = anEval.EvaluateGridD3(); + NCollection_Array1 aGrid = anEval.EvaluateGridD3(aParams); for (int i = 1; i <= 9; ++i) { diff --git a/src/ModelingData/TKG3d/GTests/GeomGridEval_Hyperbola_Test.cxx b/src/ModelingData/TKG3d/GTests/GeomGridEval_Hyperbola_Test.cxx index fa954353be..39f256a038 100644 --- a/src/ModelingData/TKG3d/GTests/GeomGridEval_Hyperbola_Test.cxx +++ b/src/ModelingData/TKG3d/GTests/GeomGridEval_Hyperbola_Test.cxx @@ -48,9 +48,8 @@ TEST(GeomGridEval_HyperbolaTest, BasicEvaluation) // Test from -2 to 2 TColStd_Array1OfReal aParams = CreateUniformParams(-2.0, 2.0, 9); - anEval.SetParams(aParams); - NCollection_Array1 aGrid = anEval.EvaluateGrid(); + NCollection_Array1 aGrid = anEval.EvaluateGrid(aParams); EXPECT_EQ(aGrid.Size(), 9); // Verify points @@ -68,9 +67,8 @@ TEST(GeomGridEval_HyperbolaTest, DerivativeD1) GeomGridEval_Hyperbola anEval(aHypr); TColStd_Array1OfReal aParams = CreateUniformParams(-2.0, 2.0, 9); - anEval.SetParams(aParams); - NCollection_Array1 aGrid = anEval.EvaluateGridD1(); + NCollection_Array1 aGrid = anEval.EvaluateGridD1(aParams); for (int i = 1; i <= 9; ++i) { @@ -89,9 +87,8 @@ TEST(GeomGridEval_HyperbolaTest, DerivativeD2) GeomGridEval_Hyperbola anEval(aHypr); TColStd_Array1OfReal aParams = CreateUniformParams(-2.0, 2.0, 9); - anEval.SetParams(aParams); - NCollection_Array1 aGrid = anEval.EvaluateGridD2(); + NCollection_Array1 aGrid = anEval.EvaluateGridD2(aParams); for (int i = 1; i <= 9; ++i) { @@ -111,9 +108,8 @@ TEST(GeomGridEval_HyperbolaTest, DerivativeD3) GeomGridEval_Hyperbola anEval(aHypr); TColStd_Array1OfReal aParams = CreateUniformParams(-2.0, 2.0, 9); - anEval.SetParams(aParams); - NCollection_Array1 aGrid = anEval.EvaluateGridD3(); + NCollection_Array1 aGrid = anEval.EvaluateGridD3(aParams); for (int i = 1; i <= 9; ++i) { diff --git a/src/ModelingData/TKG3d/GTests/GeomGridEval_OffsetSurface_Test.cxx b/src/ModelingData/TKG3d/GTests/GeomGridEval_OffsetSurface_Test.cxx index 84aa9eb4e7..cfd71f4c9a 100644 --- a/src/ModelingData/TKG3d/GTests/GeomGridEval_OffsetSurface_Test.cxx +++ b/src/ModelingData/TKG3d/GTests/GeomGridEval_OffsetSurface_Test.cxx @@ -54,9 +54,8 @@ TEST(GeomGridEval_OffsetSurfaceTest, PlaneOffset) TColStd_Array1OfReal aUParams = CreateUniformParams(0.0, 10.0, 5); TColStd_Array1OfReal aVParams = CreateUniformParams(0.0, 10.0, 5); - anEval.SetUVParams(aUParams, aVParams); - NCollection_Array2 aGrid = anEval.EvaluateGrid(); + NCollection_Array2 aGrid = anEval.EvaluateGrid(aUParams, aVParams); for (int i = 1; i <= 5; ++i) { @@ -82,9 +81,8 @@ TEST(GeomGridEval_OffsetSurfaceTest, CylinderOffset) TColStd_Array1OfReal aUParams = CreateUniformParams(0.0, 2 * M_PI, 9); TColStd_Array1OfReal aVParams = CreateUniformParams(0.0, 5.0, 5); - anEval.SetUVParams(aUParams, aVParams); - NCollection_Array2 aGrid = anEval.EvaluateGrid(); + NCollection_Array2 aGrid = anEval.EvaluateGrid(aUParams, aVParams); for (int i = 1; i <= 9; ++i) { @@ -112,9 +110,8 @@ TEST(GeomGridEval_OffsetSurfaceTest, DerivativeD1) TColStd_Array1OfReal aUParams = CreateUniformParams(0.0, 2 * M_PI, 5); TColStd_Array1OfReal aVParams = CreateUniformParams(0.0, 5.0, 3); - anEval.SetUVParams(aUParams, aVParams); - NCollection_Array2 aGrid = anEval.EvaluateGridD1(); + NCollection_Array2 aGrid = anEval.EvaluateGridD1(aUParams, aVParams); for (int i = 1; i <= 5; ++i) { @@ -147,9 +144,8 @@ TEST(GeomGridEval_OffsetSurfaceTest, NestedDispatch) TColStd_Array1OfReal aUParams = CreateUniformParams(0.0, 1.0, 3); TColStd_Array1OfReal aVParams = CreateUniformParams(0.0, 1.0, 3); - anEval.SetUVParams(aUParams, aVParams); - NCollection_Array2 aGrid = anEval.EvaluateGrid(); + NCollection_Array2 aGrid = anEval.EvaluateGrid(aUParams, aVParams); EXPECT_EQ(aGrid.RowLength(), 3); EXPECT_EQ(aGrid.ColLength(), 3); @@ -167,9 +163,8 @@ TEST(GeomGridEval_OffsetSurfaceTest, DerivativeD2) TColStd_Array1OfReal aUParams = CreateUniformParams(0.0, 2 * M_PI, 5); TColStd_Array1OfReal aVParams = CreateUniformParams(0.0, 5.0, 3); - anEval.SetUVParams(aUParams, aVParams); - NCollection_Array2 aGrid = anEval.EvaluateGridD2(); + NCollection_Array2 aGrid = anEval.EvaluateGridD2(aUParams, aVParams); for (int i = 1; i <= 5; ++i) { @@ -200,9 +195,8 @@ TEST(GeomGridEval_OffsetSurfaceTest, DerivativeD3) TColStd_Array1OfReal aUParams = CreateUniformParams(0.0, 2 * M_PI, 5); TColStd_Array1OfReal aVParams = CreateUniformParams(0.0, 5.0, 3); - anEval.SetUVParams(aUParams, aVParams); - NCollection_Array2 aGrid = anEval.EvaluateGridD3(); + NCollection_Array2 aGrid = anEval.EvaluateGridD3(aUParams, aVParams); GeomAdaptor_Surface anAdaptor(anOffset); for (int i = 1; i <= 5; ++i) @@ -249,9 +243,8 @@ TEST(GeomGridEval_OffsetSurfaceTest, DerivativeDN_U1V0) TColStd_Array1OfReal aUParams = CreateUniformParams(0.0, 2 * M_PI, 5); TColStd_Array1OfReal aVParams = CreateUniformParams(0.0, 5.0, 3); - anEval.SetUVParams(aUParams, aVParams); - NCollection_Array2 aGrid = anEval.EvaluateGridDN(1, 0); + NCollection_Array2 aGrid = anEval.EvaluateGridDN(aUParams, aVParams, 1, 0); // Use Geom_OffsetSurface::DN as reference (GeomAdaptor_Surface::DN doesn't // properly handle offset surfaces - it returns base surface derivatives) @@ -276,9 +269,8 @@ TEST(GeomGridEval_OffsetSurfaceTest, DerivativeDN_U0V1) TColStd_Array1OfReal aUParams = CreateUniformParams(0.0, 2 * M_PI, 5); TColStd_Array1OfReal aVParams = CreateUniformParams(0.0, 5.0, 3); - anEval.SetUVParams(aUParams, aVParams); - NCollection_Array2 aGrid = anEval.EvaluateGridDN(0, 1); + NCollection_Array2 aGrid = anEval.EvaluateGridDN(aUParams, aVParams, 0, 1); for (int i = 1; i <= 5; ++i) { @@ -301,9 +293,8 @@ TEST(GeomGridEval_OffsetSurfaceTest, DerivativeDN_U1V1) TColStd_Array1OfReal aUParams = CreateUniformParams(0.0, 2 * M_PI, 5); TColStd_Array1OfReal aVParams = CreateUniformParams(0.0, 5.0, 3); - anEval.SetUVParams(aUParams, aVParams); - NCollection_Array2 aGrid = anEval.EvaluateGridDN(1, 1); + NCollection_Array2 aGrid = anEval.EvaluateGridDN(aUParams, aVParams, 1, 1); for (int i = 1; i <= 5; ++i) { @@ -326,9 +317,8 @@ TEST(GeomGridEval_OffsetSurfaceTest, DerivativeDN_U2V0) TColStd_Array1OfReal aUParams = CreateUniformParams(0.0, 2 * M_PI, 5); TColStd_Array1OfReal aVParams = CreateUniformParams(0.0, 5.0, 3); - anEval.SetUVParams(aUParams, aVParams); - NCollection_Array2 aGrid = anEval.EvaluateGridDN(2, 0); + NCollection_Array2 aGrid = anEval.EvaluateGridDN(aUParams, aVParams, 2, 0); for (int i = 1; i <= 5; ++i) { @@ -350,11 +340,10 @@ TEST(GeomGridEval_OffsetSurfaceTest, DerivativeDN_PlaneOffset) TColStd_Array1OfReal aUParams = CreateUniformParams(0.0, 10.0, 5); TColStd_Array1OfReal aVParams = CreateUniformParams(0.0, 10.0, 5); - anEval.SetUVParams(aUParams, aVParams); // Test DN(1,0) and DN(0,1) - use Geom_OffsetSurface::DN as reference - NCollection_Array2 aGridU = anEval.EvaluateGridDN(1, 0); - NCollection_Array2 aGridV = anEval.EvaluateGridDN(0, 1); + NCollection_Array2 aGridU = anEval.EvaluateGridDN(aUParams, aVParams, 1, 0); + NCollection_Array2 aGridV = anEval.EvaluateGridDN(aUParams, aVParams, 0, 1); for (int i = 1; i <= 5; ++i) { @@ -368,7 +357,7 @@ TEST(GeomGridEval_OffsetSurfaceTest, DerivativeDN_PlaneOffset) } // For a plane offset, 2nd and higher derivatives should be zero - NCollection_Array2 aGrid2U = anEval.EvaluateGridDN(2, 0); + NCollection_Array2 aGrid2U = anEval.EvaluateGridDN(aUParams, aVParams, 2, 0); for (int i = 1; i <= 5; ++i) { for (int j = 1; j <= 5; ++j) @@ -392,8 +381,7 @@ TEST(GeomGridEval_OffsetSurfaceTest, IsolineU_CompareToGeomD0) aUParams.SetValue(1, M_PI / 4); TColStd_Array1OfReal aVParams = CreateUniformParams(0.0, 5.0, 15); - anEval.SetUVParams(aUParams, aVParams); - NCollection_Array2 aGrid = anEval.EvaluateGrid(); + NCollection_Array2 aGrid = anEval.EvaluateGrid(aUParams, aVParams); // Note: RowLength() = V count (columns), ColLength() = U count (rows) EXPECT_EQ(aGrid.RowLength(), 15); @@ -422,8 +410,7 @@ TEST(GeomGridEval_OffsetSurfaceTest, IsolineV_CompareToGeomD0) TColStd_Array1OfReal aVParams(1, 1); aVParams.SetValue(1, 2.5); - anEval.SetUVParams(aUParams, aVParams); - NCollection_Array2 aGrid = anEval.EvaluateGrid(); + NCollection_Array2 aGrid = anEval.EvaluateGrid(aUParams, aVParams); // Note: RowLength() = V count (columns), ColLength() = U count (rows) EXPECT_EQ(aGrid.RowLength(), 1); @@ -451,8 +438,7 @@ TEST(GeomGridEval_OffsetSurfaceTest, IsolinePlane_CompareToGeomD0) aUParams.SetValue(1, 5.0); TColStd_Array1OfReal aVParams = CreateUniformParams(-10.0, 10.0, 20); - anEval.SetUVParams(aUParams, aVParams); - NCollection_Array2 aGrid = anEval.EvaluateGrid(); + NCollection_Array2 aGrid = anEval.EvaluateGrid(aUParams, aVParams); for (int j = 1; j <= 20; ++j) { diff --git a/src/ModelingData/TKG3d/GTests/GeomGridEval_Parabola_Test.cxx b/src/ModelingData/TKG3d/GTests/GeomGridEval_Parabola_Test.cxx index 0b23f96dc3..294c90c333 100644 --- a/src/ModelingData/TKG3d/GTests/GeomGridEval_Parabola_Test.cxx +++ b/src/ModelingData/TKG3d/GTests/GeomGridEval_Parabola_Test.cxx @@ -53,9 +53,8 @@ TEST(GeomGridEval_ParabolaTest, BasicEvaluation) // Test from -2 to 2 TColStd_Array1OfReal aParams = CreateUniformParams(-2.0, 2.0, 5); - anEval.SetParams(aParams); - NCollection_Array1 aGrid = anEval.EvaluateGrid(); + NCollection_Array1 aGrid = anEval.EvaluateGrid(aParams); EXPECT_EQ(aGrid.Size(), 5); // Verify points @@ -72,9 +71,8 @@ TEST(GeomGridEval_ParabolaTest, DerivativeD1) GeomGridEval_Parabola anEval(aParab); TColStd_Array1OfReal aParams = CreateUniformParams(-2.0, 2.0, 9); - anEval.SetParams(aParams); - NCollection_Array1 aGrid = anEval.EvaluateGridD1(); + NCollection_Array1 aGrid = anEval.EvaluateGridD1(aParams); for (int i = 1; i <= 9; ++i) { @@ -92,9 +90,8 @@ TEST(GeomGridEval_ParabolaTest, DerivativeD2) GeomGridEval_Parabola anEval(aParab); TColStd_Array1OfReal aParams = CreateUniformParams(-2.0, 2.0, 9); - anEval.SetParams(aParams); - NCollection_Array1 aGrid = anEval.EvaluateGridD2(); + NCollection_Array1 aGrid = anEval.EvaluateGridD2(aParams); for (int i = 1; i <= 9; ++i) { @@ -113,9 +110,8 @@ TEST(GeomGridEval_ParabolaTest, DerivativeD3) GeomGridEval_Parabola anEval(aParab); TColStd_Array1OfReal aParams = CreateUniformParams(-2.0, 2.0, 9); - anEval.SetParams(aParams); - NCollection_Array1 aGrid = anEval.EvaluateGridD3(); + NCollection_Array1 aGrid = anEval.EvaluateGridD3(aParams); for (int i = 1; i <= 9; ++i) { diff --git a/src/ModelingData/TKG3d/GTests/GeomGridEval_Sphere_Test.cxx b/src/ModelingData/TKG3d/GTests/GeomGridEval_Sphere_Test.cxx new file mode 100644 index 0000000000..6c3ce73f55 --- /dev/null +++ b/src/ModelingData/TKG3d/GTests/GeomGridEval_Sphere_Test.cxx @@ -0,0 +1,422 @@ +// Copyright (c) 2025 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#include + +#include +#include +#include +#include +#include +#include + +#include + +namespace +{ +const double THE_TOLERANCE = 1e-10; + +TColStd_Array1OfReal CreateUniformParams(double theFirst, double theLast, int theNbPoints) +{ + TColStd_Array1OfReal 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 + +//================================================================================================== +// Grid evaluation tests +//================================================================================================== + +TEST(GeomGridEval_SphereTest, GridBasicEvaluation) +{ + // Sphere: Radius=5, Center(0,0,0), Z-axis + Handle(Geom_SphericalSurface) aSphere = + new Geom_SphericalSurface(gp_Ax3(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), 5.0); + + GeomGridEval_Sphere anEval(aSphere); + EXPECT_FALSE(anEval.Geometry().IsNull()); + + TColStd_Array1OfReal aUParams = CreateUniformParams(0.0, 2 * M_PI, 9); // Longitude + TColStd_Array1OfReal aVParams = CreateUniformParams(-M_PI / 2, M_PI / 2, 7); // Latitude + + NCollection_Array2 aGrid = anEval.EvaluateGrid(aUParams, aVParams); + EXPECT_EQ(aGrid.RowLength(), 7); + EXPECT_EQ(aGrid.ColLength(), 9); + + // Verify points + for (int iU = 1; iU <= 9; ++iU) + { + for (int iV = 1; iV <= 7; ++iV) + { + gp_Pnt aExpected = aSphere->Value(aUParams.Value(iU), aVParams.Value(iV)); + EXPECT_NEAR(aGrid.Value(iU, iV).Distance(aExpected), 0.0, THE_TOLERANCE); + } + } +} + +TEST(GeomGridEval_SphereTest, GridDerivativeD1) +{ + Handle(Geom_SphericalSurface) aSphere = + new Geom_SphericalSurface(gp_Ax3(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), 5.0); + GeomGridEval_Sphere anEval(aSphere); + + TColStd_Array1OfReal aUParams = CreateUniformParams(0.0, 2 * M_PI, 9); + TColStd_Array1OfReal aVParams = CreateUniformParams(-M_PI / 2, M_PI / 2, 7); + + NCollection_Array2 aGrid = anEval.EvaluateGridD1(aUParams, aVParams); + + for (int iU = 1; iU <= 9; ++iU) + { + for (int iV = 1; iV <= 7; ++iV) + { + gp_Pnt aPnt; + gp_Vec aD1U, aD1V; + aSphere->D1(aUParams.Value(iU), aVParams.Value(iV), aPnt, aD1U, aD1V); + EXPECT_NEAR(aGrid.Value(iU, iV).Point.Distance(aPnt), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aGrid.Value(iU, iV).D1U - aD1U).Magnitude(), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aGrid.Value(iU, iV).D1V - aD1V).Magnitude(), 0.0, THE_TOLERANCE); + } + } +} + +TEST(GeomGridEval_SphereTest, GridDerivativeD2) +{ + Handle(Geom_SphericalSurface) aSphere = + new Geom_SphericalSurface(gp_Ax3(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), 5.0); + GeomGridEval_Sphere anEval(aSphere); + + TColStd_Array1OfReal aUParams = CreateUniformParams(0.0, 2 * M_PI, 9); + TColStd_Array1OfReal aVParams = CreateUniformParams(-M_PI / 2, M_PI / 2, 7); + + NCollection_Array2 aGrid = anEval.EvaluateGridD2(aUParams, aVParams); + + for (int iU = 1; iU <= 9; ++iU) + { + for (int iV = 1; iV <= 7; ++iV) + { + gp_Pnt aPnt; + gp_Vec aD1U, aD1V, aD2U, aD2V, aD2UV; + aSphere->D2(aUParams.Value(iU), aVParams.Value(iV), aPnt, aD1U, aD1V, aD2U, aD2V, aD2UV); + EXPECT_NEAR(aGrid.Value(iU, iV).Point.Distance(aPnt), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aGrid.Value(iU, iV).D1U - aD1U).Magnitude(), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aGrid.Value(iU, iV).D1V - aD1V).Magnitude(), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aGrid.Value(iU, iV).D2U - aD2U).Magnitude(), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aGrid.Value(iU, iV).D2V - aD2V).Magnitude(), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aGrid.Value(iU, iV).D2UV - aD2UV).Magnitude(), 0.0, THE_TOLERANCE); + } + } +} + +TEST(GeomGridEval_SphereTest, GridDerivativeD3) +{ + Handle(Geom_SphericalSurface) aSphere = + new Geom_SphericalSurface(gp_Ax3(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), 5.0); + GeomGridEval_Sphere anEval(aSphere); + + TColStd_Array1OfReal aUParams = CreateUniformParams(0.0, 2 * M_PI, 9); + TColStd_Array1OfReal aVParams = CreateUniformParams(-M_PI / 2, M_PI / 2, 7); + + NCollection_Array2 aGrid = anEval.EvaluateGridD3(aUParams, aVParams); + + for (int iU = 1; iU <= 9; ++iU) + { + for (int iV = 1; iV <= 7; ++iV) + { + gp_Pnt aPnt; + gp_Vec aD1U, aD1V, aD2U, aD2V, aD2UV, aD3U, aD3V, aD3UUV, aD3UVV; + aSphere->D3(aUParams.Value(iU), + aVParams.Value(iV), + aPnt, + aD1U, + aD1V, + aD2U, + aD2V, + aD2UV, + aD3U, + aD3V, + aD3UUV, + aD3UVV); + EXPECT_NEAR(aGrid.Value(iU, iV).Point.Distance(aPnt), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aGrid.Value(iU, iV).D1U - aD1U).Magnitude(), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aGrid.Value(iU, iV).D1V - aD1V).Magnitude(), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aGrid.Value(iU, iV).D2U - aD2U).Magnitude(), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aGrid.Value(iU, iV).D2V - aD2V).Magnitude(), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aGrid.Value(iU, iV).D2UV - aD2UV).Magnitude(), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aGrid.Value(iU, iV).D3U - aD3U).Magnitude(), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aGrid.Value(iU, iV).D3V - aD3V).Magnitude(), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aGrid.Value(iU, iV).D3UUV - aD3UUV).Magnitude(), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aGrid.Value(iU, iV).D3UVV - aD3UVV).Magnitude(), 0.0, THE_TOLERANCE); + } + } +} + +TEST(GeomGridEval_SphereTest, GridDerivativeDN) +{ + Handle(Geom_SphericalSurface) aSphere = + new Geom_SphericalSurface(gp_Ax3(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), 5.0); + GeomGridEval_Sphere anEval(aSphere); + + TColStd_Array1OfReal aUParams = CreateUniformParams(0.0, 2 * M_PI, 5); + TColStd_Array1OfReal aVParams = CreateUniformParams(-M_PI / 2, M_PI / 2, 4); + + // Test D4U (4th derivative in U) + NCollection_Array2 aD4U = anEval.EvaluateGridDN(aUParams, aVParams, 4, 0); + for (int iU = 1; iU <= 5; ++iU) + { + for (int iV = 1; iV <= 4; ++iV) + { + gp_Vec aExpected = aSphere->DN(aUParams.Value(iU), aVParams.Value(iV), 4, 0); + EXPECT_NEAR((aD4U.Value(iU, iV) - aExpected).Magnitude(), 0.0, THE_TOLERANCE); + } + } +} + +//================================================================================================== +// Points evaluation tests +//================================================================================================== + +TEST(GeomGridEval_SphereTest, PointsBasicEvaluation) +{ + Handle(Geom_SphericalSurface) aSphere = + new Geom_SphericalSurface(gp_Ax3(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), 5.0); + GeomGridEval_Sphere anEval(aSphere); + + // Create arbitrary UV pairs + NCollection_Array1 aUVPairs(1, 10); + aUVPairs.SetValue(1, gp_Pnt2d(0.0, 0.0)); + aUVPairs.SetValue(2, gp_Pnt2d(M_PI / 4, M_PI / 6)); + aUVPairs.SetValue(3, gp_Pnt2d(M_PI / 2, M_PI / 4)); + aUVPairs.SetValue(4, gp_Pnt2d(M_PI, 0.0)); + aUVPairs.SetValue(5, gp_Pnt2d(3 * M_PI / 2, -M_PI / 4)); + aUVPairs.SetValue(6, gp_Pnt2d(2 * M_PI, -M_PI / 6)); + aUVPairs.SetValue(7, gp_Pnt2d(0.5, 0.2)); + aUVPairs.SetValue(8, gp_Pnt2d(1.5, -0.3)); + aUVPairs.SetValue(9, gp_Pnt2d(2.5, 0.4)); + aUVPairs.SetValue(10, gp_Pnt2d(3.5, -0.1)); + + NCollection_Array1 aPoints = anEval.EvaluatePoints(aUVPairs); + EXPECT_EQ(aPoints.Length(), 10); + + for (int i = 1; i <= 10; ++i) + { + const gp_Pnt2d& aUV = aUVPairs.Value(i); + gp_Pnt aExpected = aSphere->Value(aUV.X(), aUV.Y()); + EXPECT_NEAR(aPoints.Value(i).Distance(aExpected), 0.0, THE_TOLERANCE); + } +} + +TEST(GeomGridEval_SphereTest, PointsDerivativeD1) +{ + Handle(Geom_SphericalSurface) aSphere = + new Geom_SphericalSurface(gp_Ax3(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), 5.0); + GeomGridEval_Sphere anEval(aSphere); + + NCollection_Array1 aUVPairs(1, 5); + aUVPairs.SetValue(1, gp_Pnt2d(0.0, 0.0)); + aUVPairs.SetValue(2, gp_Pnt2d(M_PI / 4, M_PI / 6)); + aUVPairs.SetValue(3, gp_Pnt2d(M_PI / 2, M_PI / 4)); + aUVPairs.SetValue(4, gp_Pnt2d(M_PI, -M_PI / 6)); + aUVPairs.SetValue(5, gp_Pnt2d(3 * M_PI / 2, -M_PI / 4)); + + NCollection_Array1 aResults = anEval.EvaluatePointsD1(aUVPairs); + + for (int i = 1; i <= 5; ++i) + { + const gp_Pnt2d& aUV = aUVPairs.Value(i); + gp_Pnt aPnt; + gp_Vec aD1U, aD1V; + aSphere->D1(aUV.X(), aUV.Y(), aPnt, aD1U, aD1V); + EXPECT_NEAR(aResults.Value(i).Point.Distance(aPnt), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aResults.Value(i).D1U - aD1U).Magnitude(), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aResults.Value(i).D1V - aD1V).Magnitude(), 0.0, THE_TOLERANCE); + } +} + +TEST(GeomGridEval_SphereTest, PointsDerivativeD2) +{ + Handle(Geom_SphericalSurface) aSphere = + new Geom_SphericalSurface(gp_Ax3(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), 5.0); + GeomGridEval_Sphere anEval(aSphere); + + NCollection_Array1 aUVPairs(1, 5); + aUVPairs.SetValue(1, gp_Pnt2d(0.0, 0.0)); + aUVPairs.SetValue(2, gp_Pnt2d(M_PI / 4, M_PI / 6)); + aUVPairs.SetValue(3, gp_Pnt2d(M_PI / 2, M_PI / 4)); + aUVPairs.SetValue(4, gp_Pnt2d(M_PI, -M_PI / 6)); + aUVPairs.SetValue(5, gp_Pnt2d(3 * M_PI / 2, -M_PI / 4)); + + NCollection_Array1 aResults = anEval.EvaluatePointsD2(aUVPairs); + + for (int i = 1; i <= 5; ++i) + { + const gp_Pnt2d& aUV = aUVPairs.Value(i); + gp_Pnt aPnt; + gp_Vec aD1U, aD1V, aD2U, aD2V, aD2UV; + aSphere->D2(aUV.X(), aUV.Y(), aPnt, aD1U, aD1V, aD2U, aD2V, aD2UV); + EXPECT_NEAR(aResults.Value(i).Point.Distance(aPnt), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aResults.Value(i).D1U - aD1U).Magnitude(), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aResults.Value(i).D1V - aD1V).Magnitude(), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aResults.Value(i).D2U - aD2U).Magnitude(), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aResults.Value(i).D2V - aD2V).Magnitude(), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aResults.Value(i).D2UV - aD2UV).Magnitude(), 0.0, THE_TOLERANCE); + } +} + +TEST(GeomGridEval_SphereTest, PointsDerivativeD3) +{ + Handle(Geom_SphericalSurface) aSphere = + new Geom_SphericalSurface(gp_Ax3(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), 5.0); + GeomGridEval_Sphere anEval(aSphere); + + NCollection_Array1 aUVPairs(1, 5); + aUVPairs.SetValue(1, gp_Pnt2d(0.0, 0.0)); + aUVPairs.SetValue(2, gp_Pnt2d(M_PI / 4, M_PI / 6)); + aUVPairs.SetValue(3, gp_Pnt2d(M_PI / 2, M_PI / 4)); + aUVPairs.SetValue(4, gp_Pnt2d(M_PI, -M_PI / 6)); + aUVPairs.SetValue(5, gp_Pnt2d(3 * M_PI / 2, -M_PI / 4)); + + NCollection_Array1 aResults = anEval.EvaluatePointsD3(aUVPairs); + + for (int i = 1; i <= 5; ++i) + { + const gp_Pnt2d& aUV = aUVPairs.Value(i); + gp_Pnt aPnt; + gp_Vec aD1U, aD1V, aD2U, aD2V, aD2UV, aD3U, aD3V, aD3UUV, aD3UVV; + aSphere->D3(aUV.X(), aUV.Y(), aPnt, aD1U, aD1V, aD2U, aD2V, aD2UV, aD3U, aD3V, aD3UUV, aD3UVV); + EXPECT_NEAR(aResults.Value(i).Point.Distance(aPnt), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aResults.Value(i).D1U - aD1U).Magnitude(), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aResults.Value(i).D1V - aD1V).Magnitude(), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aResults.Value(i).D2U - aD2U).Magnitude(), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aResults.Value(i).D2V - aD2V).Magnitude(), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aResults.Value(i).D2UV - aD2UV).Magnitude(), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aResults.Value(i).D3U - aD3U).Magnitude(), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aResults.Value(i).D3V - aD3V).Magnitude(), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aResults.Value(i).D3UUV - aD3UUV).Magnitude(), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aResults.Value(i).D3UVV - aD3UVV).Magnitude(), 0.0, THE_TOLERANCE); + } +} + +TEST(GeomGridEval_SphereTest, PointsDerivativeDN) +{ + Handle(Geom_SphericalSurface) aSphere = + new Geom_SphericalSurface(gp_Ax3(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), 5.0); + GeomGridEval_Sphere anEval(aSphere); + + NCollection_Array1 aUVPairs(1, 5); + aUVPairs.SetValue(1, gp_Pnt2d(0.0, 0.0)); + aUVPairs.SetValue(2, gp_Pnt2d(M_PI / 4, M_PI / 6)); + aUVPairs.SetValue(3, gp_Pnt2d(M_PI / 2, M_PI / 4)); + aUVPairs.SetValue(4, gp_Pnt2d(M_PI, -M_PI / 6)); + aUVPairs.SetValue(5, gp_Pnt2d(3 * M_PI / 2, -M_PI / 4)); + + // Test D4U + NCollection_Array1 aD4U = anEval.EvaluatePointsDN(aUVPairs, 4, 0); + for (int i = 1; i <= 5; ++i) + { + const gp_Pnt2d& aUV = aUVPairs.Value(i); + gp_Vec aExpected = aSphere->DN(aUV.X(), aUV.Y(), 4, 0); + EXPECT_NEAR((aD4U.Value(i) - aExpected).Magnitude(), 0.0, THE_TOLERANCE); + } + + // Test mixed D2UV + NCollection_Array1 aD2UV = anEval.EvaluatePointsDN(aUVPairs, 2, 2); + for (int i = 1; i <= 5; ++i) + { + const gp_Pnt2d& aUV = aUVPairs.Value(i); + gp_Vec aExpected = aSphere->DN(aUV.X(), aUV.Y(), 2, 2); + EXPECT_NEAR((aD2UV.Value(i) - aExpected).Magnitude(), 0.0, THE_TOLERANCE); + } +} + +TEST(GeomGridEval_SphereTest, PointsTransformedSphere) +{ + // Sphere with offset center and tilted axis + gp_Ax3 anAxis(gp_Pnt(5, 3, 2), gp_Dir(1, 1, 1)); + Handle(Geom_SphericalSurface) aSphere = new Geom_SphericalSurface(anAxis, 4.0); + GeomGridEval_Sphere anEval(aSphere); + + NCollection_Array1 aUVPairs(1, 8); + for (int i = 1; i <= 8; ++i) + { + aUVPairs.SetValue(i, gp_Pnt2d((i - 1) * M_PI / 4, (i - 4) * M_PI / 8)); + } + + NCollection_Array1 aPoints = anEval.EvaluatePoints(aUVPairs); + + for (int i = 1; i <= 8; ++i) + { + const gp_Pnt2d& aUV = aUVPairs.Value(i); + gp_Pnt aExpected = aSphere->Value(aUV.X(), aUV.Y()); + EXPECT_NEAR(aPoints.Value(i).Distance(aExpected), 0.0, THE_TOLERANCE); + } +} + +TEST(GeomGridEval_SphereTest, PointsAtPoles) +{ + // Test evaluation at sphere poles + Handle(Geom_SphericalSurface) aSphere = + new Geom_SphericalSurface(gp_Ax3(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), 5.0); + GeomGridEval_Sphere anEval(aSphere); + + NCollection_Array1 aUVPairs(1, 5); + // North pole at V = PI/2 + aUVPairs.SetValue(1, gp_Pnt2d(0.0, M_PI / 2)); + aUVPairs.SetValue(2, gp_Pnt2d(M_PI / 2, M_PI / 2)); + aUVPairs.SetValue(3, gp_Pnt2d(M_PI, M_PI / 2)); + // South pole at V = -PI/2 + aUVPairs.SetValue(4, gp_Pnt2d(0.0, -M_PI / 2)); + aUVPairs.SetValue(5, gp_Pnt2d(M_PI, -M_PI / 2)); + + NCollection_Array1 aPoints = anEval.EvaluatePoints(aUVPairs); + + // All points at north pole should be at (0, 0, 5) + for (int i = 1; i <= 3; ++i) + { + EXPECT_NEAR(aPoints.Value(i).Distance(gp_Pnt(0, 0, 5)), 0.0, THE_TOLERANCE); + } + + // All points at south pole should be at (0, 0, -5) + for (int i = 4; i <= 5; ++i) + { + EXPECT_NEAR(aPoints.Value(i).Distance(gp_Pnt(0, 0, -5)), 0.0, THE_TOLERANCE); + } +} + +TEST(GeomGridEval_SphereTest, PointsOnEquator) +{ + // Test points on equator (V=0) + Handle(Geom_SphericalSurface) aSphere = + new Geom_SphericalSurface(gp_Ax3(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), 5.0); + GeomGridEval_Sphere anEval(aSphere); + + NCollection_Array1 aUVPairs(1, 4); + aUVPairs.SetValue(1, gp_Pnt2d(0.0, 0.0)); // (5, 0, 0) + aUVPairs.SetValue(2, gp_Pnt2d(M_PI / 2, 0.0)); // (0, 5, 0) + aUVPairs.SetValue(3, gp_Pnt2d(M_PI, 0.0)); // (-5, 0, 0) + aUVPairs.SetValue(4, gp_Pnt2d(3 * M_PI / 2, 0.0)); // (0, -5, 0) + + NCollection_Array1 aPoints = anEval.EvaluatePoints(aUVPairs); + + // Points on equator should be at distance 5 from origin and Z=0 + for (int i = 1; i <= 4; ++i) + { + const gp_Pnt& aPnt = aPoints.Value(i); + EXPECT_NEAR(aPnt.Distance(gp_Pnt(0, 0, 0)), 5.0, THE_TOLERANCE); + EXPECT_NEAR(aPnt.Z(), 0.0, THE_TOLERANCE); + } +} diff --git a/src/ModelingData/TKG3d/GTests/GeomGridEval_SurfaceOfExtrusion_Test.cxx b/src/ModelingData/TKG3d/GTests/GeomGridEval_SurfaceOfExtrusion_Test.cxx index 7db20b12ec..eaeb1e9ef2 100644 --- a/src/ModelingData/TKG3d/GTests/GeomGridEval_SurfaceOfExtrusion_Test.cxx +++ b/src/ModelingData/TKG3d/GTests/GeomGridEval_SurfaceOfExtrusion_Test.cxx @@ -59,9 +59,8 @@ TEST(GeomGridEval_SurfaceOfExtrusionTest, BasicEvaluation) TColStd_Array1OfReal aUParams = CreateUniformParams(0.0, 10.0, 5); TColStd_Array1OfReal aVParams = CreateUniformParams(0.0, 5.0, 5); - anEval.SetUVParams(aUParams, aVParams); - NCollection_Array2 aGrid = anEval.EvaluateGrid(); + NCollection_Array2 aGrid = anEval.EvaluateGrid(aUParams, aVParams); for (int i = 1; i <= 5; ++i) { @@ -93,9 +92,8 @@ TEST(GeomGridEval_SurfaceOfExtrusionTest, CircleBasisCurve) TColStd_Array1OfReal aUParams = CreateUniformParams(0.0, 2 * M_PI, 9); TColStd_Array1OfReal aVParams = CreateUniformParams(0.0, 10.0, 5); - anEval.SetUVParams(aUParams, aVParams); - NCollection_Array2 aGrid = anEval.EvaluateGrid(); + NCollection_Array2 aGrid = anEval.EvaluateGrid(aUParams, aVParams); for (int i = 1; i <= 9; ++i) { @@ -126,9 +124,8 @@ TEST(GeomGridEval_SurfaceOfExtrusionTest, DerivativeD1) TColStd_Array1OfReal aUParams = CreateUniformParams(0.0, 10.0, 5); TColStd_Array1OfReal aVParams = CreateUniformParams(0.0, 5.0, 5); - anEval.SetUVParams(aUParams, aVParams); - NCollection_Array2 aGridD1 = anEval.EvaluateGridD1(); + NCollection_Array2 aGridD1 = anEval.EvaluateGridD1(aUParams, aVParams); for (int i = 1; i <= 5; ++i) { @@ -164,9 +161,8 @@ TEST(GeomGridEval_SurfaceOfExtrusionTest, DerivativeD2) TColStd_Array1OfReal aUParams = CreateUniformParams(0.0, M_PI, 5); TColStd_Array1OfReal aVParams = CreateUniformParams(0.0, 5.0, 5); - anEval.SetUVParams(aUParams, aVParams); - NCollection_Array2 aGridD2 = anEval.EvaluateGridD2(); + NCollection_Array2 aGridD2 = anEval.EvaluateGridD2(aUParams, aVParams); for (int i = 1; i <= 5; ++i) { @@ -204,9 +200,8 @@ TEST(GeomGridEval_SurfaceOfExtrusionTest, DerivativeD3) TColStd_Array1OfReal aUParams = CreateUniformParams(0.0, M_PI, 5); TColStd_Array1OfReal aVParams = CreateUniformParams(0.0, 5.0, 5); - anEval.SetUVParams(aUParams, aVParams); - NCollection_Array2 aGridD3 = anEval.EvaluateGridD3(); + NCollection_Array2 aGridD3 = anEval.EvaluateGridD3(aUParams, aVParams); for (int i = 1; i <= 5; ++i) { @@ -258,9 +253,8 @@ TEST(GeomGridEval_SurfaceOfExtrusionTest, UnifiedDispatch) TColStd_Array1OfReal aUParams = CreateUniformParams(0.0, 10.0, 5); TColStd_Array1OfReal aVParams = CreateUniformParams(0.0, 5.0, 5); - anEval.SetUVParams(aUParams, aVParams); - NCollection_Array2 aGrid = anEval.EvaluateGrid(); + NCollection_Array2 aGrid = anEval.EvaluateGrid(aUParams, aVParams); for (int i = 1; i <= 5; ++i) { @@ -289,9 +283,8 @@ TEST(GeomGridEval_SurfaceOfExtrusionTest, AdaptorDispatch) TColStd_Array1OfReal aUParams = CreateUniformParams(0.0, 10.0, 5); TColStd_Array1OfReal aVParams = CreateUniformParams(0.0, 5.0, 5); - anEval.SetUVParams(aUParams, aVParams); - NCollection_Array2 aGrid = anEval.EvaluateGrid(); + NCollection_Array2 aGrid = anEval.EvaluateGrid(aUParams, aVParams); for (int i = 1; i <= 5; ++i) { @@ -318,9 +311,8 @@ TEST(GeomGridEval_SurfaceOfExtrusionTest, NonAxisAlignedDirection) TColStd_Array1OfReal aUParams = CreateUniformParams(0.0, 2 * M_PI, 9); TColStd_Array1OfReal aVParams = CreateUniformParams(-5.0, 5.0, 5); - anEval.SetUVParams(aUParams, aVParams); - NCollection_Array2 aGrid = anEval.EvaluateGrid(); + NCollection_Array2 aGrid = anEval.EvaluateGrid(aUParams, aVParams); for (int i = 1; i <= 9; ++i) { diff --git a/src/ModelingData/TKG3d/GTests/GeomGridEval_SurfaceOfRevolution_Test.cxx b/src/ModelingData/TKG3d/GTests/GeomGridEval_SurfaceOfRevolution_Test.cxx index d46f4f619b..0461aa031d 100644 --- a/src/ModelingData/TKG3d/GTests/GeomGridEval_SurfaceOfRevolution_Test.cxx +++ b/src/ModelingData/TKG3d/GTests/GeomGridEval_SurfaceOfRevolution_Test.cxx @@ -57,9 +57,8 @@ TEST(GeomGridEval_SurfaceOfRevolutionTest, BasicEvaluation) TColStd_Array1OfReal aUParams = CreateUniformParams(0.0, M_PI, 9); TColStd_Array1OfReal aVParams = CreateUniformParams(0.0, 5.0, 5); - anEval.SetUVParams(aUParams, aVParams); - NCollection_Array2 aGrid = anEval.EvaluateGrid(); + NCollection_Array2 aGrid = anEval.EvaluateGrid(aUParams, aVParams); for (int i = 1; i <= 9; ++i) { @@ -91,9 +90,8 @@ TEST(GeomGridEval_SurfaceOfRevolutionTest, CircleMeridian) TColStd_Array1OfReal aUParams = CreateUniformParams(0.0, 2 * M_PI, 9); TColStd_Array1OfReal aVParams = CreateUniformParams(0.0, 2 * M_PI, 9); - anEval.SetUVParams(aUParams, aVParams); - NCollection_Array2 aGrid = anEval.EvaluateGrid(); + NCollection_Array2 aGrid = anEval.EvaluateGrid(aUParams, aVParams); for (int i = 1; i <= 9; ++i) { @@ -115,9 +113,8 @@ TEST(GeomGridEval_SurfaceOfRevolutionTest, DerivativeD1) TColStd_Array1OfReal aUParams = CreateUniformParams(0.0, M_PI, 5); TColStd_Array1OfReal aVParams = CreateUniformParams(0.0, 5.0, 5); - anEval.SetUVParams(aUParams, aVParams); - NCollection_Array2 aGridD1 = anEval.EvaluateGridD1(); + NCollection_Array2 aGridD1 = anEval.EvaluateGridD1(aUParams, aVParams); for (int i = 1; i <= 5; ++i) { @@ -145,9 +142,8 @@ TEST(GeomGridEval_SurfaceOfRevolutionTest, DerivativeD2) TColStd_Array1OfReal aUParams = CreateUniformParams(0.0, M_PI, 5); TColStd_Array1OfReal aVParams = CreateUniformParams(0.0, 5.0, 5); - anEval.SetUVParams(aUParams, aVParams); - NCollection_Array2 aGridD2 = anEval.EvaluateGridD2(); + NCollection_Array2 aGridD2 = anEval.EvaluateGridD2(aUParams, aVParams); for (int i = 1; i <= 5; ++i) { @@ -178,9 +174,8 @@ TEST(GeomGridEval_SurfaceOfRevolutionTest, DerivativeD3) TColStd_Array1OfReal aUParams = CreateUniformParams(0.0, M_PI, 5); TColStd_Array1OfReal aVParams = CreateUniformParams(0.0, 5.0, 5); - anEval.SetUVParams(aUParams, aVParams); - NCollection_Array2 aGridD3 = anEval.EvaluateGridD3(); + NCollection_Array2 aGridD3 = anEval.EvaluateGridD3(aUParams, aVParams); for (int i = 1; i <= 5; ++i) { @@ -226,9 +221,8 @@ TEST(GeomGridEval_SurfaceOfRevolutionTest, UnifiedDispatch) TColStd_Array1OfReal aUParams = CreateUniformParams(0.0, M_PI, 5); TColStd_Array1OfReal aVParams = CreateUniformParams(0.0, 5.0, 5); - anEval.SetUVParams(aUParams, aVParams); - NCollection_Array2 aGrid = anEval.EvaluateGrid(); + NCollection_Array2 aGrid = anEval.EvaluateGrid(aUParams, aVParams); for (int i = 1; i <= 5; ++i) { @@ -256,9 +250,8 @@ TEST(GeomGridEval_SurfaceOfRevolutionTest, AdaptorDispatch) TColStd_Array1OfReal aUParams = CreateUniformParams(0.0, M_PI, 5); TColStd_Array1OfReal aVParams = CreateUniformParams(0.0, 5.0, 5); - anEval.SetUVParams(aUParams, aVParams); - NCollection_Array2 aGrid = anEval.EvaluateGrid(); + NCollection_Array2 aGrid = anEval.EvaluateGrid(aUParams, aVParams); for (int i = 1; i <= 5; ++i) { diff --git a/src/ModelingData/TKG3d/GTests/GeomGridEval_Surface_Test.cxx b/src/ModelingData/TKG3d/GTests/GeomGridEval_Surface_Test.cxx index 3e2883909b..8482a58199 100644 --- a/src/ModelingData/TKG3d/GTests/GeomGridEval_Surface_Test.cxx +++ b/src/ModelingData/TKG3d/GTests/GeomGridEval_Surface_Test.cxx @@ -99,12 +99,8 @@ TEST(GeomGridEval_PlaneTest, BasicEvaluation) TColStd_Array1OfReal aUParams = CreateUniformParams(0.0, 5.0, 6); TColStd_Array1OfReal aVParams = CreateUniformParams(0.0, 3.0, 4); - anEval.SetUVParams(aUParams, aVParams); - EXPECT_EQ(anEval.NbUParams(), 6); - EXPECT_EQ(anEval.NbVParams(), 4); - - NCollection_Array2 aGrid = anEval.EvaluateGrid(); + NCollection_Array2 aGrid = anEval.EvaluateGrid(aUParams, aVParams); EXPECT_EQ(aGrid.RowLength(), 4); EXPECT_EQ(aGrid.ColLength(), 6); @@ -130,9 +126,8 @@ TEST(GeomGridEval_PlaneTest, NonOriginPlane) TColStd_Array1OfReal aUParams = CreateUniformParams(-1.0, 1.0, 3); TColStd_Array1OfReal aVParams = CreateUniformParams(-1.0, 1.0, 3); - anEval.SetUVParams(aUParams, aVParams); - NCollection_Array2 aGrid = anEval.EvaluateGrid(); + NCollection_Array2 aGrid = anEval.EvaluateGrid(aUParams, aVParams); // All points should be at Z=3 for (int iU = 1; iU <= 3; ++iU) @@ -163,9 +158,8 @@ TEST(GeomGridEval_SphereTest, BasicEvaluation) TColStd_Array1OfReal aUParams = CreateUniformParams(0.0, 2 * M_PI, 9); // Longitude TColStd_Array1OfReal aVParams = CreateUniformParams(-M_PI / 2, M_PI / 2, 5); // Latitude - anEval.SetUVParams(aUParams, aVParams); - NCollection_Array2 aGrid = anEval.EvaluateGrid(); + NCollection_Array2 aGrid = anEval.EvaluateGrid(aUParams, aVParams); // All points should be at distance 1 from origin for (int iU = 1; iU <= 9; ++iU) @@ -204,9 +198,8 @@ TEST(GeomGridEval_SphereTest, NonUnitSphere) TColStd_Array1OfReal aUParams = CreateUniformParams(0.0, 2 * M_PI, 17); TColStd_Array1OfReal aVParams = CreateUniformParams(-M_PI / 2, M_PI / 2, 9); - anEval.SetUVParams(aUParams, aVParams); - NCollection_Array2 aGrid = anEval.EvaluateGrid(); + NCollection_Array2 aGrid = anEval.EvaluateGrid(aUParams, aVParams); // All points should be at distance 3 from center const gp_Pnt aCenter(1, 2, 3); @@ -231,13 +224,12 @@ TEST(GeomGridEval_OtherSurfaceTest, CylinderFallback) new Geom_CylindricalSurface(gp_Ax3(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), 2.0); GeomAdaptor_Surface anAdaptor(aCyl); - GeomGridEval_OtherSurface anEval(anAdaptor); + GeomGridEval_OtherSurface anEval(&anAdaptor); TColStd_Array1OfReal aUParams = CreateUniformParams(0.0, 2 * M_PI, 9); TColStd_Array1OfReal aVParams = CreateUniformParams(0.0, 5.0, 6); - anEval.SetUVParams(aUParams, aVParams); - NCollection_Array2 aGrid = anEval.EvaluateGrid(); + NCollection_Array2 aGrid = anEval.EvaluateGrid(aUParams, aVParams); // Verify against direct evaluation for (int iU = 1; iU <= 9; ++iU) @@ -266,9 +258,8 @@ TEST(GeomGridEval_SurfaceTest, PlaneDispatch) TColStd_Array1OfReal aUParams = CreateUniformParams(-5.0, 5.0, 11); TColStd_Array1OfReal aVParams = CreateUniformParams(-3.0, 3.0, 7); - anEval.SetUVParams(aUParams, aVParams); - NCollection_Array2 aGrid = anEval.EvaluateGrid(); + NCollection_Array2 aGrid = anEval.EvaluateGrid(aUParams, aVParams); // Verify against direct evaluation for (int iU = 1; iU <= 11; ++iU) @@ -294,9 +285,8 @@ TEST(GeomGridEval_SurfaceTest, SphereDispatch) TColStd_Array1OfReal aUParams = CreateUniformParams(0.0, 2 * M_PI, 13); TColStd_Array1OfReal aVParams = CreateUniformParams(-M_PI / 2, M_PI / 2, 7); - anEval.SetUVParams(aUParams, aVParams); - NCollection_Array2 aGrid = anEval.EvaluateGrid(); + NCollection_Array2 aGrid = anEval.EvaluateGrid(aUParams, aVParams); // Verify against direct evaluation for (int iU = 1; iU <= 13; ++iU) @@ -321,9 +311,8 @@ TEST(GeomGridEval_SurfaceTest, BSplineDispatch) TColStd_Array1OfReal aUParams = CreateUniformParams(0.0, 1.0, 11); TColStd_Array1OfReal aVParams = CreateUniformParams(0.0, 1.0, 11); - anEval.SetUVParams(aUParams, aVParams); - NCollection_Array2 aGrid = anEval.EvaluateGrid(); + NCollection_Array2 aGrid = anEval.EvaluateGrid(aUParams, aVParams); // Verify against direct evaluation for (int iU = 1; iU <= 11; ++iU) @@ -352,9 +341,8 @@ TEST(GeomGridEval_SurfaceTest, BezierSurfaceDispatch) EXPECT_EQ(anEval.GetType(), GeomAbs_BezierSurface); TColStd_Array1OfReal aParams = CreateUniformParams(0.0, 1.0, 5); - anEval.SetUVParams(aParams, aParams); - NCollection_Array2 aGrid = anEval.EvaluateGrid(); + NCollection_Array2 aGrid = anEval.EvaluateGrid(aParams, aParams); for (int i = 1; i <= 5; ++i) { @@ -379,9 +367,8 @@ TEST(GeomGridEval_SurfaceTest, CylinderDispatch) TColStd_Array1OfReal aUParams = CreateUniformParams(0.0, 2 * M_PI, 9); TColStd_Array1OfReal aVParams = CreateUniformParams(0.0, 5.0, 6); - anEval.SetUVParams(aUParams, aVParams); - NCollection_Array2 aGrid = anEval.EvaluateGrid(); + NCollection_Array2 aGrid = anEval.EvaluateGrid(aUParams, aVParams); // Verify against direct evaluation for (int iU = 1; iU <= 9; ++iU) @@ -407,9 +394,8 @@ TEST(GeomGridEval_SurfaceTest, TorusDispatch) TColStd_Array1OfReal aUParams = CreateUniformParams(0.0, 2 * M_PI, 9); TColStd_Array1OfReal aVParams = CreateUniformParams(0.0, 2 * M_PI, 9); - anEval.SetUVParams(aUParams, aVParams); - NCollection_Array2 aGrid = anEval.EvaluateGrid(); + NCollection_Array2 aGrid = anEval.EvaluateGrid(aUParams, aVParams); // Verify against direct evaluation for (int iU = 1; iU <= 9; ++iU) @@ -435,9 +421,8 @@ TEST(GeomGridEval_SurfaceTest, ConeDispatch) TColStd_Array1OfReal aUParams = CreateUniformParams(0.0, 2 * M_PI, 9); TColStd_Array1OfReal aVParams = CreateUniformParams(0.0, 5.0, 6); - anEval.SetUVParams(aUParams, aVParams); - NCollection_Array2 aGrid = anEval.EvaluateGrid(); + NCollection_Array2 aGrid = anEval.EvaluateGrid(aUParams, aVParams); // Verify against direct evaluation for (int iU = 1; iU <= 9; ++iU) @@ -467,9 +452,8 @@ TEST(GeomGridEval_SurfaceTest, SurfaceOfRevolutionFallbackDispatch) TColStd_Array1OfReal aUParams = CreateUniformParams(0.0, 2 * M_PI, 9); TColStd_Array1OfReal aVParams = CreateUniformParams(0.0, 5.0, 6); - anEval.SetUVParams(aUParams, aVParams); - NCollection_Array2 aGrid = anEval.EvaluateGrid(); + NCollection_Array2 aGrid = anEval.EvaluateGrid(aUParams, aVParams); // Verify against direct evaluation for (int iU = 1; iU <= 9; ++iU) @@ -495,9 +479,8 @@ TEST(GeomGridEval_SurfaceTest, DirectHandleInit) TColStd_Array1OfReal aUParams = CreateUniformParams(0.0, 1.0, 5); TColStd_Array1OfReal aVParams = CreateUniformParams(0.0, 1.0, 5); - anEval.SetUVParams(aUParams, aVParams); - NCollection_Array2 aGrid = anEval.EvaluateGrid(); + NCollection_Array2 aGrid = anEval.EvaluateGrid(aUParams, aVParams); EXPECT_FALSE(aGrid.IsEmpty()); // Verify value @@ -508,10 +491,11 @@ TEST(GeomGridEval_SurfaceTest, UninitializedState) { GeomGridEval_Surface anEval; EXPECT_FALSE(anEval.IsInitialized()); - EXPECT_EQ(anEval.NbUParams(), 0); - EXPECT_EQ(anEval.NbVParams(), 0); - NCollection_Array2 aGrid = anEval.EvaluateGrid(); + TColStd_Array1OfReal aUParams = CreateUniformParams(0.0, 1.0, 5); + TColStd_Array1OfReal aVParams = CreateUniformParams(0.0, 1.0, 5); + + NCollection_Array2 aGrid = anEval.EvaluateGrid(aUParams, aVParams); EXPECT_TRUE(aGrid.IsEmpty()); } @@ -523,11 +507,10 @@ TEST(GeomGridEval_SurfaceTest, EmptyParams) GeomGridEval_Surface anEval; anEval.Initialize(anAdaptor); EXPECT_TRUE(anEval.IsInitialized()); - EXPECT_EQ(anEval.NbUParams(), 0); - EXPECT_EQ(anEval.NbVParams(), 0); - // EvaluateGrid without setting params should return empty - NCollection_Array2 aGrid = anEval.EvaluateGrid(); + // EvaluateGrid with empty params should return empty + TColStd_Array1OfReal aEmptyParams; + NCollection_Array2 aGrid = anEval.EvaluateGrid(aEmptyParams, aEmptyParams); EXPECT_TRUE(aGrid.IsEmpty()); } @@ -543,9 +526,8 @@ TEST(GeomGridEval_PlaneTest, DerivativeD1) TColStd_Array1OfReal aUParams = CreateUniformParams(0.0, 5.0, 6); TColStd_Array1OfReal aVParams = CreateUniformParams(0.0, 3.0, 4); - anEval.SetUVParams(aUParams, aVParams); - NCollection_Array2 aGrid = anEval.EvaluateGridD1(); + NCollection_Array2 aGrid = anEval.EvaluateGridD1(aUParams, aVParams); // For a plane, D1U and D1V are constant (the X and Y directions of the plane) gp_Pnt aPnt; @@ -569,9 +551,8 @@ TEST(GeomGridEval_PlaneTest, DerivativeD2) TColStd_Array1OfReal aUParams = CreateUniformParams(0.0, 5.0, 6); TColStd_Array1OfReal aVParams = CreateUniformParams(0.0, 3.0, 4); - anEval.SetUVParams(aUParams, aVParams); - NCollection_Array2 aGrid = anEval.EvaluateGridD2(); + NCollection_Array2 aGrid = anEval.EvaluateGridD2(aUParams, aVParams); // For a plane, all second derivatives are zero for (int iU = 1; iU <= 6; ++iU) @@ -593,9 +574,8 @@ TEST(GeomGridEval_SphereTest, DerivativeD1) TColStd_Array1OfReal aUParams = CreateUniformParams(0.0, 2 * M_PI, 9); TColStd_Array1OfReal aVParams = CreateUniformParams(-M_PI / 2, M_PI / 2, 5); - anEval.SetUVParams(aUParams, aVParams); - NCollection_Array2 aGrid = anEval.EvaluateGridD1(); + NCollection_Array2 aGrid = anEval.EvaluateGridD1(aUParams, aVParams); // Verify D1 against direct evaluation for (int iU = 1; iU <= 9; ++iU) @@ -620,9 +600,8 @@ TEST(GeomGridEval_SphereTest, DerivativeD2) TColStd_Array1OfReal aUParams = CreateUniformParams(0.0, 2 * M_PI, 9); TColStd_Array1OfReal aVParams = CreateUniformParams(-M_PI / 2, M_PI / 2, 5); - anEval.SetUVParams(aUParams, aVParams); - NCollection_Array2 aGrid = anEval.EvaluateGridD2(); + NCollection_Array2 aGrid = anEval.EvaluateGridD2(aUParams, aVParams); // Verify D2 against direct evaluation for (int iU = 1; iU <= 9; ++iU) @@ -653,9 +632,8 @@ TEST(GeomGridEval_SurfaceTest, UnifiedDerivativeD1) TColStd_Array1OfReal aUParams = CreateUniformParams(0.0, 2 * M_PI, 9); TColStd_Array1OfReal aVParams = CreateUniformParams(-M_PI / 2, M_PI / 2, 5); - anEval.SetUVParams(aUParams, aVParams); - NCollection_Array2 aGrid = anEval.EvaluateGridD1(); + NCollection_Array2 aGrid = anEval.EvaluateGridD1(aUParams, aVParams); // Verify against direct evaluation for (int iU = 1; iU <= 9; ++iU) @@ -682,9 +660,8 @@ TEST(GeomGridEval_SurfaceTest, UnifiedDerivativeD2) TColStd_Array1OfReal aUParams = CreateUniformParams(0.0, 1.0, 5); TColStd_Array1OfReal aVParams = CreateUniformParams(0.0, 1.0, 5); - anEval.SetUVParams(aUParams, aVParams); - NCollection_Array2 aGrid = anEval.EvaluateGridD2(); + NCollection_Array2 aGrid = anEval.EvaluateGridD2(aUParams, aVParams); // Verify against direct evaluation for (int iU = 1; iU <= 5; ++iU) @@ -715,9 +692,8 @@ TEST(GeomGridEval_PlaneTest, DerivativeD3) TColStd_Array1OfReal aUParams = CreateUniformParams(0.0, 5.0, 6); TColStd_Array1OfReal aVParams = CreateUniformParams(0.0, 3.0, 4); - anEval.SetUVParams(aUParams, aVParams); - NCollection_Array2 aGrid = anEval.EvaluateGridD3(); + NCollection_Array2 aGrid = anEval.EvaluateGridD3(aUParams, aVParams); // For a plane, all derivatives >= 2 are zero for (int iU = 1; iU <= 6; ++iU) @@ -744,9 +720,8 @@ TEST(GeomGridEval_SphereTest, DerivativeD3) TColStd_Array1OfReal aUParams = CreateUniformParams(0.0, 2 * M_PI, 9); TColStd_Array1OfReal aVParams = CreateUniformParams(-M_PI / 2 + 0.1, M_PI / 2 - 0.1, 5); // Avoid poles - anEval.SetUVParams(aUParams, aVParams); - NCollection_Array2 aGrid = anEval.EvaluateGridD3(); + NCollection_Array2 aGrid = anEval.EvaluateGridD3(aUParams, aVParams); // Verify D3 against direct evaluation using GeomAdaptor GeomAdaptor_Surface anAdaptor(aSphere); @@ -790,9 +765,8 @@ TEST(GeomGridEval_CylinderTest, DerivativeD3) TColStd_Array1OfReal aUParams = CreateUniformParams(0.0, 2 * M_PI, 9); TColStd_Array1OfReal aVParams = CreateUniformParams(0.0, 5.0, 6); - anEval.SetUVParams(aUParams, aVParams); - NCollection_Array2 aGrid = anEval.EvaluateGridD3(); + NCollection_Array2 aGrid = anEval.EvaluateGridD3(aUParams, aVParams); GeomAdaptor_Surface anAdaptor(aCyl); for (int iU = 1; iU <= 9; ++iU) @@ -830,9 +804,8 @@ TEST(GeomGridEval_ConeTest, DerivativeD3) TColStd_Array1OfReal aUParams = CreateUniformParams(0.0, 2 * M_PI, 9); TColStd_Array1OfReal aVParams = CreateUniformParams(0.0, 5.0, 6); - anEval.SetUVParams(aUParams, aVParams); - NCollection_Array2 aGrid = anEval.EvaluateGridD3(); + NCollection_Array2 aGrid = anEval.EvaluateGridD3(aUParams, aVParams); GeomAdaptor_Surface anAdaptor(aCone); for (int iU = 1; iU <= 9; ++iU) @@ -870,9 +843,8 @@ TEST(GeomGridEval_TorusTest, DerivativeD3) TColStd_Array1OfReal aUParams = CreateUniformParams(0.0, 2 * M_PI, 9); TColStd_Array1OfReal aVParams = CreateUniformParams(0.0, 2 * M_PI, 9); - anEval.SetUVParams(aUParams, aVParams); - NCollection_Array2 aGrid = anEval.EvaluateGridD3(); + NCollection_Array2 aGrid = anEval.EvaluateGridD3(aUParams, aVParams); GeomAdaptor_Surface anAdaptor(aTorus); for (int iU = 1; iU <= 9; ++iU) @@ -913,9 +885,8 @@ TEST(GeomGridEval_SurfaceTest, UnifiedDerivativeD3) TColStd_Array1OfReal aUParams = CreateUniformParams(0.0, 2 * M_PI, 9); TColStd_Array1OfReal aVParams = CreateUniformParams(0.0, 2 * M_PI, 9); - anEval.SetUVParams(aUParams, aVParams); - NCollection_Array2 aGrid = anEval.EvaluateGridD3(); + NCollection_Array2 aGrid = anEval.EvaluateGridD3(aUParams, aVParams); for (int iU = 1; iU <= 9; ++iU) { diff --git a/src/ModelingData/TKG3d/GTests/GeomGridEval_Torus_Test.cxx b/src/ModelingData/TKG3d/GTests/GeomGridEval_Torus_Test.cxx index d496d119d1..2f1e2025ca 100644 --- a/src/ModelingData/TKG3d/GTests/GeomGridEval_Torus_Test.cxx +++ b/src/ModelingData/TKG3d/GTests/GeomGridEval_Torus_Test.cxx @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -37,7 +38,11 @@ TColStd_Array1OfReal CreateUniformParams(double theFirst, double theLast, int th } } // namespace -TEST(GeomGridEval_TorusTest, BasicEvaluation) +//================================================================================================== +// Grid evaluation tests +//================================================================================================== + +TEST(GeomGridEval_TorusTest, GridBasicEvaluation) { // Torus: Major=10, Minor=2, Center(0,0,0), Z-axis Handle(Geom_ToroidalSurface) aTorus = @@ -48,12 +53,8 @@ TEST(GeomGridEval_TorusTest, BasicEvaluation) TColStd_Array1OfReal aUParams = CreateUniformParams(0.0, 2 * M_PI, 9); // Major TColStd_Array1OfReal aVParams = CreateUniformParams(0.0, 2 * M_PI, 9); // Minor - anEval.SetUVParams(aUParams, aVParams); - EXPECT_EQ(anEval.NbUParams(), 9); - EXPECT_EQ(anEval.NbVParams(), 9); - - NCollection_Array2 aGrid = anEval.EvaluateGrid(); + NCollection_Array2 aGrid = anEval.EvaluateGrid(aUParams, aVParams); EXPECT_EQ(aGrid.RowLength(), 9); EXPECT_EQ(aGrid.ColLength(), 9); @@ -68,7 +69,7 @@ TEST(GeomGridEval_TorusTest, BasicEvaluation) } } -TEST(GeomGridEval_TorusTest, DerivativeD1) +TEST(GeomGridEval_TorusTest, GridDerivativeD1) { Handle(Geom_ToroidalSurface) aTorus = new Geom_ToroidalSurface(gp_Ax3(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), 10.0, 2.0); @@ -76,9 +77,8 @@ TEST(GeomGridEval_TorusTest, DerivativeD1) TColStd_Array1OfReal aUParams = CreateUniformParams(0.0, 2 * M_PI, 9); TColStd_Array1OfReal aVParams = CreateUniformParams(0.0, 2 * M_PI, 9); - anEval.SetUVParams(aUParams, aVParams); - NCollection_Array2 aGrid = anEval.EvaluateGridD1(); + NCollection_Array2 aGrid = anEval.EvaluateGridD1(aUParams, aVParams); for (int iU = 1; iU <= 9; ++iU) { @@ -94,7 +94,7 @@ TEST(GeomGridEval_TorusTest, DerivativeD1) } } -TEST(GeomGridEval_TorusTest, DerivativeD2) +TEST(GeomGridEval_TorusTest, GridDerivativeD2) { Handle(Geom_ToroidalSurface) aTorus = new Geom_ToroidalSurface(gp_Ax3(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), 10.0, 2.0); @@ -102,9 +102,8 @@ TEST(GeomGridEval_TorusTest, DerivativeD2) TColStd_Array1OfReal aUParams = CreateUniformParams(0.0, 2 * M_PI, 9); TColStd_Array1OfReal aVParams = CreateUniformParams(0.0, 2 * M_PI, 9); - anEval.SetUVParams(aUParams, aVParams); - NCollection_Array2 aGrid = anEval.EvaluateGridD2(); + NCollection_Array2 aGrid = anEval.EvaluateGridD2(aUParams, aVParams); for (int iU = 1; iU <= 9; ++iU) { @@ -122,3 +121,273 @@ TEST(GeomGridEval_TorusTest, DerivativeD2) } } } + +TEST(GeomGridEval_TorusTest, GridDerivativeD3) +{ + Handle(Geom_ToroidalSurface) aTorus = + new Geom_ToroidalSurface(gp_Ax3(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), 10.0, 2.0); + GeomGridEval_Torus anEval(aTorus); + + TColStd_Array1OfReal aUParams = CreateUniformParams(0.0, 2 * M_PI, 9); + TColStd_Array1OfReal aVParams = CreateUniformParams(0.0, 2 * M_PI, 9); + + NCollection_Array2 aGrid = anEval.EvaluateGridD3(aUParams, aVParams); + + for (int iU = 1; iU <= 9; ++iU) + { + for (int iV = 1; iV <= 9; ++iV) + { + gp_Pnt aPnt; + gp_Vec aD1U, aD1V, aD2U, aD2V, aD2UV, aD3U, aD3V, aD3UUV, aD3UVV; + aTorus->D3(aUParams.Value(iU), + aVParams.Value(iV), + aPnt, + aD1U, + aD1V, + aD2U, + aD2V, + aD2UV, + aD3U, + aD3V, + aD3UUV, + aD3UVV); + EXPECT_NEAR(aGrid.Value(iU, iV).Point.Distance(aPnt), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aGrid.Value(iU, iV).D1U - aD1U).Magnitude(), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aGrid.Value(iU, iV).D1V - aD1V).Magnitude(), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aGrid.Value(iU, iV).D2U - aD2U).Magnitude(), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aGrid.Value(iU, iV).D2V - aD2V).Magnitude(), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aGrid.Value(iU, iV).D2UV - aD2UV).Magnitude(), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aGrid.Value(iU, iV).D3U - aD3U).Magnitude(), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aGrid.Value(iU, iV).D3V - aD3V).Magnitude(), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aGrid.Value(iU, iV).D3UUV - aD3UUV).Magnitude(), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aGrid.Value(iU, iV).D3UVV - aD3UVV).Magnitude(), 0.0, THE_TOLERANCE); + } + } +} + +TEST(GeomGridEval_TorusTest, GridDerivativeDN) +{ + Handle(Geom_ToroidalSurface) aTorus = + new Geom_ToroidalSurface(gp_Ax3(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), 10.0, 2.0); + GeomGridEval_Torus anEval(aTorus); + + TColStd_Array1OfReal aUParams = CreateUniformParams(0.0, 2 * M_PI, 5); + TColStd_Array1OfReal aVParams = CreateUniformParams(0.0, 2 * M_PI, 4); + + // Test D4U (4th derivative in U) + NCollection_Array2 aD4U = anEval.EvaluateGridDN(aUParams, aVParams, 4, 0); + for (int iU = 1; iU <= 5; ++iU) + { + for (int iV = 1; iV <= 4; ++iV) + { + gp_Vec aExpected = aTorus->DN(aUParams.Value(iU), aVParams.Value(iV), 4, 0); + EXPECT_NEAR((aD4U.Value(iU, iV) - aExpected).Magnitude(), 0.0, THE_TOLERANCE); + } + } +} + +//================================================================================================== +// Points evaluation tests +//================================================================================================== + +TEST(GeomGridEval_TorusTest, PointsBasicEvaluation) +{ + Handle(Geom_ToroidalSurface) aTorus = + new Geom_ToroidalSurface(gp_Ax3(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), 10.0, 2.0); + GeomGridEval_Torus anEval(aTorus); + + // Create arbitrary UV pairs + NCollection_Array1 aUVPairs(1, 10); + aUVPairs.SetValue(1, gp_Pnt2d(0.0, 0.0)); + aUVPairs.SetValue(2, gp_Pnt2d(M_PI / 4, M_PI / 4)); + aUVPairs.SetValue(3, gp_Pnt2d(M_PI / 2, M_PI / 2)); + aUVPairs.SetValue(4, gp_Pnt2d(M_PI, M_PI)); + aUVPairs.SetValue(5, gp_Pnt2d(3 * M_PI / 2, 3 * M_PI / 2)); + aUVPairs.SetValue(6, gp_Pnt2d(2 * M_PI, 2 * M_PI)); + aUVPairs.SetValue(7, gp_Pnt2d(0.5, 1.0)); + aUVPairs.SetValue(8, gp_Pnt2d(1.5, 2.0)); + aUVPairs.SetValue(9, gp_Pnt2d(2.5, 3.0)); + aUVPairs.SetValue(10, gp_Pnt2d(3.5, 4.0)); + + NCollection_Array1 aPoints = anEval.EvaluatePoints(aUVPairs); + EXPECT_EQ(aPoints.Length(), 10); + + for (int i = 1; i <= 10; ++i) + { + const gp_Pnt2d& aUV = aUVPairs.Value(i); + gp_Pnt aExpected = aTorus->Value(aUV.X(), aUV.Y()); + EXPECT_NEAR(aPoints.Value(i).Distance(aExpected), 0.0, THE_TOLERANCE); + } +} + +TEST(GeomGridEval_TorusTest, PointsDerivativeD1) +{ + Handle(Geom_ToroidalSurface) aTorus = + new Geom_ToroidalSurface(gp_Ax3(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), 10.0, 2.0); + GeomGridEval_Torus anEval(aTorus); + + NCollection_Array1 aUVPairs(1, 5); + aUVPairs.SetValue(1, gp_Pnt2d(0.0, 0.0)); + aUVPairs.SetValue(2, gp_Pnt2d(M_PI / 4, M_PI / 3)); + aUVPairs.SetValue(3, gp_Pnt2d(M_PI / 2, M_PI / 2)); + aUVPairs.SetValue(4, gp_Pnt2d(M_PI, M_PI)); + aUVPairs.SetValue(5, gp_Pnt2d(3 * M_PI / 2, 5 * M_PI / 4)); + + NCollection_Array1 aResults = anEval.EvaluatePointsD1(aUVPairs); + + for (int i = 1; i <= 5; ++i) + { + const gp_Pnt2d& aUV = aUVPairs.Value(i); + gp_Pnt aPnt; + gp_Vec aD1U, aD1V; + aTorus->D1(aUV.X(), aUV.Y(), aPnt, aD1U, aD1V); + EXPECT_NEAR(aResults.Value(i).Point.Distance(aPnt), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aResults.Value(i).D1U - aD1U).Magnitude(), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aResults.Value(i).D1V - aD1V).Magnitude(), 0.0, THE_TOLERANCE); + } +} + +TEST(GeomGridEval_TorusTest, PointsDerivativeD2) +{ + Handle(Geom_ToroidalSurface) aTorus = + new Geom_ToroidalSurface(gp_Ax3(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), 10.0, 2.0); + GeomGridEval_Torus anEval(aTorus); + + NCollection_Array1 aUVPairs(1, 5); + aUVPairs.SetValue(1, gp_Pnt2d(0.0, 0.0)); + aUVPairs.SetValue(2, gp_Pnt2d(M_PI / 4, M_PI / 3)); + aUVPairs.SetValue(3, gp_Pnt2d(M_PI / 2, M_PI / 2)); + aUVPairs.SetValue(4, gp_Pnt2d(M_PI, M_PI)); + aUVPairs.SetValue(5, gp_Pnt2d(3 * M_PI / 2, 5 * M_PI / 4)); + + NCollection_Array1 aResults = anEval.EvaluatePointsD2(aUVPairs); + + for (int i = 1; i <= 5; ++i) + { + const gp_Pnt2d& aUV = aUVPairs.Value(i); + gp_Pnt aPnt; + gp_Vec aD1U, aD1V, aD2U, aD2V, aD2UV; + aTorus->D2(aUV.X(), aUV.Y(), aPnt, aD1U, aD1V, aD2U, aD2V, aD2UV); + EXPECT_NEAR(aResults.Value(i).Point.Distance(aPnt), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aResults.Value(i).D1U - aD1U).Magnitude(), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aResults.Value(i).D1V - aD1V).Magnitude(), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aResults.Value(i).D2U - aD2U).Magnitude(), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aResults.Value(i).D2V - aD2V).Magnitude(), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aResults.Value(i).D2UV - aD2UV).Magnitude(), 0.0, THE_TOLERANCE); + } +} + +TEST(GeomGridEval_TorusTest, PointsDerivativeD3) +{ + Handle(Geom_ToroidalSurface) aTorus = + new Geom_ToroidalSurface(gp_Ax3(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), 10.0, 2.0); + GeomGridEval_Torus anEval(aTorus); + + NCollection_Array1 aUVPairs(1, 5); + aUVPairs.SetValue(1, gp_Pnt2d(0.0, 0.0)); + aUVPairs.SetValue(2, gp_Pnt2d(M_PI / 4, M_PI / 3)); + aUVPairs.SetValue(3, gp_Pnt2d(M_PI / 2, M_PI / 2)); + aUVPairs.SetValue(4, gp_Pnt2d(M_PI, M_PI)); + aUVPairs.SetValue(5, gp_Pnt2d(3 * M_PI / 2, 5 * M_PI / 4)); + + NCollection_Array1 aResults = anEval.EvaluatePointsD3(aUVPairs); + + for (int i = 1; i <= 5; ++i) + { + const gp_Pnt2d& aUV = aUVPairs.Value(i); + gp_Pnt aPnt; + gp_Vec aD1U, aD1V, aD2U, aD2V, aD2UV, aD3U, aD3V, aD3UUV, aD3UVV; + aTorus->D3(aUV.X(), aUV.Y(), aPnt, aD1U, aD1V, aD2U, aD2V, aD2UV, aD3U, aD3V, aD3UUV, aD3UVV); + EXPECT_NEAR(aResults.Value(i).Point.Distance(aPnt), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aResults.Value(i).D1U - aD1U).Magnitude(), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aResults.Value(i).D1V - aD1V).Magnitude(), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aResults.Value(i).D2U - aD2U).Magnitude(), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aResults.Value(i).D2V - aD2V).Magnitude(), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aResults.Value(i).D2UV - aD2UV).Magnitude(), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aResults.Value(i).D3U - aD3U).Magnitude(), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aResults.Value(i).D3V - aD3V).Magnitude(), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aResults.Value(i).D3UUV - aD3UUV).Magnitude(), 0.0, THE_TOLERANCE); + EXPECT_NEAR((aResults.Value(i).D3UVV - aD3UVV).Magnitude(), 0.0, THE_TOLERANCE); + } +} + +TEST(GeomGridEval_TorusTest, PointsDerivativeDN) +{ + Handle(Geom_ToroidalSurface) aTorus = + new Geom_ToroidalSurface(gp_Ax3(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), 10.0, 2.0); + GeomGridEval_Torus anEval(aTorus); + + NCollection_Array1 aUVPairs(1, 5); + aUVPairs.SetValue(1, gp_Pnt2d(0.0, 0.0)); + aUVPairs.SetValue(2, gp_Pnt2d(M_PI / 4, M_PI / 3)); + aUVPairs.SetValue(3, gp_Pnt2d(M_PI / 2, M_PI / 2)); + aUVPairs.SetValue(4, gp_Pnt2d(M_PI, M_PI)); + aUVPairs.SetValue(5, gp_Pnt2d(3 * M_PI / 2, 5 * M_PI / 4)); + + // Test D4U + NCollection_Array1 aD4U = anEval.EvaluatePointsDN(aUVPairs, 4, 0); + for (int i = 1; i <= 5; ++i) + { + const gp_Pnt2d& aUV = aUVPairs.Value(i); + gp_Vec aExpected = aTorus->DN(aUV.X(), aUV.Y(), 4, 0); + EXPECT_NEAR((aD4U.Value(i) - aExpected).Magnitude(), 0.0, THE_TOLERANCE); + } + + // Test mixed D2UV + NCollection_Array1 aD2UV = anEval.EvaluatePointsDN(aUVPairs, 2, 2); + for (int i = 1; i <= 5; ++i) + { + const gp_Pnt2d& aUV = aUVPairs.Value(i); + gp_Vec aExpected = aTorus->DN(aUV.X(), aUV.Y(), 2, 2); + EXPECT_NEAR((aD2UV.Value(i) - aExpected).Magnitude(), 0.0, THE_TOLERANCE); + } +} + +TEST(GeomGridEval_TorusTest, PointsTransformedTorus) +{ + // Torus with offset center and tilted axis + gp_Ax3 anAxis(gp_Pnt(5, 3, 2), gp_Dir(1, 1, 1)); + Handle(Geom_ToroidalSurface) aTorus = new Geom_ToroidalSurface(anAxis, 8.0, 1.5); + GeomGridEval_Torus anEval(aTorus); + + NCollection_Array1 aUVPairs(1, 8); + for (int i = 1; i <= 8; ++i) + { + aUVPairs.SetValue(i, gp_Pnt2d((i - 1) * M_PI / 4, (i - 1) * M_PI / 3)); + } + + NCollection_Array1 aPoints = anEval.EvaluatePoints(aUVPairs); + + for (int i = 1; i <= 8; ++i) + { + const gp_Pnt2d& aUV = aUVPairs.Value(i); + gp_Pnt aExpected = aTorus->Value(aUV.X(), aUV.Y()); + EXPECT_NEAR(aPoints.Value(i).Distance(aExpected), 0.0, THE_TOLERANCE); + } +} + +TEST(GeomGridEval_TorusTest, PointsOnMajorCircle) +{ + // Test points on major circle (V=0) + Handle(Geom_ToroidalSurface) aTorus = + new Geom_ToroidalSurface(gp_Ax3(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), 10.0, 2.0); + GeomGridEval_Torus anEval(aTorus); + + NCollection_Array1 aUVPairs(1, 4); + aUVPairs.SetValue(1, gp_Pnt2d(0.0, 0.0)); + aUVPairs.SetValue(2, gp_Pnt2d(M_PI / 2, 0.0)); + aUVPairs.SetValue(3, gp_Pnt2d(M_PI, 0.0)); + aUVPairs.SetValue(4, gp_Pnt2d(3 * M_PI / 2, 0.0)); + + NCollection_Array1 aPoints = anEval.EvaluatePoints(aUVPairs); + + // Points on major circle at V=0 should be at distance (Major+Minor) from Z axis + const double aExpectedRadius = 10.0 + 2.0; // Major + Minor + for (int i = 1; i <= 4; ++i) + { + const gp_Pnt& aPnt = aPoints.Value(i); + double aRadialDist = std::sqrt(aPnt.X() * aPnt.X() + aPnt.Y() * aPnt.Y()); + EXPECT_NEAR(aRadialDist, aExpectedRadius, THE_TOLERANCE); + EXPECT_NEAR(aPnt.Z(), 0.0, THE_TOLERANCE); + } +} diff --git a/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval.hxx b/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval.hxx index 1a40a923ed..ef6368542a 100644 --- a/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval.hxx +++ b/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval.hxx @@ -15,7 +15,11 @@ #define _GeomGridEval_HeaderFile #include +#include #include +#include +#include +#include //! @brief Namespace containing result structures for grid evaluators. //! @@ -82,6 +86,284 @@ struct SurfD3 gp_Vec D3UVV; }; +//! UV point with output index for unified grid/pairs handling. +//! Used internally by surface evaluators - both SetUVParams (grid) and SetUVPairs +//! convert input to this format for unified evaluation. +//! For grid input: OutputIdx = i * NbV + j (row-major linear index) +//! For pairs input: OutputIdx = original index in input array +struct UVPoint +{ + double U; //!< U parameter value + double V; //!< V parameter value + int OutputIdx; //!< Linear output index for result placement +}; + +//! UV point with span information for BSpline/Bezier optimization. +//! Extends UVPoint with pre-computed span data for cache-optimal evaluation. +//! The sorting by (USpanIdx, VSpanIdx, U) minimizes cache rebuilds during evaluation. +struct UVPointWithSpan +{ + double U; //!< U parameter value + double V; //!< V parameter value + double LocalU; //!< Pre-computed local U in [-1, 1] range for cache evaluation + double LocalV; //!< Pre-computed local V in [-1, 1] range for cache evaluation + int USpanIdx; //!< U flat knot index identifying the span + int VSpanIdx; //!< V flat knot index identifying the span + int OutputIdx; //!< Linear output index for result placement +}; + +//================================================================================================== +// Template helpers for parametric surface evaluation. +// These provide the iteration pattern, while the actual computation is delegated to a functor. +//================================================================================================== + +//! Evaluate grid points using a point evaluator functor. +//! @tparam Evaluator functor type with operator()(double theU, double theV) -> gp_Pnt +//! @param theUParams array of U parameter values +//! @param theVParams array of V parameter values +//! @param theEval evaluator functor +//! @return 2D array of evaluated points (1-based indexing) +template +NCollection_Array2 EvaluateGridHelper(const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams, + Evaluator theEval) +{ + const int aNbU = theUParams.Size(); + const int aNbV = theVParams.Size(); + if (aNbU == 0 || aNbV == 0) + { + return NCollection_Array2(); + } + + NCollection_Array2 aResult(1, aNbU, 1, aNbV); + for (int iU = 1; iU <= aNbU; ++iU) + { + const double aU = theUParams.Value(theUParams.Lower() + iU - 1); + for (int iV = 1; iV <= aNbV; ++iV) + { + const double aV = theVParams.Value(theVParams.Lower() + iV - 1); + aResult.SetValue(iU, iV, theEval(aU, aV)); + } + } + return aResult; +} + +//! Evaluate grid points with D1 using an evaluator functor. +//! @tparam Evaluator functor type with operator()(double theU, double theV) -> SurfD1 +template +NCollection_Array2 EvaluateGridD1Helper(const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams, + Evaluator theEval) +{ + const int aNbU = theUParams.Size(); + const int aNbV = theVParams.Size(); + if (aNbU == 0 || aNbV == 0) + { + return NCollection_Array2(); + } + + NCollection_Array2 aResult(1, aNbU, 1, aNbV); + for (int iU = 1; iU <= aNbU; ++iU) + { + const double aU = theUParams.Value(theUParams.Lower() + iU - 1); + for (int iV = 1; iV <= aNbV; ++iV) + { + const double aV = theVParams.Value(theVParams.Lower() + iV - 1); + aResult.ChangeValue(iU, iV) = theEval(aU, aV); + } + } + return aResult; +} + +//! Evaluate grid points with D2 using an evaluator functor. +//! @tparam Evaluator functor type with operator()(double theU, double theV) -> SurfD2 +template +NCollection_Array2 EvaluateGridD2Helper(const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams, + Evaluator theEval) +{ + const int aNbU = theUParams.Size(); + const int aNbV = theVParams.Size(); + if (aNbU == 0 || aNbV == 0) + { + return NCollection_Array2(); + } + + NCollection_Array2 aResult(1, aNbU, 1, aNbV); + for (int iU = 1; iU <= aNbU; ++iU) + { + const double aU = theUParams.Value(theUParams.Lower() + iU - 1); + for (int iV = 1; iV <= aNbV; ++iV) + { + const double aV = theVParams.Value(theVParams.Lower() + iV - 1); + aResult.ChangeValue(iU, iV) = theEval(aU, aV); + } + } + return aResult; +} + +//! Evaluate grid points with D3 using an evaluator functor. +//! @tparam Evaluator functor type with operator()(double theU, double theV) -> SurfD3 +template +NCollection_Array2 EvaluateGridD3Helper(const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams, + Evaluator theEval) +{ + const int aNbU = theUParams.Size(); + const int aNbV = theVParams.Size(); + if (aNbU == 0 || aNbV == 0) + { + return NCollection_Array2(); + } + + NCollection_Array2 aResult(1, aNbU, 1, aNbV); + for (int iU = 1; iU <= aNbU; ++iU) + { + const double aU = theUParams.Value(theUParams.Lower() + iU - 1); + for (int iV = 1; iV <= aNbV; ++iV) + { + const double aV = theVParams.Value(theVParams.Lower() + iV - 1); + aResult.ChangeValue(iU, iV) = theEval(aU, aV); + } + } + return aResult; +} + +//! Evaluate grid DN using an evaluator functor. +//! @tparam Evaluator functor type with operator()(double theU, double theV) -> gp_Vec +template +NCollection_Array2 EvaluateGridDNHelper(const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams, + Evaluator theEval) +{ + const int aNbU = theUParams.Size(); + const int aNbV = theVParams.Size(); + if (aNbU == 0 || aNbV == 0) + { + return NCollection_Array2(); + } + + NCollection_Array2 aResult(1, aNbU, 1, aNbV); + for (int iU = 1; iU <= aNbU; ++iU) + { + const double aU = theUParams.Value(theUParams.Lower() + iU - 1); + for (int iV = 1; iV <= aNbV; ++iV) + { + const double aV = theVParams.Value(theVParams.Lower() + iV - 1); + aResult.SetValue(iU, iV, theEval(aU, aV)); + } + } + return aResult; +} + +//! Evaluate UV pairs using a point evaluator functor. +//! @tparam Evaluator functor type with operator()(double theU, double theV) -> gp_Pnt +//! @param theUVPairs array of UV coordinate pairs (U=X(), V=Y()) +//! @param theEval evaluator functor +//! @return 1D array of evaluated points (1-based indexing) +template +NCollection_Array1 EvaluatePointsHelper(const NCollection_Array1& theUVPairs, + Evaluator theEval) +{ + const int aNbPts = theUVPairs.Size(); + if (aNbPts == 0) + { + return NCollection_Array1(); + } + + NCollection_Array1 aResult(1, aNbPts); + for (int i = 1; i <= aNbPts; ++i) + { + const gp_Pnt2d& aUV = theUVPairs.Value(theUVPairs.Lower() + i - 1); + aResult.SetValue(i, theEval(aUV.X(), aUV.Y())); + } + return aResult; +} + +//! Evaluate UV pairs with D1 using an evaluator functor. +//! @tparam Evaluator functor type with operator()(double theU, double theV) -> SurfD1 +template +NCollection_Array1 EvaluatePointsD1Helper(const NCollection_Array1& theUVPairs, + Evaluator theEval) +{ + const int aNbPts = theUVPairs.Size(); + if (aNbPts == 0) + { + return NCollection_Array1(); + } + + NCollection_Array1 aResult(1, aNbPts); + for (int i = 1; i <= aNbPts; ++i) + { + const gp_Pnt2d& aUV = theUVPairs.Value(theUVPairs.Lower() + i - 1); + aResult.ChangeValue(i) = theEval(aUV.X(), aUV.Y()); + } + return aResult; +} + +//! Evaluate UV pairs with D2 using an evaluator functor. +//! @tparam Evaluator functor type with operator()(double theU, double theV) -> SurfD2 +template +NCollection_Array1 EvaluatePointsD2Helper(const NCollection_Array1& theUVPairs, + Evaluator theEval) +{ + const int aNbPts = theUVPairs.Size(); + if (aNbPts == 0) + { + return NCollection_Array1(); + } + + NCollection_Array1 aResult(1, aNbPts); + for (int i = 1; i <= aNbPts; ++i) + { + const gp_Pnt2d& aUV = theUVPairs.Value(theUVPairs.Lower() + i - 1); + aResult.ChangeValue(i) = theEval(aUV.X(), aUV.Y()); + } + return aResult; +} + +//! Evaluate UV pairs with D3 using an evaluator functor. +//! @tparam Evaluator functor type with operator()(double theU, double theV) -> SurfD3 +template +NCollection_Array1 EvaluatePointsD3Helper(const NCollection_Array1& theUVPairs, + Evaluator theEval) +{ + const int aNbPts = theUVPairs.Size(); + if (aNbPts == 0) + { + return NCollection_Array1(); + } + + NCollection_Array1 aResult(1, aNbPts); + for (int i = 1; i <= aNbPts; ++i) + { + const gp_Pnt2d& aUV = theUVPairs.Value(theUVPairs.Lower() + i - 1); + aResult.ChangeValue(i) = theEval(aUV.X(), aUV.Y()); + } + return aResult; +} + +//! Evaluate UV pairs DN using an evaluator functor. +//! @tparam Evaluator functor type with operator()(double theU, double theV) -> gp_Vec +template +NCollection_Array1 EvaluatePointsDNHelper(const NCollection_Array1& theUVPairs, + Evaluator theEval) +{ + const int aNbPts = theUVPairs.Size(); + if (aNbPts == 0) + { + return NCollection_Array1(); + } + + NCollection_Array1 aResult(1, aNbPts); + for (int i = 1; i <= aNbPts; ++i) + { + const gp_Pnt2d& aUV = theUVPairs.Value(theUVPairs.Lower() + i - 1); + aResult.SetValue(i, theEval(aUV.X(), aUV.Y())); + } + return aResult; +} + } // namespace GeomGridEval #endif // _GeomGridEval_HeaderFile diff --git a/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_BSplineCurve.cxx b/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_BSplineCurve.cxx index 21fe03201d..668137726b 100644 --- a/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_BSplineCurve.cxx +++ b/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_BSplineCurve.cxx @@ -14,144 +14,61 @@ #include #include +#include #include #include namespace { -//! Threshold for using cache vs direct evaluation (same logic as surface). + +//! Threshold for using cache vs direct evaluation. constexpr int THE_CACHE_THRESHOLD = 4; -//! Iterate over span blocks and dispatch to cache or direct evaluation functors. -template -void iterateSpanBlocks(const SpanArray& theSpanRanges, - const ParamArray& theParams, - BuildCacheFunc&& theBuildCache, - CacheEvalFunc&& theCacheEval, - DirectEvalFunc&& theDirectEval) +//! Parameter value with pre-computed span index and local parameter. +struct ParamWithSpan { - const int aNbRanges = theSpanRanges.Size(); - for (int iRange = 0; iRange < aNbRanges; ++iRange) - { - const auto& aRange = theSpanRanges.Value(iRange); - const int aNbInSpan = aRange.EndIdx - aRange.StartIdx; + double Param; //!< Original parameter value + double LocalParam; //!< Pre-computed local parameter in [0, 1] range + int SpanIndex; //!< Flat knot index identifying the span + int OrigIdx; //!< Original index in the input array (0-based) +}; - if (aNbInSpan >= THE_CACHE_THRESHOLD) - { - // Large block: reuse cache - theBuildCache(theParams.Value(aRange.StartIdx).Param); - - for (int i = aRange.StartIdx; i < aRange.EndIdx; ++i) - { - theCacheEval(i, theParams.Value(i).LocalParam); - } - } - else - { - // Small block: cheaper to evaluate directly - const int aSpanIdx = aRange.SpanIndex; - for (int i = aRange.StartIdx; i < aRange.EndIdx; ++i) - { - theDirectEval(i, theParams.Value(i).Param, aSpanIdx); - } - } - } -} - -} // namespace - -//================================================================================================== - -void GeomGridEval_BSplineCurve::SetParams(const TColStd_Array1OfReal& theParams) +//! Range of parameter indices belonging to the same span. +struct SpanRange { - mySpanRanges = NCollection_Array1(); // Clear cached span data - myRawParams.Resize(theParams.Lower(), theParams.Upper(), false); - for (int i = theParams.Lower(); i <= theParams.Upper(); ++i) - { - myRawParams.SetValue(i, theParams.Value(i)); - } -} + int SpanIndex; //!< Flat knot index of this span + int StartIdx; //!< First parameter index (0-based, inclusive) + int EndIdx; //!< Past-the-end parameter index (exclusive) + double SpanMid; //!< Midpoint of span (for cache convention) +}; -//================================================================================================== - -void GeomGridEval_BSplineCurve::prepare() const -{ - // Check if already prepared using span ranges emptiness - if (!mySpanRanges.IsEmpty()) - { - return; - } - - if (myGeom.IsNull() || myRawParams.IsEmpty()) - { - myParams = NCollection_Array1(); - return; - } - - // Get flat knots directly from geometry - const Handle(TColStd_HArray1OfReal)& aFlatKnotsHandle = myGeom->HArrayFlatKnots(); - if (aFlatKnotsHandle.IsNull()) - { - myParams = NCollection_Array1(); - return; - } - const TColStd_Array1OfReal& aFlatKnots = aFlatKnotsHandle->Array1(); - - const int aDegree = myGeom->Degree(); - const int aNbParams = myRawParams.Size(); - myParams.Resize(0, aNbParams - 1, false); - - // Use hint-based span location for efficiency on sorted parameters - int aPrevSpan = aFlatKnots.Lower() + aDegree; - - for (int i = myRawParams.Lower(); i <= myRawParams.Upper(); ++i) - { - const double aParam = myRawParams.Value(i); - const int aSpanIdx = locateSpanWithHint(aParam, aPrevSpan, aFlatKnots); - aPrevSpan = aSpanIdx; - - // Pre-compute local parameter for this span - const double aSpanStart = aFlatKnots.Value(aSpanIdx); - const double aSpanLength = aFlatKnots.Value(aSpanIdx + 1) - aSpanStart; - const double aLocalParam = (aParam - aSpanStart) / aSpanLength; - - myParams.SetValue(i - myRawParams.Lower(), ParamWithSpan{aParam, aLocalParam, aSpanIdx}); - } - - // Compute span ranges for optimized iteration - computeSpanRanges(myParams, aFlatKnots, mySpanRanges); -} - -//================================================================================================== - -int GeomGridEval_BSplineCurve::locateSpan(double theParam, - const TColStd_Array1OfReal& theFlatKnots) const +//! Find span index for a parameter value. +int locateSpan(double theParam, + int theDegree, + bool theIsPeriodic, + const TColStd_Array1OfReal& theFlatKnots) { int aSpanIndex = 0; double aNewParam = theParam; - BSplCLib::LocateParameter(myGeom->Degree(), + BSplCLib::LocateParameter(theDegree, theFlatKnots, BSplCLib::NoMults(), theParam, - myGeom->IsPeriodic(), + theIsPeriodic, aSpanIndex, aNewParam); return aSpanIndex; } -//================================================================================================== - -int GeomGridEval_BSplineCurve::locateSpanWithHint(double theParam, - int theHint, - const TColStd_Array1OfReal& theFlatKnots) const +//! Find span index with a hint for better performance on sorted parameters. +int locateSpanWithHint(double theParam, + int theHint, + int theDegree, + bool theIsPeriodic, + const TColStd_Array1OfReal& theFlatKnots) { - const int aDegree = myGeom->Degree(); - const int aLower = theFlatKnots.Lower() + aDegree; - const int aUpper = theFlatKnots.Upper() - aDegree - 1; + const int aLower = theFlatKnots.Lower() + theDegree; + const int aUpper = theFlatKnots.Upper() - theDegree - 1; // Quick check if hint is still valid if (theHint >= aLower && theHint <= aUpper) @@ -176,53 +93,68 @@ int GeomGridEval_BSplineCurve::locateSpanWithHint(double th } // Fall back to standard locate - return locateSpan(theParam, theFlatKnots); + return locateSpan(theParam, theDegree, theIsPeriodic, theFlatKnots); } -//================================================================================================== - -void GeomGridEval_BSplineCurve::computeSpanRanges( - const NCollection_Array1& theParams, - const TColStd_Array1OfReal& theFlatKnots, - NCollection_Array1& theSpanRanges) +//! Prepare parameters with span data. +void prepareParams(const TColStd_Array1OfReal& theParams, + int theDegree, + bool theIsPeriodic, + const TColStd_Array1OfReal& theFlatKnots, + NCollection_Array1& theParamsWithSpan, + NCollection_Array1& theSpanRanges) { - if (theParams.IsEmpty()) + const int aNbParams = theParams.Size(); + theParamsWithSpan.Resize(0, aNbParams - 1, false); + + // Use hint-based span location for efficiency on sorted parameters + int aPrevSpan = theFlatKnots.Lower() + theDegree; + + for (int i = theParams.Lower(); i <= theParams.Upper(); ++i) { - theSpanRanges = NCollection_Array1(); - return; + const double aParam = theParams.Value(i); + const int aSpanIdx = + locateSpanWithHint(aParam, aPrevSpan, theDegree, theIsPeriodic, theFlatKnots); + aPrevSpan = aSpanIdx; + + // Pre-compute local parameter for this span + const double aSpanStart = theFlatKnots.Value(aSpanIdx); + const double aSpanLength = theFlatKnots.Value(aSpanIdx + 1) - aSpanStart; + const double aLocalParam = (aSpanLength > 0.0) ? (aParam - aSpanStart) / aSpanLength : 0.0; + + const int aIdx = i - theParams.Lower(); + theParamsWithSpan.SetValue(aIdx, ParamWithSpan{aParam, aLocalParam, aSpanIdx, aIdx}); } // Count distinct spans int aNbSpans = 1; - int aCurrentSpan = theParams.Value(0).SpanIndex; - for (int i = 1; i < theParams.Size(); ++i) + int aCurrentSpan = theParamsWithSpan.Value(0).SpanIndex; + for (int i = 1; i < aNbParams; ++i) { - if (theParams.Value(i).SpanIndex != aCurrentSpan) + if (theParamsWithSpan.Value(i).SpanIndex != aCurrentSpan) { ++aNbSpans; - aCurrentSpan = theParams.Value(i).SpanIndex; + aCurrentSpan = theParamsWithSpan.Value(i).SpanIndex; } } theSpanRanges.Resize(0, aNbSpans - 1, false); // Fill span ranges - aCurrentSpan = theParams.Value(0).SpanIndex; + aCurrentSpan = theParamsWithSpan.Value(0).SpanIndex; int aRangeStart = 0; int aRangeIdx = 0; - for (int i = 1; i < theParams.Size(); ++i) + for (int i = 1; i < aNbParams; ++i) { - const int aSpan = theParams.Value(i).SpanIndex; + const int aSpan = theParamsWithSpan.Value(i).SpanIndex; if (aSpan != aCurrentSpan) { - const double aSpanStart = theFlatKnots.Value(aCurrentSpan); - const double aSpanLength = theFlatKnots.Value(aCurrentSpan + 1) - aSpanStart; - const double aSpanMid = aSpanStart + aSpanLength * 0.5; - const double aSpanHalfLen = aSpanLength * 0.5; + const double aSpanStart = theFlatKnots.Value(aCurrentSpan); + const double aSpanLength = theFlatKnots.Value(aCurrentSpan + 1) - aSpanStart; + const double aSpanMid = aSpanStart + aSpanLength * 0.5; - theSpanRanges.SetValue(aRangeIdx, - SpanRange{aCurrentSpan, aRangeStart, i, aSpanMid, aSpanHalfLen}); + theSpanRanges.SetValue(aRangeIdx, SpanRange{aCurrentSpan, aRangeStart, i, aSpanMid}); ++aRangeIdx; aCurrentSpan = aSpan; aRangeStart = i; @@ -230,36 +162,64 @@ void GeomGridEval_BSplineCurve::computeSpanRanges( } // Add the last range - const double aSpanStart = theFlatKnots.Value(aCurrentSpan); - const double aSpanLength = theFlatKnots.Value(aCurrentSpan + 1) - aSpanStart; - const double aSpanMid = aSpanStart + aSpanLength * 0.5; - const double aSpanHalfLen = aSpanLength * 0.5; + const double aSpanStart = theFlatKnots.Value(aCurrentSpan); + const double aSpanLength = theFlatKnots.Value(aCurrentSpan + 1) - aSpanStart; + const double aSpanMid = aSpanStart + aSpanLength * 0.5; - theSpanRanges.SetValue( - aRangeIdx, - SpanRange{aCurrentSpan, aRangeStart, theParams.Size(), aSpanMid, aSpanHalfLen}); + theSpanRanges.SetValue(aRangeIdx, SpanRange{aCurrentSpan, aRangeStart, aNbParams, aSpanMid}); } +//! Iterate over span blocks and dispatch to cache or direct evaluation functors. +template +void iterateSpanBlocks(const NCollection_Array1& theSpanRanges, + const NCollection_Array1& theParams, + BuildCacheFunc&& theBuildCache, + CacheEvalFunc&& theCacheEval, + DirectEvalFunc&& theDirectEval) +{ + const int aNbRanges = theSpanRanges.Size(); + for (int iRange = 0; iRange < aNbRanges; ++iRange) + { + const auto& aRange = theSpanRanges.Value(iRange); + const int aNbInSpan = aRange.EndIdx - aRange.StartIdx; + + if (aNbInSpan >= THE_CACHE_THRESHOLD) + { + // Large block: reuse cache + theBuildCache(theParams.Value(aRange.StartIdx).Param); + + for (int i = aRange.StartIdx; i < aRange.EndIdx; ++i) + { + const auto& aP = theParams.Value(i); + theCacheEval(aP.OrigIdx, aP.LocalParam); + } + } + else + { + // Small block: cheaper to evaluate directly + const int aSpanIdx = aRange.SpanIndex; + for (int i = aRange.StartIdx; i < aRange.EndIdx; ++i) + { + const auto& aP = theParams.Value(i); + theDirectEval(aP.OrigIdx, aP.Param, aSpanIdx); + } + } + } +} + +} // namespace + //================================================================================================== -NCollection_Array1 GeomGridEval_BSplineCurve::EvaluateGrid() const +NCollection_Array1 GeomGridEval_BSplineCurve::EvaluateGrid( + const TColStd_Array1OfReal& theParams) const { - if (myGeom.IsNull() || myRawParams.IsEmpty()) + if (myGeom.IsNull() || theParams.IsEmpty()) { return NCollection_Array1(); } - // Prepare span data if needed - prepare(); - - if (myParams.IsEmpty() || mySpanRanges.IsEmpty()) - { - return NCollection_Array1(); - } - - const int aNbParams = myParams.Size(); - NCollection_Array1 aPoints(1, aNbParams); - + // Get flat knots directly from geometry const Handle(TColStd_HArray1OfReal)& aFlatKnotsHandle = myGeom->HArrayFlatKnots(); if (aFlatKnotsHandle.IsNull()) { @@ -285,18 +245,24 @@ NCollection_Array1 GeomGridEval_BSplineCurve::EvaluateGrid() const const int aDegree = myGeom->Degree(); const bool isPeriodic = myGeom->IsPeriodic(); - if (myCache.IsNull()) - { - myCache = new BSplCLib_Cache(aDegree, isPeriodic, aFlatKnots, aPoles, aWeights); - } + // Prepare parameters with span data + NCollection_Array1 aParamsWithSpan; + NCollection_Array1 aSpanRanges; + prepareParams(theParams, aDegree, isPeriodic, aFlatKnots, aParamsWithSpan, aSpanRanges); + + const int aNbParams = theParams.Size(); + NCollection_Array1 aPoints(1, aNbParams); + + Handle(BSplCLib_Cache) aCache = + new BSplCLib_Cache(aDegree, isPeriodic, aFlatKnots, aPoles, aWeights); iterateSpanBlocks( - mySpanRanges, - myParams, - [&](double theParam) { myCache->BuildCache(theParam, aFlatKnots, aPoles, aWeights); }, + aSpanRanges, + aParamsWithSpan, + [&](double theParam) { aCache->BuildCache(theParam, aFlatKnots, aPoles, aWeights); }, // Cache evaluation (local parameter) [&](int theIdx, double theLocalParam) { - myCache->D0Local(theLocalParam, aPoints.ChangeValue(theIdx + 1)); + aCache->D0Local(theLocalParam, aPoints.ChangeValue(theIdx + 1)); }, // Direct evaluation (global parameter + span index) [&](int theIdx, double theParam, int theSpanIdx) { @@ -318,23 +284,14 @@ NCollection_Array1 GeomGridEval_BSplineCurve::EvaluateGrid() const //================================================================================================== -NCollection_Array1 GeomGridEval_BSplineCurve::EvaluateGridD1() const +NCollection_Array1 GeomGridEval_BSplineCurve::EvaluateGridD1( + const TColStd_Array1OfReal& theParams) const { - if (myGeom.IsNull() || myRawParams.IsEmpty()) + if (myGeom.IsNull() || theParams.IsEmpty()) { return NCollection_Array1(); } - prepare(); - - if (myParams.IsEmpty() || mySpanRanges.IsEmpty()) - { - return NCollection_Array1(); - } - - const int aNbParams = myParams.Size(); - NCollection_Array1 aResults(1, aNbParams); - const Handle(TColStd_HArray1OfReal)& aFlatKnotsHandle = myGeom->HArrayFlatKnots(); if (aFlatKnotsHandle.IsNull()) { @@ -360,23 +317,26 @@ NCollection_Array1 GeomGridEval_BSplineCurve::EvaluateGri const int aDegree = myGeom->Degree(); const bool isPeriodic = myGeom->IsPeriodic(); - if (myCache.IsNull()) - { - myCache = new BSplCLib_Cache(aDegree, isPeriodic, aFlatKnots, aPoles, aWeights); - } + NCollection_Array1 aParamsWithSpan; + NCollection_Array1 aSpanRanges; + prepareParams(theParams, aDegree, isPeriodic, aFlatKnots, aParamsWithSpan, aSpanRanges); + + const int aNbParams = theParams.Size(); + NCollection_Array1 aResults(1, aNbParams); + + Handle(BSplCLib_Cache) aCache = + new BSplCLib_Cache(aDegree, isPeriodic, aFlatKnots, aPoles, aWeights); iterateSpanBlocks( - mySpanRanges, - myParams, - [&](double theParam) { myCache->BuildCache(theParam, aFlatKnots, aPoles, aWeights); }, - // Cache evaluation + aSpanRanges, + aParamsWithSpan, + [&](double theParam) { aCache->BuildCache(theParam, aFlatKnots, aPoles, aWeights); }, [&](int theIdx, double theLocalParam) { gp_Pnt aPoint; gp_Vec aD1; - myCache->D1Local(theLocalParam, aPoint, aD1); + aCache->D1Local(theLocalParam, aPoint, aD1); aResults.ChangeValue(theIdx + 1) = {aPoint, aD1}; }, - // Direct evaluation [&](int theIdx, double theParam, int theSpanIdx) { gp_Pnt aPoint; gp_Vec aD1; @@ -398,23 +358,14 @@ NCollection_Array1 GeomGridEval_BSplineCurve::EvaluateGri //================================================================================================== -NCollection_Array1 GeomGridEval_BSplineCurve::EvaluateGridD2() const +NCollection_Array1 GeomGridEval_BSplineCurve::EvaluateGridD2( + const TColStd_Array1OfReal& theParams) const { - if (myGeom.IsNull() || myRawParams.IsEmpty()) + if (myGeom.IsNull() || theParams.IsEmpty()) { return NCollection_Array1(); } - prepare(); - - if (myParams.IsEmpty() || mySpanRanges.IsEmpty()) - { - return NCollection_Array1(); - } - - const int aNbParams = myParams.Size(); - NCollection_Array1 aResults(1, aNbParams); - const Handle(TColStd_HArray1OfReal)& aFlatKnotsHandle = myGeom->HArrayFlatKnots(); if (aFlatKnotsHandle.IsNull()) { @@ -440,23 +391,26 @@ NCollection_Array1 GeomGridEval_BSplineCurve::EvaluateGri const int aDegree = myGeom->Degree(); const bool isPeriodic = myGeom->IsPeriodic(); - if (myCache.IsNull()) - { - myCache = new BSplCLib_Cache(aDegree, isPeriodic, aFlatKnots, aPoles, aWeights); - } + NCollection_Array1 aParamsWithSpan; + NCollection_Array1 aSpanRanges; + prepareParams(theParams, aDegree, isPeriodic, aFlatKnots, aParamsWithSpan, aSpanRanges); + + const int aNbParams = theParams.Size(); + NCollection_Array1 aResults(1, aNbParams); + + Handle(BSplCLib_Cache) aCache = + new BSplCLib_Cache(aDegree, isPeriodic, aFlatKnots, aPoles, aWeights); iterateSpanBlocks( - mySpanRanges, - myParams, - [&](double theParam) { myCache->BuildCache(theParam, aFlatKnots, aPoles, aWeights); }, - // Cache evaluation + aSpanRanges, + aParamsWithSpan, + [&](double theParam) { aCache->BuildCache(theParam, aFlatKnots, aPoles, aWeights); }, [&](int theIdx, double theLocalParam) { gp_Pnt aPoint; gp_Vec aD1, aD2; - myCache->D2Local(theLocalParam, aPoint, aD1, aD2); + aCache->D2Local(theLocalParam, aPoint, aD1, aD2); aResults.ChangeValue(theIdx + 1) = {aPoint, aD1, aD2}; }, - // Direct evaluation [&](int theIdx, double theParam, int theSpanIdx) { gp_Pnt aPoint; gp_Vec aD1, aD2; @@ -479,23 +433,14 @@ NCollection_Array1 GeomGridEval_BSplineCurve::EvaluateGri //================================================================================================== -NCollection_Array1 GeomGridEval_BSplineCurve::EvaluateGridD3() const +NCollection_Array1 GeomGridEval_BSplineCurve::EvaluateGridD3( + const TColStd_Array1OfReal& theParams) const { - if (myGeom.IsNull() || myRawParams.IsEmpty()) + if (myGeom.IsNull() || theParams.IsEmpty()) { return NCollection_Array1(); } - prepare(); - - if (myParams.IsEmpty() || mySpanRanges.IsEmpty()) - { - return NCollection_Array1(); - } - - const int aNbParams = myParams.Size(); - NCollection_Array1 aResults(1, aNbParams); - const Handle(TColStd_HArray1OfReal)& aFlatKnotsHandle = myGeom->HArrayFlatKnots(); if (aFlatKnotsHandle.IsNull()) { @@ -521,23 +466,26 @@ NCollection_Array1 GeomGridEval_BSplineCurve::EvaluateGri const int aDegree = myGeom->Degree(); const bool isPeriodic = myGeom->IsPeriodic(); - if (myCache.IsNull()) - { - myCache = new BSplCLib_Cache(aDegree, isPeriodic, aFlatKnots, aPoles, aWeights); - } + NCollection_Array1 aParamsWithSpan; + NCollection_Array1 aSpanRanges; + prepareParams(theParams, aDegree, isPeriodic, aFlatKnots, aParamsWithSpan, aSpanRanges); + + const int aNbParams = theParams.Size(); + NCollection_Array1 aResults(1, aNbParams); + + Handle(BSplCLib_Cache) aCache = + new BSplCLib_Cache(aDegree, isPeriodic, aFlatKnots, aPoles, aWeights); iterateSpanBlocks( - mySpanRanges, - myParams, - [&](double theParam) { myCache->BuildCache(theParam, aFlatKnots, aPoles, aWeights); }, - // Cache evaluation + aSpanRanges, + aParamsWithSpan, + [&](double theParam) { aCache->BuildCache(theParam, aFlatKnots, aPoles, aWeights); }, [&](int theIdx, double theLocalParam) { gp_Pnt aPoint; gp_Vec aD1, aD2, aD3; - myCache->D3Local(theLocalParam, aPoint, aD1, aD2, aD3); + aCache->D3Local(theLocalParam, aPoint, aD1, aD2, aD3); aResults.ChangeValue(theIdx + 1) = {aPoint, aD1, aD2, aD3}; }, - // Direct evaluation [&](int theIdx, double theParam, int theSpanIdx) { gp_Pnt aPoint; gp_Vec aD1, aD2, aD3; @@ -561,21 +509,16 @@ NCollection_Array1 GeomGridEval_BSplineCurve::EvaluateGri //================================================================================================== -NCollection_Array1 GeomGridEval_BSplineCurve::EvaluateGridDN(int theN) const +NCollection_Array1 GeomGridEval_BSplineCurve::EvaluateGridDN( + const TColStd_Array1OfReal& theParams, + int theN) const { - if (myGeom.IsNull() || myRawParams.IsEmpty() || theN < 1) + if (myGeom.IsNull() || theParams.IsEmpty() || theN < 1) { return NCollection_Array1(); } - prepare(); - - if (myParams.IsEmpty() || mySpanRanges.IsEmpty()) - { - return NCollection_Array1(); - } - - const int aNbParams = myParams.Size(); + const int aNbParams = theParams.Size(); NCollection_Array1 aResult(1, aNbParams); // For B-spline curves, derivatives become zero when order exceeds degree @@ -590,7 +533,14 @@ NCollection_Array1 GeomGridEval_BSplineCurve::EvaluateGridDN(int theN) c return aResult; } - // Get curve data for direct BSplCLib::DN call + // Get flat knots directly from geometry + const Handle(TColStd_HArray1OfReal)& aFlatKnotsHandle = myGeom->HArrayFlatKnots(); + if (aFlatKnotsHandle.IsNull()) + { + return NCollection_Array1(); + } + const TColStd_Array1OfReal& aFlatKnots = aFlatKnotsHandle->Array1(); + const Handle(TColgp_HArray1OfPnt)& aPolesHandle = myGeom->HArrayPoles(); if (aPolesHandle.IsNull()) { @@ -607,17 +557,22 @@ NCollection_Array1 GeomGridEval_BSplineCurve::EvaluateGridDN(int theN) c const TColStd_Array1OfInteger& aMults = myGeom->Multiplicities(); const bool isPeriodic = myGeom->IsPeriodic(); + NCollection_Array1 aParamsWithSpan; + NCollection_Array1 aSpanRanges; + prepareParams(theParams, aDegree, isPeriodic, aFlatKnots, aParamsWithSpan, aSpanRanges); + // Use BSplCLib::DN directly with pre-computed span indices - const int aNbRanges = mySpanRanges.Size(); + const int aNbRanges = aSpanRanges.Size(); for (int iRange = 0; iRange < aNbRanges; ++iRange) { - const auto& aRange = mySpanRanges.Value(iRange); + const auto& aRange = aSpanRanges.Value(iRange); const int aSpanIdx = aRange.SpanIndex; for (int i = aRange.StartIdx; i < aRange.EndIdx; ++i) { - gp_Vec aDN; - BSplCLib::DN(myParams.Value(i).Param, + const auto& aP = aParamsWithSpan.Value(i); + gp_Vec aDN; + BSplCLib::DN(aP.Param, theN, aSpanIdx, aDegree, @@ -627,7 +582,7 @@ NCollection_Array1 GeomGridEval_BSplineCurve::EvaluateGridDN(int theN) c aKnots, &aMults, aDN); - aResult.SetValue(i + 1, aDN); + aResult.SetValue(aP.OrigIdx + 1, aDN); } } return aResult; diff --git a/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_BSplineCurve.hxx b/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_BSplineCurve.hxx index 280f575552..1c1cf2df7f 100644 --- a/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_BSplineCurve.hxx +++ b/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_BSplineCurve.hxx @@ -25,7 +25,7 @@ //! @brief Efficient batch evaluator for B-spline curve grid points. //! //! Optimizes evaluation of multiple points on a B-spline curve by: -//! - Pre-computing span indices during parameter setup (no runtime binary search) +//! - 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 HArrayFlatKnots() from Geom_BSplineCurve for direct flat knot access @@ -33,8 +33,7 @@ //! Usage: //! @code //! GeomGridEval_BSplineCurve anEvaluator(myBSplineCurve); -//! anEvaluator.SetParams(myParams); -//! NCollection_Array1 aGrid = anEvaluator.EvaluateGrid(); +//! NCollection_Array1 aGrid = anEvaluator.EvaluateGrid(myParams); //! @endcode class GeomGridEval_BSplineCurve { @@ -54,103 +53,49 @@ public: GeomGridEval_BSplineCurve(GeomGridEval_BSplineCurve&&) = delete; GeomGridEval_BSplineCurve& operator=(GeomGridEval_BSplineCurve&&) = delete; - //! Parameter value with pre-computed span index and local parameter. - struct ParamWithSpan - { - double Param; //!< Original parameter value - double LocalParam; //!< Pre-computed local parameter in [0, 1] range for polynomial evaluation - int SpanIndex; //!< Flat knot index identifying the span - }; - - //! Range of parameter indices belonging to the same span. - struct SpanRange - { - int SpanIndex; //!< Flat knot index of this span - int StartIdx; //!< First parameter index (0-based, inclusive) - int EndIdx; //!< Past-the-end parameter index (exclusive) - double SpanMid; //!< Midpoint of span (for cache convention: start + length/2) - double SpanHalfLen; //!< Half-length of span (for cache convention: length/2) - }; - - //! Set parameters for grid evaluation (by const reference). - //! Span indices and local parameters are pre-computed for optimal EvaluateGrid() performance. - //! @param theParams array of parameter values - Standard_EXPORT void SetParams(const TColStd_Array1OfReal& theParams); - - //! Set parameters for grid evaluation (by move). - //! @param theParams array of parameter values to move - void SetParams(NCollection_Array1&& theParams) - { - myRawParams = std::move(theParams); - mySpanRanges = NCollection_Array1(); // Clear cached span data - } - //! Returns the geometry handle. const Handle(Geom_BSplineCurve)& Geometry() const { return myGeom; } - //! Returns number of parameters. - int NbParams() const { return myRawParams.Size(); } - //! 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 set - Standard_EXPORT NCollection_Array1 EvaluateGrid() const; + //! or empty array if geometry is null or no parameters + Standard_EXPORT NCollection_Array1 EvaluateGrid( + const TColStd_Array1OfReal& 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 set - Standard_EXPORT NCollection_Array1 EvaluateGridD1() const; + //! or empty array if geometry is null or no parameters + Standard_EXPORT NCollection_Array1 EvaluateGridD1( + const TColStd_Array1OfReal& 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 set - Standard_EXPORT NCollection_Array1 EvaluateGridD2() const; + //! or empty array if geometry is null or no parameters + Standard_EXPORT NCollection_Array1 EvaluateGridD2( + const TColStd_Array1OfReal& 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 set - Standard_EXPORT NCollection_Array1 EvaluateGridD3() const; + //! or empty array if geometry is null or no parameters + Standard_EXPORT NCollection_Array1 EvaluateGridD3( + const TColStd_Array1OfReal& theParams) const; //! Evaluate Nth derivative at all grid points. //! For orders 1-3, reuses EvaluateGridD1/D2/D3. //! For orders > 3, uses geometry 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 EvaluateGridDN(int theN) const; - -private: - //! Find span index for a parameter value. - int locateSpan(double theParam, const TColStd_Array1OfReal& theFlatKnots) const; - - //! Find span index with a hint for better performance on sorted parameters. - int locateSpanWithHint(double theParam, - int theHint, - const TColStd_Array1OfReal& theFlatKnots) const; - - //! Compute span ranges from parameters array. - static void computeSpanRanges(const NCollection_Array1& theParams, - const TColStd_Array1OfReal& theFlatKnots, - NCollection_Array1& theSpanRanges); - - //! Prepare internal data structures from raw parameters. - //! Called lazily from EvaluateGrid() when mySpanRanges is empty. - void prepare() const; + Standard_EXPORT NCollection_Array1 EvaluateGridDN(const TColStd_Array1OfReal& theParams, + int theN) const; private: Handle(Geom_BSplineCurve) myGeom; - - // Raw parameters storage - NCollection_Array1 myRawParams; - - // Pre-computed parameters with span indices (0-based indexing internally) - mutable NCollection_Array1 myParams; - - // Pre-computed span ranges for optimized iteration (empty = not prepared) - mutable NCollection_Array1 mySpanRanges; - - // Cache for efficient evaluation within spans - mutable Handle(BSplCLib_Cache) myCache; }; #endif // _GeomGridEval_BSplineCurve_HeaderFile diff --git a/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_BSplineSurface.cxx b/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_BSplineSurface.cxx index 41241eaf12..916fe6156a 100644 --- a/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_BSplineSurface.cxx +++ b/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_BSplineSurface.cxx @@ -13,14 +13,13 @@ #include +#include #include #include -#include #include -#include -#include -#include +#include #include +#include namespace { @@ -28,88 +27,71 @@ namespace //! For small spans (few points), direct BSplSLib evaluation is faster than building cache. constexpr int THE_CACHE_THRESHOLD = 4; -//! Minimum number of points along varying dimension to use isoline optimization. -//! For small grids (e.g., 1x4), cache-based surface evaluation is faster than -//! extracting an isoline curve and setting up a curve evaluator. -constexpr int THE_ISOLINE_THRESHOLD = 8; - -//! @brief Iterates over UV span blocks and invokes evaluation functors. +//! @brief Iterates over sorted UV points with cache-optimal span grouping. //! -//! This helper encapsulates the common pattern of iterating over pre-computed span ranges, -//! deciding whether to use cache or direct evaluation based on block size, and invoking -//! the appropriate evaluation functor. +//! This helper processes UV points that have been sorted by (USpanIdx, VSpanIdx, U). +//! It tracks span changes and decides whether to use cache or direct evaluation +//! based on the number of points in each span group. //! -//! @tparam CacheEvalFunc Functor type for cache-based evaluation: void(int iu, int iv, double -//! uParam, double vParam) -//! @tparam DirectEvalFunc Functor type for direct evaluation: void(int iu, int iv, double uParam, -//! double vParam, int uSpanIdx, int vSpanIdx) +//! @tparam BuildCacheFunc Functor type for cache initialization: void(double U, double V) +//! @tparam CacheEvalFunc Functor type for cache-based evaluation: void(const UVPointWithSpan& pt) +//! @tparam DirectEvalFunc Functor type for direct evaluation: void(const UVPointWithSpan& pt) //! -//! @param theUSpanRanges Pre-computed U span ranges -//! @param theVSpanRanges Pre-computed V span ranges -//! @param theUParams U parameters with span info -//! @param theVParams V parameters with span info -//! @param theBuildCache Functor that rebuilds cache for a span block -//! @param theCacheEval Functor called for cache evaluation (large blocks) -//! @param theDirectEval Functor called for direct evaluation (small blocks) +//! @param theUVPoints Sorted UV points with span info +//! @param theBuildCache Functor to rebuild cache for a span +//! @param theCacheEval Functor called for cache-based evaluation (large spans) +//! @param theDirectEval Functor called for direct evaluation (small spans) template -void iterateSpanBlocks( - const NCollection_Array1& theUSpanRanges, - const NCollection_Array1& theVSpanRanges, - const NCollection_Array1& theUParams, - const NCollection_Array1& theVParams, - BuildCacheFunc&& theBuildCache, - CacheEvalFunc&& theCacheEval, - DirectEvalFunc&& theDirectEval) +void iterateSortedUVPoints(const NCollection_Array1& theUVPoints, + BuildCacheFunc&& theBuildCache, + CacheEvalFunc&& theCacheEval, + DirectEvalFunc&& theDirectEval) { - const int aNbUSpans = theUSpanRanges.Size(); - const int aNbVSpans = theVSpanRanges.Size(); - - for (int iURange = 0; iURange < aNbUSpans; ++iURange) + const int aNbPoints = theUVPoints.Size(); + if (aNbPoints == 0) { - const auto& aURange = theUSpanRanges.Value(iURange); - const int aNbUInSpan = aURange.EndIdx - aURange.StartIdx; + return; + } - for (int iVRange = 0; iVRange < aNbVSpans; ++iVRange) + int i = 0; + while (i < aNbPoints) + { + const GeomGridEval::UVPointWithSpan& aFirstPt = theUVPoints.Value(i); + const int aUSpan = aFirstPt.USpanIdx; + const int aVSpan = aFirstPt.VSpanIdx; + + // Count points in this span group + int aGroupEnd = i + 1; + while (aGroupEnd < aNbPoints) { - const auto& aVRange = theVSpanRanges.Value(iVRange); - const int aNbVInSpan = aVRange.EndIdx - aVRange.StartIdx; - const int aNbPoints = aNbUInSpan * aNbVInSpan; - - if (aNbPoints >= THE_CACHE_THRESHOLD) + const GeomGridEval::UVPointWithSpan& aPt = theUVPoints.Value(aGroupEnd); + if (aPt.USpanIdx != aUSpan || aPt.VSpanIdx != aVSpan) { - // Large block: use cache - theBuildCache(theUParams.Value(aURange.StartIdx).Param, - theVParams.Value(aVRange.StartIdx).Param); - - for (int iu = aURange.StartIdx; iu < aURange.EndIdx; ++iu) - { - const double aLocalU = theUParams.Value(iu).LocalParam; - for (int iv = aVRange.StartIdx; iv < aVRange.EndIdx; ++iv) - { - theCacheEval(iu, iv, aLocalU, theVParams.Value(iv).LocalParam); - } - } + break; } - else - { - // Small block: direct evaluation - for (int iu = aURange.StartIdx; iu < aURange.EndIdx; ++iu) - { - const double aUParam = theUParams.Value(iu).Param; - const int aUSpanIdx = aURange.SpanIndex; + ++aGroupEnd; + } + const int aGroupSize = aGroupEnd - i; - for (int iv = aVRange.StartIdx; iv < aVRange.EndIdx; ++iv) - { - theDirectEval(iu, - iv, - aUParam, - theVParams.Value(iv).Param, - aUSpanIdx, - aVRange.SpanIndex); - } - } + if (aGroupSize >= THE_CACHE_THRESHOLD) + { + // Large group: use cache-based evaluation + theBuildCache(aFirstPt.U, aFirstPt.V); + for (int j = i; j < aGroupEnd; ++j) + { + theCacheEval(theUVPoints.Value(j)); } } + else + { + // Small group: use direct evaluation (skip cache building) + for (int j = i; j < aGroupEnd; ++j) + { + theDirectEval(theUVPoints.Value(j)); + } + } + + i = aGroupEnd; } } @@ -117,47 +99,66 @@ void iterateSpanBlocks( //================================================================================================== -void GeomGridEval_BSplineSurface::SetUVParams(const TColStd_Array1OfReal& theUParams, - const TColStd_Array1OfReal& theVParams) +void GeomGridEval_BSplineSurface::prepareGridPoints( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams, + NCollection_Array1& theUVPoints) const { - const int aNbU = theUParams.Size(); - const int aNbV = theVParams.Size(); + const int aNbU = theUParams.Size(); + const int aNbV = theVParams.Size(); + const int aNbPoints = aNbU * aNbV; + const int aULower = theUParams.Lower(); + const int aVLower = theVParams.Lower(); - myRawUParams.Resize(1, aNbU, false); - for (int i = 1; i <= aNbU; ++i) + theUVPoints.Resize(0, aNbPoints - 1, false); + + int aIdx = 0; + for (int i = 0; i < aNbU; ++i) { - myRawUParams.SetValue(i, theUParams.Value(theUParams.Lower() + i - 1)); + const double aU = theUParams.Value(aULower + i); + for (int j = 0; j < aNbV; ++j) + { + const double aV = theVParams.Value(aVLower + j); + const int aOutIdx = i * aNbV + j; // Row-major linear index + theUVPoints.SetValue(aIdx++, GeomGridEval::UVPointWithSpan{aU, aV, 0.0, 0.0, 0, 0, aOutIdx}); + } } - myRawVParams.Resize(1, aNbV, false); - for (int j = 1; j <= aNbV; ++j) - { - myRawVParams.SetValue(j, theVParams.Value(theVParams.Lower() + j - 1)); - } - - // Clear cached data - myUSpanRanges = NCollection_Array1(); - myVSpanRanges = NCollection_Array1(); - myCache.Nullify(); + computeSpansAndSort(theUVPoints); } //================================================================================================== -void GeomGridEval_BSplineSurface::prepare() const +void GeomGridEval_BSplineSurface::preparePairPoints( + const NCollection_Array1& theUVPairs, + NCollection_Array1& theUVPoints) const { - // Check if already prepared using span ranges emptiness - if (!myUSpanRanges.IsEmpty()) + const int aNbPairs = theUVPairs.IsEmpty() ? 0 : theUVPairs.Size(); + if (aNbPairs == 0) { + theUVPoints = NCollection_Array1(); return; } - if (myGeom.IsNull() || myRawUParams.IsEmpty() || myRawVParams.IsEmpty()) + theUVPoints.Resize(0, aNbPairs - 1, false); + + const int aLower = theUVPairs.Lower(); + for (int i = 0; i < aNbPairs; ++i) + { + const gp_Pnt2d& aUV = theUVPairs.Value(aLower + i); + theUVPoints.SetValue(i, GeomGridEval::UVPointWithSpan{aUV.X(), aUV.Y(), 0.0, 0.0, 0, 0, i}); + } + + computeSpansAndSort(theUVPoints); +} + +//================================================================================================== + +void GeomGridEval_BSplineSurface::computeSpansAndSort( + NCollection_Array1& theUVPoints) const +{ + if (myGeom.IsNull() || theUVPoints.IsEmpty()) { - myUParams = NCollection_Array1(); - myVParams = NCollection_Array1(); - myUSpanRanges = NCollection_Array1(); - myVSpanRanges = NCollection_Array1(); - myCache.Nullify(); return; } @@ -166,61 +167,51 @@ void GeomGridEval_BSplineSurface::prepare() const const Handle(TColStd_HArray1OfReal)& aVFlatKnotsHandle = myGeom->HArrayVFlatKnots(); if (aUFlatKnotsHandle.IsNull() || aVFlatKnotsHandle.IsNull()) { - myUParams = NCollection_Array1(); - myVParams = NCollection_Array1(); - myUSpanRanges = NCollection_Array1(); - myVSpanRanges = NCollection_Array1(); - myCache.Nullify(); return; } const TColStd_Array1OfReal& aUFlatKnots = aUFlatKnotsHandle->Array1(); const TColStd_Array1OfReal& aVFlatKnots = aVFlatKnotsHandle->Array1(); - const int aUDegree = myGeom->UDegree(); - const int aVDegree = myGeom->VDegree(); + // Compute span indices and local parameters for each point + const int aNbPoints = theUVPoints.Size(); - const int aNbU = myRawUParams.Size(); - const int aNbV = myRawVParams.Size(); - - // Process U parameters - myUParams.Resize(0, aNbU - 1, false); - - int aPrevUSpan = aUFlatKnots.Lower() + aUDegree; - for (int i = 1; i <= aNbU; ++i) + for (int i = 0; i < aNbPoints; ++i) { - double aParam = myRawUParams.Value(i); - const int aSpanIdx = locateSpanWithHint(aParam, true, aPrevUSpan, aUFlatKnots); - aPrevUSpan = aSpanIdx; + GeomGridEval::UVPointWithSpan& aPt = theUVPoints.ChangeValue(i); - const double aSpanStart = aUFlatKnots.Value(aSpanIdx); - const double aSpanHalfLen = 0.5 * (aUFlatKnots.Value(aSpanIdx + 1) - aSpanStart); - const double aSpanMid = aSpanStart + aSpanHalfLen; - const double aLocalParam = (aParam - aSpanMid) / aSpanHalfLen; + // Locate U span + double aUParam = aPt.U; + int aUSpanIdx = locateSpan(aUParam, true, aUFlatKnots); + aPt.U = aUParam; // May be adjusted for periodicity + aPt.USpanIdx = aUSpanIdx; - myUParams.SetValue(i - 1, ParamWithSpan{aParam, aLocalParam, aSpanIdx}); + const double aUSpanStart = aUFlatKnots.Value(aUSpanIdx); + const double aUSpanHalfLen = 0.5 * (aUFlatKnots.Value(aUSpanIdx + 1) - aUSpanStart); + const double aUSpanMid = aUSpanStart + aUSpanHalfLen; + aPt.LocalU = (aPt.U - aUSpanMid) / aUSpanHalfLen; + + // Locate V span + double aVParam = aPt.V; + int aVSpanIdx = locateSpan(aVParam, false, aVFlatKnots); + aPt.V = aVParam; // May be adjusted for periodicity + aPt.VSpanIdx = aVSpanIdx; + + const double aVSpanStart = aVFlatKnots.Value(aVSpanIdx); + const double aVSpanHalfLen = 0.5 * (aVFlatKnots.Value(aVSpanIdx + 1) - aVSpanStart); + const double aVSpanMid = aVSpanStart + aVSpanHalfLen; + aPt.LocalV = (aPt.V - aVSpanMid) / aVSpanHalfLen; } - // Process V parameters - myVParams.Resize(0, aNbV - 1, false); - - int aPrevVSpan = aVFlatKnots.Lower() + aVDegree; - for (int j = 1; j <= aNbV; ++j) - { - double aParam = myRawVParams.Value(j); - const int aSpanIdx = locateSpanWithHint(aParam, false, aPrevVSpan, aVFlatKnots); - aPrevVSpan = aSpanIdx; - - const double aSpanStart = aVFlatKnots.Value(aSpanIdx); - const double aSpanHalfLen = 0.5 * (aVFlatKnots.Value(aSpanIdx + 1) - aSpanStart); - const double aSpanMid = aSpanStart + aSpanHalfLen; - const double aLocalParam = (aParam - aSpanMid) / aSpanHalfLen; - - myVParams.SetValue(j - 1, ParamWithSpan{aParam, aLocalParam, aSpanIdx}); - } - - // Compute span ranges - computeSpanRanges(myUParams, aUFlatKnots, myUSpanRanges); - computeSpanRanges(myVParams, aVFlatKnots, myVSpanRanges); + // Sort by (USpanIdx, VSpanIdx, U) for cache-optimal iteration + std::sort(theUVPoints.begin(), + theUVPoints.end(), + [](const GeomGridEval::UVPointWithSpan& a, const GeomGridEval::UVPointWithSpan& b) { + if (a.USpanIdx != b.USpanIdx) + return a.USpanIdx < b.USpanIdx; + if (a.VSpanIdx != b.VSpanIdx) + return a.VSpanIdx < b.VSpanIdx; + return a.U < b.U; + }); } //================================================================================================== @@ -248,208 +239,80 @@ int GeomGridEval_BSplineSurface::locateSpan(double& theParam //================================================================================================== -int GeomGridEval_BSplineSurface::locateSpanWithHint(double& theParam, - bool theUDir, - int theHint, - const TColStd_Array1OfReal& theFlatKnots) const +NCollection_Array2 GeomGridEval_BSplineSurface::EvaluateGrid( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams) const { - const int aDegree = theUDir ? myGeom->UDegree() : myGeom->VDegree(); - const int aLower = theFlatKnots.Lower() + aDegree; - const int aUpper = theFlatKnots.Upper() - aDegree - 1; - - if (theHint >= aLower && theHint <= aUpper) - { - const double aSpanStart = theFlatKnots.Value(theHint); - const double aSpanEnd = theFlatKnots.Value(theHint + 1); - - if (theParam >= aSpanStart && theParam < aSpanEnd) - { - return theHint; - } - - if (theHint < aUpper && theParam >= aSpanEnd) - { - const double aNextEnd = theFlatKnots.Value(theHint + 2); - if (theParam < aNextEnd) - { - return theHint + 1; - } - } - } - - return locateSpan(theParam, theUDir, theFlatKnots); -} - -//================================================================================================== - -void GeomGridEval_BSplineSurface::computeSpanRanges( - const NCollection_Array1& theParams, - const TColStd_Array1OfReal& theFlatKnots, - NCollection_Array1& theSpanRanges) -{ - const int aNbParams = theParams.Size(); - if (aNbParams == 0) - { - theSpanRanges = NCollection_Array1(); - return; - } - - // Count distinct spans - int aNbRanges = 1; - int aCurrentSpan = theParams.Value(0).SpanIndex; - for (int i = 1; i < aNbParams; ++i) - { - if (theParams.Value(i).SpanIndex != aCurrentSpan) - { - ++aNbRanges; - aCurrentSpan = theParams.Value(i).SpanIndex; - } - } - - theSpanRanges.Resize(0, aNbRanges - 1, false); - - // Fill ranges - aCurrentSpan = theParams.Value(0).SpanIndex; - int aRangeStart = 0; - int aRangeIdx = 0; - - for (int i = 1; i < aNbParams; ++i) - { - if (theParams.Value(i).SpanIndex != aCurrentSpan) - { - const double aSpanStart = theFlatKnots.Value(aCurrentSpan); - const double aSpanHalfLen = 0.5 * (theFlatKnots.Value(aCurrentSpan + 1) - aSpanStart); - const double aSpanMid = aSpanStart + aSpanHalfLen; - - theSpanRanges.SetValue(aRangeIdx++, - SpanRange{aCurrentSpan, aRangeStart, i, aSpanMid, aSpanHalfLen}); - aCurrentSpan = theParams.Value(i).SpanIndex; - aRangeStart = i; - } - } - - // Last range - const double aSpanStart = theFlatKnots.Value(aCurrentSpan); - const double aSpanHalfLen = 0.5 * (theFlatKnots.Value(aCurrentSpan + 1) - aSpanStart); - const double aSpanMid = aSpanStart + aSpanHalfLen; - - theSpanRanges.SetValue(aRangeIdx, - SpanRange{aCurrentSpan, aRangeStart, aNbParams, aSpanMid, aSpanHalfLen}); -} - -//================================================================================================== - -NCollection_Array2 GeomGridEval_BSplineSurface::EvaluateGrid() const -{ - if (myGeom.IsNull() || myRawUParams.IsEmpty() || myRawVParams.IsEmpty()) + if (myGeom.IsNull() || theUParams.IsEmpty() || theVParams.IsEmpty()) { return NCollection_Array2(); } - const int aNbU = myRawUParams.Size(); - const int aNbV = myRawVParams.Size(); + const int aNbU = theUParams.Size(); + const int aNbV = theVParams.Size(); - // Check for V-isoline case (Nx1) - use 1D curve evaluation - // For U-isoline (1xN), cache-based surface evaluation is efficient since U span is fixed. - // For V-isoline (Nx1), extracting the isoline curve avoids repeated U span transitions. - // Only use isoline optimization when varying dimension is large enough. - const bool isVIso = (aNbV == 1 && aNbU >= THE_ISOLINE_THRESHOLD); + // Prepare UV points and sort by span + NCollection_Array1 aUVPoints; + prepareGridPoints(theUParams, theVParams, aUVPoints); - if (isVIso) - { - try - { - OCC_CATCH_SIGNALS - // Extract V-isoline curve (parameterized by U) - Handle(Geom_Curve) aCurve = myGeom->VIso(myRawVParams.Value(1)); - - if (!aCurve.IsNull()) - { - // Use unified curve evaluator - GeomGridEval_Curve aCurveEval; - aCurveEval.Initialize(aCurve); - aCurveEval.SetParams(myRawUParams); - NCollection_Array1 aCurveResult = aCurveEval.EvaluateGrid(); - - // Reshape 1D curve result to 2D surface result (Nx1 grid) - NCollection_Array2 aResult(1, aNbU, 1, 1); - for (int k = 1; k <= aNbU; ++k) - { - aResult(k, 1) = aCurveResult(k); - } - return aResult; - } - } - catch (const Standard_Failure&) - { - // Isoline extraction failed, fall through to surface evaluation - } - } - - prepare(); - - if (aNbU == 0 || aNbV == 0 || myUSpanRanges.IsEmpty() || myVSpanRanges.IsEmpty()) + if (aUVPoints.IsEmpty()) { return NCollection_Array2(); } - NCollection_Array2 aPoints(1, aNbU, 1, aNbV); - + // Get surface data from geometry const Handle(TColStd_HArray1OfReal)& aUFlatKnotsHandle = myGeom->HArrayUFlatKnots(); const Handle(TColStd_HArray1OfReal)& aVFlatKnotsHandle = myGeom->HArrayVFlatKnots(); - if (aUFlatKnotsHandle.IsNull() || aVFlatKnotsHandle.IsNull()) + const Handle(TColgp_HArray2OfPnt)& aPolesHandle = myGeom->HArrayPoles(); + + if (aUFlatKnotsHandle.IsNull() || aVFlatKnotsHandle.IsNull() || aPolesHandle.IsNull()) { return NCollection_Array2(); } + const TColStd_Array1OfReal& aUFlatKnots = aUFlatKnotsHandle->Array1(); const TColStd_Array1OfReal& aVFlatKnots = aVFlatKnotsHandle->Array1(); + const TColgp_Array2OfPnt& aPoles = aPolesHandle->Array2(); + const TColStd_Array2OfReal* aWeights = myGeom->Weights(); + // Get surface properties for direct evaluation const int aUDegree = myGeom->UDegree(); const int aVDegree = myGeom->VDegree(); - const bool isURational = myGeom->IsURational(); - const bool isVRational = myGeom->IsVRational(); const bool isUPeriodic = myGeom->IsUPeriodic(); const bool isVPeriodic = myGeom->IsVPeriodic(); + const bool isURational = myGeom->IsURational(); + const bool isVRational = myGeom->IsVRational(); - const Handle(TColgp_HArray2OfPnt)& aPolesHandle = myGeom->HArrayPoles(); - if (aPolesHandle.IsNull()) - { - return NCollection_Array2(); - } - const TColgp_Array2OfPnt& aPoles = aPolesHandle->Array2(); + // Allocate linear result buffer + const int aNbPoints = aNbU * aNbV; + NCollection_Array1 aLinearResult(1, aNbPoints); - const TColStd_Array2OfReal* aWeights = myGeom->Weights(); + // Create local cache for cache-based evaluation (only used for large span groups) + Handle(BSplSLib_Cache) aCache = new BSplSLib_Cache(aUDegree, + isUPeriodic, + aUFlatKnots, + aVDegree, + isVPeriodic, + aVFlatKnots, + aWeights); - if (myCache.IsNull()) - { - myCache = new BSplSLib_Cache(aUDegree, - myGeom->IsUPeriodic(), - aUFlatKnots, - aVDegree, - myGeom->IsVPeriodic(), - aVFlatKnots, - aWeights); - } - - // Use helper with lambdas for cache and direct evaluation - iterateSpanBlocks( - myUSpanRanges, - myVSpanRanges, - myUParams, - myVParams, - [&](double theUParam, double theVParam) { - myCache->BuildCache(theUParam, theVParam, aUFlatKnots, aVFlatKnots, aPoles, aWeights); + // Evaluate using sorted UV points + iterateSortedUVPoints( + aUVPoints, + [&](double theU, double theV) { + aCache->BuildCache(theU, theV, aUFlatKnots, aVFlatKnots, aPoles, aWeights); }, - // Cache evaluation (local parameters) - [&](int iu, int iv, double theLocalU, double theLocalV) { - myCache->D0Local(theLocalU, theLocalV, aPoints.ChangeValue(iu + 1, iv + 1)); + [&](const GeomGridEval::UVPointWithSpan& thePt) { + gp_Pnt aPnt; + aCache->D0Local(thePt.LocalU, thePt.LocalV, aPnt); + aLinearResult.SetValue(thePt.OutputIdx + 1, aPnt); }, - // Direct evaluation (global parameters + span indices) - [&](int iu, int iv, double theUParam, double theVParam, int theUSpanIdx, int theVSpanIdx) { - BSplSLib::D0(theUParam, - theVParam, - theUSpanIdx, - theVSpanIdx, + [&](const GeomGridEval::UVPointWithSpan& thePt) { + gp_Pnt aPnt; + BSplSLib::D0(thePt.U, + thePt.V, + thePt.USpanIdx, + thePt.VSpanIdx, aPoles, aWeights, aUFlatKnots, @@ -462,7 +325,109 @@ NCollection_Array2 GeomGridEval_BSplineSurface::EvaluateGrid() const isVRational, isUPeriodic, isVPeriodic, - aPoints.ChangeValue(iu + 1, iv + 1)); + aPnt); + aLinearResult.SetValue(thePt.OutputIdx + 1, aPnt); + }); + + // Reshape linear buffer to 2D grid + NCollection_Array2 aGrid(1, aNbU, 1, aNbV); + for (int i = 0; i < aNbU; ++i) + { + for (int j = 0; j < aNbV; ++j) + { + const int aLinIdx = i * aNbV + j; + aGrid.SetValue(i + 1, j + 1, aLinearResult.Value(aLinIdx + 1)); + } + } + return aGrid; +} + +//================================================================================================== + +NCollection_Array1 GeomGridEval_BSplineSurface::EvaluatePoints( + const NCollection_Array1& theUVPairs) const +{ + if (myGeom.IsNull() || theUVPairs.IsEmpty()) + { + return NCollection_Array1(); + } + + // Prepare UV points and sort by span + NCollection_Array1 aUVPoints; + preparePairPoints(theUVPairs, aUVPoints); + + const int aNbPoints = aUVPoints.Size(); + if (aNbPoints == 0) + { + return NCollection_Array1(); + } + + // Get surface data from geometry + const Handle(TColStd_HArray1OfReal)& aUFlatKnotsHandle = myGeom->HArrayUFlatKnots(); + const Handle(TColStd_HArray1OfReal)& aVFlatKnotsHandle = myGeom->HArrayVFlatKnots(); + const Handle(TColgp_HArray2OfPnt)& aPolesHandle = myGeom->HArrayPoles(); + + if (aUFlatKnotsHandle.IsNull() || aVFlatKnotsHandle.IsNull() || aPolesHandle.IsNull()) + { + return NCollection_Array1(); + } + + const TColStd_Array1OfReal& aUFlatKnots = aUFlatKnotsHandle->Array1(); + const TColStd_Array1OfReal& aVFlatKnots = aVFlatKnotsHandle->Array1(); + const TColgp_Array2OfPnt& aPoles = aPolesHandle->Array2(); + const TColStd_Array2OfReal* aWeights = myGeom->Weights(); + + // Get surface properties for direct evaluation + const int aUDegree = myGeom->UDegree(); + const int aVDegree = myGeom->VDegree(); + const bool isUPeriodic = myGeom->IsUPeriodic(); + const bool isVPeriodic = myGeom->IsVPeriodic(); + const bool isURational = myGeom->IsURational(); + const bool isVRational = myGeom->IsVRational(); + + // Allocate result buffer (1-based indexing) + NCollection_Array1 aPoints(1, aNbPoints); + + // Create local cache for cache-based evaluation (only used for large span groups) + Handle(BSplSLib_Cache) aCache = new BSplSLib_Cache(aUDegree, + isUPeriodic, + aUFlatKnots, + aVDegree, + isVPeriodic, + aVFlatKnots, + aWeights); + + // Evaluate using sorted UV points + iterateSortedUVPoints( + aUVPoints, + [&](double theU, double theV) { + aCache->BuildCache(theU, theV, aUFlatKnots, aVFlatKnots, aPoles, aWeights); + }, + [&](const GeomGridEval::UVPointWithSpan& thePt) { + gp_Pnt aPnt; + aCache->D0Local(thePt.LocalU, thePt.LocalV, aPnt); + aPoints.SetValue(thePt.OutputIdx + 1, aPnt); + }, + [&](const GeomGridEval::UVPointWithSpan& thePt) { + gp_Pnt aPnt; + BSplSLib::D0(thePt.U, + thePt.V, + thePt.USpanIdx, + thePt.VSpanIdx, + aPoles, + aWeights, + aUFlatKnots, + aVFlatKnots, + nullptr, + nullptr, + aUDegree, + aVDegree, + isURational, + isVRational, + isUPeriodic, + isVPeriodic, + aPnt); + aPoints.SetValue(thePt.OutputIdx + 1, aPnt); }); return aPoints; @@ -470,85 +435,108 @@ NCollection_Array2 GeomGridEval_BSplineSurface::EvaluateGrid() const //================================================================================================== -NCollection_Array2 GeomGridEval_BSplineSurface::EvaluateGridD1() const +NCollection_Array2 GeomGridEval_BSplineSurface::EvaluateGridD1( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams) const { - if (myGeom.IsNull() || myRawUParams.IsEmpty() || myRawVParams.IsEmpty()) + if (myGeom.IsNull() || theUParams.IsEmpty() || theVParams.IsEmpty()) { return NCollection_Array2(); } - prepare(); + const int aNbU = theUParams.Size(); + const int aNbV = theVParams.Size(); - const int aNbUParams = myUParams.Size(); - const int aNbVParams = myVParams.Size(); - - if (aNbUParams == 0 || aNbVParams == 0 || myUSpanRanges.IsEmpty() || myVSpanRanges.IsEmpty()) + NCollection_Array1 aLinearResult = EvaluatePointsD1(theUParams, theVParams); + if (aLinearResult.IsEmpty()) { return NCollection_Array2(); } - NCollection_Array2 aResults(1, aNbUParams, 1, aNbVParams); + NCollection_Array2 aGrid(1, aNbU, 1, aNbV); + for (int i = 0; i < aNbU; ++i) + { + for (int j = 0; j < aNbV; ++j) + { + const int aLinIdx = i * aNbV + j; + aGrid.SetValue(i + 1, j + 1, aLinearResult.Value(aLinIdx + 1)); + } + } + return aGrid; +} +//================================================================================================== + +NCollection_Array1 GeomGridEval_BSplineSurface::EvaluatePointsD1( + const NCollection_Array1& theUVPairs) const +{ + if (myGeom.IsNull() || theUVPairs.IsEmpty()) + { + return NCollection_Array1(); + } + + // Prepare UV points and sort by span + NCollection_Array1 aUVPoints; + preparePairPoints(theUVPairs, aUVPoints); + + const int aNbPoints = aUVPoints.Size(); + if (aNbPoints == 0) + { + return NCollection_Array1(); + } + + // Get surface data from geometry const Handle(TColStd_HArray1OfReal)& aUFlatKnotsHandle = myGeom->HArrayUFlatKnots(); const Handle(TColStd_HArray1OfReal)& aVFlatKnotsHandle = myGeom->HArrayVFlatKnots(); - if (aUFlatKnotsHandle.IsNull() || aVFlatKnotsHandle.IsNull()) + const Handle(TColgp_HArray2OfPnt)& aPolesHandle = myGeom->HArrayPoles(); + + if (aUFlatKnotsHandle.IsNull() || aVFlatKnotsHandle.IsNull() || aPolesHandle.IsNull()) { - return NCollection_Array2(); + return NCollection_Array1(); } + const TColStd_Array1OfReal& aUFlatKnots = aUFlatKnotsHandle->Array1(); const TColStd_Array1OfReal& aVFlatKnots = aVFlatKnotsHandle->Array1(); + const TColgp_Array2OfPnt& aPoles = aPolesHandle->Array2(); + const TColStd_Array2OfReal* aWeights = myGeom->Weights(); + // Get surface properties for direct evaluation const int aUDegree = myGeom->UDegree(); const int aVDegree = myGeom->VDegree(); - const bool isURational = myGeom->IsURational(); - const bool isVRational = myGeom->IsVRational(); const bool isUPeriodic = myGeom->IsUPeriodic(); const bool isVPeriodic = myGeom->IsVPeriodic(); + const bool isURational = myGeom->IsURational(); + const bool isVRational = myGeom->IsVRational(); - const Handle(TColgp_HArray2OfPnt)& aPolesHandle = myGeom->HArrayPoles(); - if (aPolesHandle.IsNull()) - { - return NCollection_Array2(); - } - const TColgp_Array2OfPnt& aPoles = aPolesHandle->Array2(); + NCollection_Array1 aResults(1, aNbPoints); - const TColStd_Array2OfReal* aWeights = myGeom->Weights(); + // Create local cache for cache-based evaluation (only used for large span groups) + Handle(BSplSLib_Cache) aCache = new BSplSLib_Cache(aUDegree, + isUPeriodic, + aUFlatKnots, + aVDegree, + isVPeriodic, + aVFlatKnots, + aWeights); - if (myCache.IsNull()) - { - myCache = new BSplSLib_Cache(aUDegree, - myGeom->IsUPeriodic(), - aUFlatKnots, - aVDegree, - myGeom->IsVPeriodic(), - aVFlatKnots, - aWeights); - } - - // Use helper with lambdas for cache and direct evaluation - iterateSpanBlocks( - myUSpanRanges, - myVSpanRanges, - myUParams, - myVParams, - [&](double theUParam, double theVParam) { - myCache->BuildCache(theUParam, theVParam, aUFlatKnots, aVFlatKnots, aPoles, aWeights); + iterateSortedUVPoints( + aUVPoints, + [&](double theU, double theV) { + aCache->BuildCache(theU, theV, aUFlatKnots, aVFlatKnots, aPoles, aWeights); }, - // Cache evaluation (local parameters) - [&](int iu, int iv, double theLocalU, double theLocalV) { + [&](const GeomGridEval::UVPointWithSpan& thePt) { gp_Pnt aPoint; gp_Vec aD1U, aD1V; - myCache->D1Local(theLocalU, theLocalV, aPoint, aD1U, aD1V); - aResults.ChangeValue(iu + 1, iv + 1) = {aPoint, aD1U, aD1V}; + aCache->D1Local(thePt.LocalU, thePt.LocalV, aPoint, aD1U, aD1V); + aResults.SetValue(thePt.OutputIdx + 1, GeomGridEval::SurfD1{aPoint, aD1U, aD1V}); }, - // Direct evaluation (global parameters + span indices) - [&](int iu, int iv, double theUParam, double theVParam, int theUSpanIdx, int theVSpanIdx) { + [&](const GeomGridEval::UVPointWithSpan& thePt) { gp_Pnt aPoint; gp_Vec aD1U, aD1V; - BSplSLib::D1(theUParam, - theVParam, - theUSpanIdx, - theVSpanIdx, + BSplSLib::D1(thePt.U, + thePt.V, + thePt.USpanIdx, + thePt.VSpanIdx, aPoles, aWeights, aUFlatKnots, @@ -564,7 +552,7 @@ NCollection_Array2 GeomGridEval_BSplineSurface::EvaluateGr aPoint, aD1U, aD1V); - aResults.ChangeValue(iu + 1, iv + 1) = {aPoint, aD1U, aD1V}; + aResults.SetValue(thePt.OutputIdx + 1, GeomGridEval::SurfD1{aPoint, aD1U, aD1V}); }); return aResults; @@ -572,85 +560,109 @@ NCollection_Array2 GeomGridEval_BSplineSurface::EvaluateGr //================================================================================================== -NCollection_Array2 GeomGridEval_BSplineSurface::EvaluateGridD2() const +NCollection_Array2 GeomGridEval_BSplineSurface::EvaluateGridD2( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams) const { - if (myGeom.IsNull() || myRawUParams.IsEmpty() || myRawVParams.IsEmpty()) + if (myGeom.IsNull() || theUParams.IsEmpty() || theVParams.IsEmpty()) { return NCollection_Array2(); } - prepare(); + const int aNbU = theUParams.Size(); + const int aNbV = theVParams.Size(); - const int aNbUParams = myUParams.Size(); - const int aNbVParams = myVParams.Size(); - - if (aNbUParams == 0 || aNbVParams == 0 || myUSpanRanges.IsEmpty() || myVSpanRanges.IsEmpty()) + NCollection_Array1 aLinearResult = EvaluatePointsD2(theUParams, theVParams); + if (aLinearResult.IsEmpty()) { return NCollection_Array2(); } - NCollection_Array2 aResults(1, aNbUParams, 1, aNbVParams); + NCollection_Array2 aGrid(1, aNbU, 1, aNbV); + for (int i = 0; i < aNbU; ++i) + { + for (int j = 0; j < aNbV; ++j) + { + const int aLinIdx = i * aNbV + j; + aGrid.SetValue(i + 1, j + 1, aLinearResult.Value(aLinIdx + 1)); + } + } + return aGrid; +} +//================================================================================================== + +NCollection_Array1 GeomGridEval_BSplineSurface::EvaluatePointsD2( + const NCollection_Array1& theUVPairs) const +{ + if (myGeom.IsNull() || theUVPairs.IsEmpty()) + { + return NCollection_Array1(); + } + + // Prepare UV points and sort by span + NCollection_Array1 aUVPoints; + preparePairPoints(theUVPairs, aUVPoints); + + const int aNbPoints = aUVPoints.Size(); + if (aNbPoints == 0) + { + return NCollection_Array1(); + } + + // Get surface data from geometry const Handle(TColStd_HArray1OfReal)& aUFlatKnotsHandle = myGeom->HArrayUFlatKnots(); const Handle(TColStd_HArray1OfReal)& aVFlatKnotsHandle = myGeom->HArrayVFlatKnots(); - if (aUFlatKnotsHandle.IsNull() || aVFlatKnotsHandle.IsNull()) + const Handle(TColgp_HArray2OfPnt)& aPolesHandle = myGeom->HArrayPoles(); + + if (aUFlatKnotsHandle.IsNull() || aVFlatKnotsHandle.IsNull() || aPolesHandle.IsNull()) { - return NCollection_Array2(); + return NCollection_Array1(); } + const TColStd_Array1OfReal& aUFlatKnots = aUFlatKnotsHandle->Array1(); const TColStd_Array1OfReal& aVFlatKnots = aVFlatKnotsHandle->Array1(); + const TColgp_Array2OfPnt& aPoles = aPolesHandle->Array2(); + const TColStd_Array2OfReal* aWeights = myGeom->Weights(); + // Get surface properties for direct evaluation const int aUDegree = myGeom->UDegree(); const int aVDegree = myGeom->VDegree(); - const bool isURational = myGeom->IsURational(); - const bool isVRational = myGeom->IsVRational(); const bool isUPeriodic = myGeom->IsUPeriodic(); const bool isVPeriodic = myGeom->IsVPeriodic(); + const bool isURational = myGeom->IsURational(); + const bool isVRational = myGeom->IsVRational(); - const Handle(TColgp_HArray2OfPnt)& aPolesHandle = myGeom->HArrayPoles(); - if (aPolesHandle.IsNull()) - { - return NCollection_Array2(); - } - const TColgp_Array2OfPnt& aPoles = aPolesHandle->Array2(); + NCollection_Array1 aResults(1, aNbPoints); - const TColStd_Array2OfReal* aWeights = myGeom->Weights(); + // Create local cache for cache-based evaluation (only used for large span groups) + Handle(BSplSLib_Cache) aCache = new BSplSLib_Cache(aUDegree, + isUPeriodic, + aUFlatKnots, + aVDegree, + isVPeriodic, + aVFlatKnots, + aWeights); - if (myCache.IsNull()) - { - myCache = new BSplSLib_Cache(aUDegree, - myGeom->IsUPeriodic(), - aUFlatKnots, - aVDegree, - myGeom->IsVPeriodic(), - aVFlatKnots, - aWeights); - } - - // Use helper with lambdas for cache and direct evaluation - iterateSpanBlocks( - myUSpanRanges, - myVSpanRanges, - myUParams, - myVParams, - [&](double theUParam, double theVParam) { - myCache->BuildCache(theUParam, theVParam, aUFlatKnots, aVFlatKnots, aPoles, aWeights); + iterateSortedUVPoints( + aUVPoints, + [&](double theU, double theV) { + aCache->BuildCache(theU, theV, aUFlatKnots, aVFlatKnots, aPoles, aWeights); }, - // Cache evaluation (local parameters) - [&](int iu, int iv, double theLocalU, double theLocalV) { + [&](const GeomGridEval::UVPointWithSpan& thePt) { gp_Pnt aPoint; gp_Vec aD1U, aD1V, aD2U, aD2V, aD2UV; - myCache->D2Local(theLocalU, theLocalV, aPoint, aD1U, aD1V, aD2U, aD2V, aD2UV); - aResults.ChangeValue(iu + 1, iv + 1) = {aPoint, aD1U, aD1V, aD2U, aD2V, aD2UV}; + aCache->D2Local(thePt.LocalU, thePt.LocalV, aPoint, aD1U, aD1V, aD2U, aD2V, aD2UV); + aResults.SetValue(thePt.OutputIdx + 1, + GeomGridEval::SurfD2{aPoint, aD1U, aD1V, aD2U, aD2V, aD2UV}); }, - // Direct evaluation (global parameters + span indices) - [&](int iu, int iv, double theUParam, double theVParam, int theUSpanIdx, int theVSpanIdx) { + [&](const GeomGridEval::UVPointWithSpan& thePt) { gp_Pnt aPoint; gp_Vec aD1U, aD1V, aD2U, aD2V, aD2UV; - BSplSLib::D2(theUParam, - theVParam, - theUSpanIdx, - theVSpanIdx, + BSplSLib::D2(thePt.U, + thePt.V, + thePt.USpanIdx, + thePt.VSpanIdx, aPoles, aWeights, aUFlatKnots, @@ -669,7 +681,8 @@ NCollection_Array2 GeomGridEval_BSplineSurface::EvaluateGr aD2U, aD2V, aD2UV); - aResults.ChangeValue(iu + 1, iv + 1) = {aPoint, aD1U, aD1V, aD2U, aD2V, aD2UV}; + aResults.SetValue(thePt.OutputIdx + 1, + GeomGridEval::SurfD2{aPoint, aD1U, aD1V, aD2U, aD2V, aD2UV}); }); return aResults; @@ -677,105 +690,117 @@ NCollection_Array2 GeomGridEval_BSplineSurface::EvaluateGr //================================================================================================== -NCollection_Array2 GeomGridEval_BSplineSurface::EvaluateGridD3() const +NCollection_Array2 GeomGridEval_BSplineSurface::EvaluateGridD3( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams) const { - if (myGeom.IsNull() || myRawUParams.IsEmpty() || myRawVParams.IsEmpty()) + if (myGeom.IsNull() || theUParams.IsEmpty() || theVParams.IsEmpty()) { return NCollection_Array2(); } - prepare(); + const int aNbU = theUParams.Size(); + const int aNbV = theVParams.Size(); - const int aNbUParams = myUParams.Size(); - const int aNbVParams = myVParams.Size(); - - if (aNbUParams == 0 || aNbVParams == 0 || myUSpanRanges.IsEmpty() || myVSpanRanges.IsEmpty()) + NCollection_Array1 aLinearResult = EvaluatePointsD3(theUParams, theVParams); + if (aLinearResult.IsEmpty()) { return NCollection_Array2(); } - NCollection_Array2 aResults(1, aNbUParams, 1, aNbVParams); + NCollection_Array2 aGrid(1, aNbU, 1, aNbV); + for (int i = 0; i < aNbU; ++i) + { + for (int j = 0; j < aNbV; ++j) + { + const int aLinIdx = i * aNbV + j; + aGrid.SetValue(i + 1, j + 1, aLinearResult.Value(aLinIdx + 1)); + } + } + return aGrid; +} +//================================================================================================== + +NCollection_Array1 GeomGridEval_BSplineSurface::EvaluatePointsD3( + const NCollection_Array1& theUVPairs) const +{ + if (myGeom.IsNull() || theUVPairs.IsEmpty()) + { + return NCollection_Array1(); + } + + // Prepare UV points and sort by span + NCollection_Array1 aUVPoints; + preparePairPoints(theUVPairs, aUVPoints); + + const int aNbPoints = aUVPoints.Size(); + if (aNbPoints == 0) + { + return NCollection_Array1(); + } + + // Get surface data from geometry const Handle(TColStd_HArray1OfReal)& aUFlatKnotsHandle = myGeom->HArrayUFlatKnots(); const Handle(TColStd_HArray1OfReal)& aVFlatKnotsHandle = myGeom->HArrayVFlatKnots(); - if (aUFlatKnotsHandle.IsNull() || aVFlatKnotsHandle.IsNull()) + const Handle(TColgp_HArray2OfPnt)& aPolesHandle = myGeom->HArrayPoles(); + + if (aUFlatKnotsHandle.IsNull() || aVFlatKnotsHandle.IsNull() || aPolesHandle.IsNull()) { - return NCollection_Array2(); + return NCollection_Array1(); } + const TColStd_Array1OfReal& aUFlatKnots = aUFlatKnotsHandle->Array1(); const TColStd_Array1OfReal& aVFlatKnots = aVFlatKnotsHandle->Array1(); + const TColgp_Array2OfPnt& aPoles = aPolesHandle->Array2(); + const TColStd_Array2OfReal* aWeights = myGeom->Weights(); + const int aUDegree = myGeom->UDegree(); + const int aVDegree = myGeom->VDegree(); + const bool isURational = myGeom->IsURational(); + const bool isVRational = myGeom->IsVRational(); + const bool isUPeriodic = myGeom->IsUPeriodic(); + const bool isVPeriodic = myGeom->IsVPeriodic(); - const int aUDegree = myGeom->UDegree(); - const int aVDegree = myGeom->VDegree(); - const bool isURational = myGeom->IsURational(); - const bool isVRational = myGeom->IsVRational(); - const bool isUPeriodic = myGeom->IsUPeriodic(); - const bool isVPeriodic = myGeom->IsVPeriodic(); + NCollection_Array1 aResults(1, aNbPoints); - const Handle(TColgp_HArray2OfPnt)& aPolesHandle = myGeom->HArrayPoles(); - if (aPolesHandle.IsNull()) + // D3 uses direct BSplSLib::D3 - no cache available for third derivatives + for (int i = 0; i < aNbPoints; ++i) { - return NCollection_Array2(); - } - const TColgp_Array2OfPnt& aPoles = aPolesHandle->Array2(); + const GeomGridEval::UVPointWithSpan& aPt = aUVPoints.Value(i); - const TColStd_Array2OfReal* aWeights = myGeom->Weights(); + gp_Pnt aPoint; + gp_Vec aD1U, aD1V, aD2U, aD2V, aD2UV, aD3U, aD3V, aD3UUV, aD3UVV; - // D3 evaluation uses direct BSplSLib::D3 - no cache available for third derivatives - const int aNbUSpans = myUSpanRanges.Size(); - const int aNbVSpans = myVSpanRanges.Size(); + BSplSLib::D3(aPt.U, + aPt.V, + aPt.USpanIdx, + aPt.VSpanIdx, + aPoles, + aWeights, + aUFlatKnots, + aVFlatKnots, + nullptr, + nullptr, + aUDegree, + aVDegree, + isURational, + isVRational, + isUPeriodic, + isVPeriodic, + aPoint, + aD1U, + aD1V, + aD2U, + aD2V, + aD2UV, + aD3U, + aD3V, + aD3UUV, + aD3UVV); - for (int iURange = 0; iURange < aNbUSpans; ++iURange) - { - const auto& aURange = myUSpanRanges.Value(iURange); - - for (int iVRange = 0; iVRange < aNbVSpans; ++iVRange) - { - const auto& aVRange = myVSpanRanges.Value(iVRange); - - for (int iu = aURange.StartIdx; iu < aURange.EndIdx; ++iu) - { - const double aUParam = myUParams.Value(iu).Param; - const int aUSpanIdx = aURange.SpanIndex; - - for (int iv = aVRange.StartIdx; iv < aVRange.EndIdx; ++iv) - { - gp_Pnt aPoint; - gp_Vec aD1U, aD1V, aD2U, aD2V, aD2UV, aD3U, aD3V, aD3UUV, aD3UVV; - - BSplSLib::D3(aUParam, - myVParams.Value(iv).Param, - aUSpanIdx, - aVRange.SpanIndex, - aPoles, - aWeights, - aUFlatKnots, - aVFlatKnots, - nullptr, - nullptr, - aUDegree, - aVDegree, - isURational, - isVRational, - isUPeriodic, - isVPeriodic, - aPoint, - aD1U, - aD1V, - aD2U, - aD2V, - aD2UV, - aD3U, - aD3V, - aD3UUV, - aD3UVV); - - aResults.ChangeValue( - iu + 1, - iv + 1) = {aPoint, aD1U, aD1V, aD2U, aD2V, aD2UV, aD3U, aD3V, aD3UUV, aD3UVV}; - } - } - } + aResults.SetValue( + aPt.OutputIdx + 1, + GeomGridEval::SurfD3{aPoint, aD1U, aD1V, aD2U, aD2V, aD2UV, aD3U, aD3V, aD3UUV, aD3UVV}); } return aResults; @@ -783,112 +808,495 @@ NCollection_Array2 GeomGridEval_BSplineSurface::EvaluateGr //================================================================================================== -NCollection_Array2 GeomGridEval_BSplineSurface::EvaluateGridDN(int theNU, int theNV) const +NCollection_Array2 GeomGridEval_BSplineSurface::EvaluateGridDN( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams, + int theNU, + int theNV) const { - if (myGeom.IsNull() || myRawUParams.IsEmpty() || myRawVParams.IsEmpty() || theNU < 0 || theNV < 0 - || (theNU + theNV) < 1) + if (myGeom.IsNull() || theUParams.IsEmpty() || theVParams.IsEmpty()) { return NCollection_Array2(); } - prepare(); + const int aNbU = theUParams.Size(); + const int aNbV = theVParams.Size(); - const int aNbUParams = myUParams.Size(); - const int aNbVParams = myVParams.Size(); - - if (aNbUParams == 0 || aNbVParams == 0 || myUSpanRanges.IsEmpty() || myVSpanRanges.IsEmpty()) + NCollection_Array1 aLinearResult = EvaluatePointsDN(theUParams, theVParams, theNU, theNV); + if (aLinearResult.IsEmpty()) { return NCollection_Array2(); } - NCollection_Array2 aResult(1, aNbUParams, 1, aNbVParams); - - // For B-spline surfaces, derivatives become zero when order exceeds degree in that direction - const int aUDegree = myGeom->UDegree(); - const int aVDegree = myGeom->VDegree(); - - if (theNU > aUDegree || theNV > aVDegree) + NCollection_Array2 aGrid(1, aNbU, 1, aNbV); + for (int i = 0; i < aNbU; ++i) { - // All derivatives are zero - const gp_Vec aZeroVec(0.0, 0.0, 0.0); - for (int i = 1; i <= aNbUParams; ++i) + for (int j = 0; j < aNbV; ++j) { - for (int j = 1; j <= aNbVParams; ++j) - { - aResult.SetValue(i, j, aZeroVec); - } + const int aLinIdx = i * aNbV + j; + aGrid.SetValue(i + 1, j + 1, aLinearResult.Value(aLinIdx + 1)); } - return aResult; + } + return aGrid; +} + +//================================================================================================== + +NCollection_Array1 GeomGridEval_BSplineSurface::EvaluatePointsDN( + const NCollection_Array1& theUVPairs, + int theNU, + int theNV) const +{ + if (myGeom.IsNull() || theUVPairs.IsEmpty() || theNU < 0 || theNV < 0 || (theNU + theNV) < 1) + { + return NCollection_Array1(); } - // Get surface data for direct BSplSLib::DN call - // Use flat knots with nullptr multiplicities (like D1/D2/D3 methods) + // Prepare UV points and sort by span + NCollection_Array1 aUVPoints; + preparePairPoints(theUVPairs, aUVPoints); + + const int aNbPoints = aUVPoints.Size(); + if (aNbPoints == 0) + { + return NCollection_Array1(); + } + + // Get surface data from geometry const Handle(TColStd_HArray1OfReal)& aUFlatKnotsHandle = myGeom->HArrayUFlatKnots(); const Handle(TColStd_HArray1OfReal)& aVFlatKnotsHandle = myGeom->HArrayVFlatKnots(); - if (aUFlatKnotsHandle.IsNull() || aVFlatKnotsHandle.IsNull()) + const Handle(TColgp_HArray2OfPnt)& aPolesHandle = myGeom->HArrayPoles(); + + if (aUFlatKnotsHandle.IsNull() || aVFlatKnotsHandle.IsNull() || aPolesHandle.IsNull()) { - return NCollection_Array2(); + return NCollection_Array1(); } + const TColStd_Array1OfReal& aUFlatKnots = aUFlatKnotsHandle->Array1(); const TColStd_Array1OfReal& aVFlatKnots = aVFlatKnotsHandle->Array1(); - - const Handle(TColgp_HArray2OfPnt)& aPolesHandle = myGeom->HArrayPoles(); - if (aPolesHandle.IsNull()) - { - return NCollection_Array2(); - } - const TColgp_Array2OfPnt& aPoles = aPolesHandle->Array2(); - + const TColgp_Array2OfPnt& aPoles = aPolesHandle->Array2(); const TColStd_Array2OfReal* aWeights = myGeom->Weights(); + const int aUDegree = myGeom->UDegree(); + const int aVDegree = myGeom->VDegree(); const bool isURational = myGeom->IsURational(); const bool isVRational = myGeom->IsVRational(); const bool isUPeriodic = myGeom->IsUPeriodic(); const bool isVPeriodic = myGeom->IsVPeriodic(); - // Use BSplSLib::DN directly with pre-computed span indices - const int aNbUSpans = myUSpanRanges.Size(); - const int aNbVSpans = myVSpanRanges.Size(); + NCollection_Array1 aResults(1, aNbPoints); - for (int iURange = 0; iURange < aNbUSpans; ++iURange) + // For B-spline surfaces, derivatives become zero when order exceeds degree in that direction + if (theNU > aUDegree || theNV > aVDegree) { - const auto& aURange = myUSpanRanges.Value(iURange); - - for (int iVRange = 0; iVRange < aNbVSpans; ++iVRange) + const gp_Vec aZeroVec(0.0, 0.0, 0.0); + for (int i = 1; i <= aNbPoints; ++i) { - const auto& aVRange = myVSpanRanges.Value(iVRange); - - for (int iu = aURange.StartIdx; iu < aURange.EndIdx; ++iu) - { - const double aUParam = myUParams.Value(iu).Param; - const int aUSpanIdx = aURange.SpanIndex; - - for (int iv = aVRange.StartIdx; iv < aVRange.EndIdx; ++iv) - { - gp_Vec aDN; - BSplSLib::DN(aUParam, - myVParams.Value(iv).Param, - theNU, - theNV, - aUSpanIdx, - aVRange.SpanIndex, - aPoles, - aWeights, - aUFlatKnots, - aVFlatKnots, - nullptr, - nullptr, - aUDegree, - aVDegree, - isURational, - isVRational, - isUPeriodic, - isVPeriodic, - aDN); - aResult.SetValue(iu + 1, iv + 1, aDN); - } - } + aResults.SetValue(i, aZeroVec); } + return aResults; } - return aResult; + // Use BSplSLib::DN directly with pre-computed span indices + for (int i = 0; i < aNbPoints; ++i) + { + const GeomGridEval::UVPointWithSpan& aPt = aUVPoints.Value(i); + + gp_Vec aDN; + BSplSLib::DN(aPt.U, + aPt.V, + theNU, + theNV, + aPt.USpanIdx, + aPt.VSpanIdx, + aPoles, + aWeights, + aUFlatKnots, + aVFlatKnots, + nullptr, + nullptr, + aUDegree, + aVDegree, + isURational, + isVRational, + isUPeriodic, + isVPeriodic, + aDN); + + aResults.SetValue(aPt.OutputIdx + 1, aDN); + } + + return aResults; +} + +//================================================================================================== + +// Helper overloads for grid -> points conversion (D1, D2, D3, DN) +// These allow EvaluateGridD* to call EvaluatePointsD* with grid parameters + +NCollection_Array1 GeomGridEval_BSplineSurface::EvaluatePointsD1( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams) const +{ + if (myGeom.IsNull() || theUParams.IsEmpty() || theVParams.IsEmpty()) + { + return NCollection_Array1(); + } + + // Prepare UV points and sort by span + NCollection_Array1 aUVPoints; + prepareGridPoints(theUParams, theVParams, aUVPoints); + + const int aNbPoints = aUVPoints.Size(); + if (aNbPoints == 0) + { + return NCollection_Array1(); + } + + // Get surface data from geometry + const Handle(TColStd_HArray1OfReal)& aUFlatKnotsHandle = myGeom->HArrayUFlatKnots(); + const Handle(TColStd_HArray1OfReal)& aVFlatKnotsHandle = myGeom->HArrayVFlatKnots(); + const Handle(TColgp_HArray2OfPnt)& aPolesHandle = myGeom->HArrayPoles(); + + if (aUFlatKnotsHandle.IsNull() || aVFlatKnotsHandle.IsNull() || aPolesHandle.IsNull()) + { + return NCollection_Array1(); + } + + const TColStd_Array1OfReal& aUFlatKnots = aUFlatKnotsHandle->Array1(); + const TColStd_Array1OfReal& aVFlatKnots = aVFlatKnotsHandle->Array1(); + const TColgp_Array2OfPnt& aPoles = aPolesHandle->Array2(); + const TColStd_Array2OfReal* aWeights = myGeom->Weights(); + + // Get surface properties for direct evaluation + const int aUDegree = myGeom->UDegree(); + const int aVDegree = myGeom->VDegree(); + const bool isUPeriodic = myGeom->IsUPeriodic(); + const bool isVPeriodic = myGeom->IsVPeriodic(); + const bool isURational = myGeom->IsURational(); + const bool isVRational = myGeom->IsVRational(); + + NCollection_Array1 aResults(1, aNbPoints); + + // Create local cache for cache-based evaluation (only used for large span groups) + Handle(BSplSLib_Cache) aCache = new BSplSLib_Cache(aUDegree, + isUPeriodic, + aUFlatKnots, + aVDegree, + isVPeriodic, + aVFlatKnots, + aWeights); + + iterateSortedUVPoints( + aUVPoints, + [&](double theU, double theV) { + aCache->BuildCache(theU, theV, aUFlatKnots, aVFlatKnots, aPoles, aWeights); + }, + [&](const GeomGridEval::UVPointWithSpan& thePt) { + gp_Pnt aPoint; + gp_Vec aD1U, aD1V; + aCache->D1Local(thePt.LocalU, thePt.LocalV, aPoint, aD1U, aD1V); + aResults.SetValue(thePt.OutputIdx + 1, GeomGridEval::SurfD1{aPoint, aD1U, aD1V}); + }, + [&](const GeomGridEval::UVPointWithSpan& thePt) { + gp_Pnt aPoint; + gp_Vec aD1U, aD1V; + BSplSLib::D1(thePt.U, + thePt.V, + thePt.USpanIdx, + thePt.VSpanIdx, + aPoles, + aWeights, + aUFlatKnots, + aVFlatKnots, + nullptr, + nullptr, + aUDegree, + aVDegree, + isURational, + isVRational, + isUPeriodic, + isVPeriodic, + aPoint, + aD1U, + aD1V); + aResults.SetValue(thePt.OutputIdx + 1, GeomGridEval::SurfD1{aPoint, aD1U, aD1V}); + }); + + return aResults; +} + +//================================================================================================== + +NCollection_Array1 GeomGridEval_BSplineSurface::EvaluatePointsD2( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams) const +{ + if (myGeom.IsNull() || theUParams.IsEmpty() || theVParams.IsEmpty()) + { + return NCollection_Array1(); + } + + // Prepare UV points and sort by span + NCollection_Array1 aUVPoints; + prepareGridPoints(theUParams, theVParams, aUVPoints); + + const int aNbPoints = aUVPoints.Size(); + if (aNbPoints == 0) + { + return NCollection_Array1(); + } + + // Get surface data from geometry + const Handle(TColStd_HArray1OfReal)& aUFlatKnotsHandle = myGeom->HArrayUFlatKnots(); + const Handle(TColStd_HArray1OfReal)& aVFlatKnotsHandle = myGeom->HArrayVFlatKnots(); + const Handle(TColgp_HArray2OfPnt)& aPolesHandle = myGeom->HArrayPoles(); + + if (aUFlatKnotsHandle.IsNull() || aVFlatKnotsHandle.IsNull() || aPolesHandle.IsNull()) + { + return NCollection_Array1(); + } + + const TColStd_Array1OfReal& aUFlatKnots = aUFlatKnotsHandle->Array1(); + const TColStd_Array1OfReal& aVFlatKnots = aVFlatKnotsHandle->Array1(); + const TColgp_Array2OfPnt& aPoles = aPolesHandle->Array2(); + const TColStd_Array2OfReal* aWeights = myGeom->Weights(); + + // Get surface properties for direct evaluation + const int aUDegree = myGeom->UDegree(); + const int aVDegree = myGeom->VDegree(); + const bool isUPeriodic = myGeom->IsUPeriodic(); + const bool isVPeriodic = myGeom->IsVPeriodic(); + const bool isURational = myGeom->IsURational(); + const bool isVRational = myGeom->IsVRational(); + + NCollection_Array1 aResults(1, aNbPoints); + + // Create local cache for cache-based evaluation (only used for large span groups) + Handle(BSplSLib_Cache) aCache = new BSplSLib_Cache(aUDegree, + isUPeriodic, + aUFlatKnots, + aVDegree, + isVPeriodic, + aVFlatKnots, + aWeights); + + iterateSortedUVPoints( + aUVPoints, + [&](double theU, double theV) { + aCache->BuildCache(theU, theV, aUFlatKnots, aVFlatKnots, aPoles, aWeights); + }, + [&](const GeomGridEval::UVPointWithSpan& thePt) { + gp_Pnt aPoint; + gp_Vec aD1U, aD1V, aD2U, aD2V, aD2UV; + aCache->D2Local(thePt.LocalU, thePt.LocalV, aPoint, aD1U, aD1V, aD2U, aD2V, aD2UV); + aResults.SetValue(thePt.OutputIdx + 1, + GeomGridEval::SurfD2{aPoint, aD1U, aD1V, aD2U, aD2V, aD2UV}); + }, + [&](const GeomGridEval::UVPointWithSpan& thePt) { + gp_Pnt aPoint; + gp_Vec aD1U, aD1V, aD2U, aD2V, aD2UV; + BSplSLib::D2(thePt.U, + thePt.V, + thePt.USpanIdx, + thePt.VSpanIdx, + aPoles, + aWeights, + aUFlatKnots, + aVFlatKnots, + nullptr, + nullptr, + aUDegree, + aVDegree, + isURational, + isVRational, + isUPeriodic, + isVPeriodic, + aPoint, + aD1U, + aD1V, + aD2U, + aD2V, + aD2UV); + aResults.SetValue(thePt.OutputIdx + 1, + GeomGridEval::SurfD2{aPoint, aD1U, aD1V, aD2U, aD2V, aD2UV}); + }); + + return aResults; +} + +//================================================================================================== + +NCollection_Array1 GeomGridEval_BSplineSurface::EvaluatePointsD3( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams) const +{ + if (myGeom.IsNull() || theUParams.IsEmpty() || theVParams.IsEmpty()) + { + return NCollection_Array1(); + } + + // Prepare UV points and sort by span + NCollection_Array1 aUVPoints; + prepareGridPoints(theUParams, theVParams, aUVPoints); + + const int aNbPoints = aUVPoints.Size(); + if (aNbPoints == 0) + { + return NCollection_Array1(); + } + + // Get surface data from geometry + const Handle(TColStd_HArray1OfReal)& aUFlatKnotsHandle = myGeom->HArrayUFlatKnots(); + const Handle(TColStd_HArray1OfReal)& aVFlatKnotsHandle = myGeom->HArrayVFlatKnots(); + const Handle(TColgp_HArray2OfPnt)& aPolesHandle = myGeom->HArrayPoles(); + + if (aUFlatKnotsHandle.IsNull() || aVFlatKnotsHandle.IsNull() || aPolesHandle.IsNull()) + { + return NCollection_Array1(); + } + + const TColStd_Array1OfReal& aUFlatKnots = aUFlatKnotsHandle->Array1(); + const TColStd_Array1OfReal& aVFlatKnots = aVFlatKnotsHandle->Array1(); + const TColgp_Array2OfPnt& aPoles = aPolesHandle->Array2(); + const TColStd_Array2OfReal* aWeights = myGeom->Weights(); + const int aUDegree = myGeom->UDegree(); + const int aVDegree = myGeom->VDegree(); + const bool isURational = myGeom->IsURational(); + const bool isVRational = myGeom->IsVRational(); + const bool isUPeriodic = myGeom->IsUPeriodic(); + const bool isVPeriodic = myGeom->IsVPeriodic(); + + NCollection_Array1 aResults(1, aNbPoints); + + // D3 uses direct BSplSLib::D3 - no cache available for third derivatives + for (int i = 0; i < aNbPoints; ++i) + { + const GeomGridEval::UVPointWithSpan& aPt = aUVPoints.Value(i); + + gp_Pnt aPoint; + gp_Vec aD1U, aD1V, aD2U, aD2V, aD2UV, aD3U, aD3V, aD3UUV, aD3UVV; + + BSplSLib::D3(aPt.U, + aPt.V, + aPt.USpanIdx, + aPt.VSpanIdx, + aPoles, + aWeights, + aUFlatKnots, + aVFlatKnots, + nullptr, + nullptr, + aUDegree, + aVDegree, + isURational, + isVRational, + isUPeriodic, + isVPeriodic, + aPoint, + aD1U, + aD1V, + aD2U, + aD2V, + aD2UV, + aD3U, + aD3V, + aD3UUV, + aD3UVV); + + aResults.SetValue( + aPt.OutputIdx + 1, + GeomGridEval::SurfD3{aPoint, aD1U, aD1V, aD2U, aD2V, aD2UV, aD3U, aD3V, aD3UUV, aD3UVV}); + } + + return aResults; +} + +//================================================================================================== + +NCollection_Array1 GeomGridEval_BSplineSurface::EvaluatePointsDN( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams, + int theNU, + int theNV) const +{ + if (myGeom.IsNull() || theUParams.IsEmpty() || theVParams.IsEmpty() || theNU < 0 || theNV < 0 + || (theNU + theNV) < 1) + { + return NCollection_Array1(); + } + + // Prepare UV points and sort by span + NCollection_Array1 aUVPoints; + prepareGridPoints(theUParams, theVParams, aUVPoints); + + const int aNbPoints = aUVPoints.Size(); + if (aNbPoints == 0) + { + return NCollection_Array1(); + } + + // Get surface data from geometry + const Handle(TColStd_HArray1OfReal)& aUFlatKnotsHandle = myGeom->HArrayUFlatKnots(); + const Handle(TColStd_HArray1OfReal)& aVFlatKnotsHandle = myGeom->HArrayVFlatKnots(); + const Handle(TColgp_HArray2OfPnt)& aPolesHandle = myGeom->HArrayPoles(); + + if (aUFlatKnotsHandle.IsNull() || aVFlatKnotsHandle.IsNull() || aPolesHandle.IsNull()) + { + return NCollection_Array1(); + } + + const TColStd_Array1OfReal& aUFlatKnots = aUFlatKnotsHandle->Array1(); + const TColStd_Array1OfReal& aVFlatKnots = aVFlatKnotsHandle->Array1(); + const TColgp_Array2OfPnt& aPoles = aPolesHandle->Array2(); + const TColStd_Array2OfReal* aWeights = myGeom->Weights(); + const int aUDegree = myGeom->UDegree(); + const int aVDegree = myGeom->VDegree(); + const bool isURational = myGeom->IsURational(); + const bool isVRational = myGeom->IsVRational(); + const bool isUPeriodic = myGeom->IsUPeriodic(); + const bool isVPeriodic = myGeom->IsVPeriodic(); + + NCollection_Array1 aResults(1, aNbPoints); + + // For B-spline surfaces, derivatives become zero when order exceeds degree in that direction + if (theNU > aUDegree || theNV > aVDegree) + { + const gp_Vec aZeroVec(0.0, 0.0, 0.0); + for (int i = 1; i <= aNbPoints; ++i) + { + aResults.SetValue(i, aZeroVec); + } + return aResults; + } + + // Use BSplSLib::DN directly with pre-computed span indices + for (int i = 0; i < aNbPoints; ++i) + { + const GeomGridEval::UVPointWithSpan& aPt = aUVPoints.Value(i); + + gp_Vec aDN; + BSplSLib::DN(aPt.U, + aPt.V, + theNU, + theNV, + aPt.USpanIdx, + aPt.VSpanIdx, + aPoles, + aWeights, + aUFlatKnots, + aVFlatKnots, + nullptr, + nullptr, + aUDegree, + aVDegree, + isURational, + isVRational, + isUPeriodic, + isVPeriodic, + aDN); + + aResults.SetValue(aPt.OutputIdx + 1, aDN); + } + + return aResults; } diff --git a/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_BSplineSurface.hxx b/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_BSplineSurface.hxx index dd58e3469b..0f05bff2fb 100644 --- a/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_BSplineSurface.hxx +++ b/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_BSplineSurface.hxx @@ -17,50 +17,38 @@ #include #include #include +#include #include #include #include #include #include -//! @brief Efficient batch evaluator for B-spline surface grid points. +//! @brief Efficient batch evaluator for B-spline surface points. //! -//! Optimizes evaluation of multiple points on a B-spline surface by: -//! - Pre-computing span indices during parameter setup (no runtime binary search) -//! - Pre-grouping parameters by span for cache-optimal iteration +//! Stateless evaluator - constructor takes geometry, parameters passed to methods. +//! +//! Optimizes evaluation by: +//! - Pre-computing span indices during evaluation +//! - Sorting UV points by (USpan, VSpan, U) for cache-optimal iteration //! - Rebuilding cache only once per span block (not per point) -//! - Using HArrayUFlatKnots()/HArrayVFlatKnots() from Geom_BSplineSurface for direct flat knot -//! access //! -//! Usage: +//! Usage (grid mode): //! @code //! GeomGridEval_BSplineSurface anEvaluator(myBSplineSurface); -//! anEvaluator.SetUVParams(myUParams, myVParams); -//! NCollection_Array2 aGrid = anEvaluator.EvaluateGrid(); +//! NCollection_Array2 aGrid = anEvaluator.EvaluateGrid(myUParams, myVParams); +//! @endcode +//! +//! Usage (points mode): +//! @code +//! GeomGridEval_BSplineSurface anEvaluator(myBSplineSurface); +//! NCollection_Array1 aPoints = anEvaluator.EvaluatePoints(myUVPairs); //! @endcode class GeomGridEval_BSplineSurface { public: DEFINE_STANDARD_ALLOC - //! Parameter value with pre-computed span index and local parameter. - struct ParamWithSpan - { - double Param; //!< Original parameter value - double LocalParam; //!< Pre-computed local parameter in [-1, 1] range - int SpanIndex; //!< Flat knot index identifying the span - }; - - //! Range of parameter indices belonging to the same span. - struct SpanRange - { - int SpanIndex; //!< Flat knot index of this span - int StartIdx; //!< First parameter index (0-based, inclusive) - int EndIdx; //!< Past-the-end parameter index (exclusive) - double SpanMid; //!< Midpoint of span - double SpanHalfLen; //!< Half-length of span - }; - //! Constructor with geometry. //! @param theSurface the B-spline surface to evaluate GeomGridEval_BSplineSurface(const Handle(Geom_BSplineSurface)& theSurface) @@ -74,87 +62,139 @@ public: GeomGridEval_BSplineSurface(GeomGridEval_BSplineSurface&&) = delete; GeomGridEval_BSplineSurface& operator=(GeomGridEval_BSplineSurface&&) = delete; - //! Set UV parameters from two 1D arrays. - //! @param theUParams array of U parameter values - //! @param theVParams array of V parameter values - Standard_EXPORT void SetUVParams(const TColStd_Array1OfReal& theUParams, - const TColStd_Array1OfReal& theVParams); - //! Returns the geometry handle. const Handle(Geom_BSplineSurface)& Geometry() const { return myGeom; } - //! Returns number of U parameters. - int NbUParams() const { return myRawUParams.Size(); } - - //! Returns number of V parameters. - int NbVParams() const { return myRawVParams.Size(); } - - //! Evaluate all grid points. + //! Evaluate grid points at Cartesian product of U and V parameters. //! Points are evaluated in span-grouped order to minimize cache rebuilds. + //! @param theUParams array of U parameter values + //! @param theVParams array of V parameter values //! @return 2D array of evaluated points (1-based indexing), - //! or empty array if geometry is null or no parameters set - Standard_EXPORT NCollection_Array2 EvaluateGrid() const; + //! or empty array if geometry is null or parameters empty + Standard_EXPORT NCollection_Array2 EvaluateGrid( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams) const; - //! Evaluate all grid points with first partial derivatives. + //! Evaluate grid points with first partial derivatives. + //! @param theUParams array of U parameter values + //! @param theVParams array of V parameter values //! @return 2D array of SurfD1 (1-based indexing), - //! or empty array if geometry is null or no parameters set - Standard_EXPORT NCollection_Array2 EvaluateGridD1() const; + //! or empty array if geometry is null or parameters empty + Standard_EXPORT NCollection_Array2 EvaluateGridD1( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams) const; - //! Evaluate all grid points with first and second partial derivatives. + //! Evaluate grid points with first and second partial derivatives. + //! @param theUParams array of U parameter values + //! @param theVParams array of V parameter values //! @return 2D array of SurfD2 (1-based indexing), - //! or empty array if geometry is null or no parameters set - Standard_EXPORT NCollection_Array2 EvaluateGridD2() const; + //! or empty array if geometry is null or parameters empty + Standard_EXPORT NCollection_Array2 EvaluateGridD2( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams) const; - //! Evaluate all grid points with derivatives up to third order. + //! Evaluate grid points with derivatives up to third order. //! Uses direct BSplSLib::D3 evaluation (no caching for D3). + //! @param theUParams array of U parameter values + //! @param theVParams array of V parameter values //! @return 2D array of SurfD3 (1-based indexing), - //! or empty array if geometry is null or no parameters set - Standard_EXPORT NCollection_Array2 EvaluateGridD3() const; + //! or empty array if geometry is null or parameters empty + Standard_EXPORT NCollection_Array2 EvaluateGridD3( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams) const; //! Evaluate partial derivative d^(NU+NV)S/(dU^NU dV^NV) at all grid points. //! For orders > degree in either direction, returns zero. //! Uses direct geometry DN method. + //! @param theUParams array of U parameter values + //! @param theVParams array of V parameter values //! @param theNU derivative order in U direction //! @param theNV derivative order in V direction //! @return 2D array of derivative vectors (1-based indexing) - Standard_EXPORT NCollection_Array2 EvaluateGridDN(int theNU, int theNV) const; + Standard_EXPORT NCollection_Array2 EvaluateGridDN(const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams, + int theNU, + int theNV) const; + + //! Evaluate points at arbitrary UV pairs. + //! Results are returned in the original input order. + //! @param theUVPairs array of UV coordinate pairs (gp_Pnt2d: X=U, Y=V) + //! @return 1D array of evaluated points (1-based indexing), + //! or empty array if geometry is null or pairs empty + Standard_EXPORT NCollection_Array1 EvaluatePoints( + const NCollection_Array1& theUVPairs) const; + + //! Evaluate points with first partial derivatives. + //! @param theUVPairs array of UV coordinate pairs + //! @return 1D array of SurfD1 (1-based indexing) + Standard_EXPORT NCollection_Array1 EvaluatePointsD1( + const NCollection_Array1& theUVPairs) const; + + //! Evaluate points with first and second partial derivatives. + //! @param theUVPairs array of UV coordinate pairs + //! @return 1D array of SurfD2 (1-based indexing) + Standard_EXPORT NCollection_Array1 EvaluatePointsD2( + const NCollection_Array1& theUVPairs) const; + + //! Evaluate points with derivatives up to third order. + //! @param theUVPairs array of UV coordinate pairs + //! @return 1D array of SurfD3 (1-based indexing) + Standard_EXPORT NCollection_Array1 EvaluatePointsD3( + const NCollection_Array1& theUVPairs) const; + + //! Evaluate partial derivative at all UV pairs. + //! @param theUVPairs array of UV coordinate pairs + //! @param theNU derivative order in U direction + //! @param theNV derivative order in V direction + //! @return 1D array of derivative vectors (1-based indexing) + Standard_EXPORT NCollection_Array1 EvaluatePointsDN( + const NCollection_Array1& theUVPairs, + int theNU, + int theNV) const; private: //! Find span index for a parameter value. + //! @param[in,out] theParam parameter value (may be adjusted for periodicity) + //! @param[in] theUDir true for U direction, false for V direction + //! @param[in] theFlatKnots flat knots array + //! @return span index in flat knots array int locateSpan(double& theParam, bool theUDir, const TColStd_Array1OfReal& theFlatKnots) const; - //! Find span index with a hint for better performance on sorted parameters. - int locateSpanWithHint(double& theParam, - bool theUDir, - int theHint, - const TColStd_Array1OfReal& theFlatKnots) const; + //! Prepare UV points from grid parameters and sort for cache-optimal evaluation. + //! @param theUParams array of U parameter values + //! @param theVParams array of V parameter values + //! @param theUVPoints output array of UV points with span info + void prepareGridPoints(const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams, + NCollection_Array1& theUVPoints) const; - //! Compute span ranges from parameters array. - static void computeSpanRanges(const NCollection_Array1& theParams, - const TColStd_Array1OfReal& theFlatKnots, - NCollection_Array1& theSpanRanges); + //! Prepare UV points from pairs and sort for cache-optimal evaluation. + //! @param theUVPairs array of UV coordinate pairs + //! @param theUVPoints output array of UV points with span info + void preparePairPoints(const NCollection_Array1& theUVPairs, + NCollection_Array1& theUVPoints) const; - //! Prepare internal data structures from raw parameters. - //! Called lazily from EvaluateGrid() when myUSpanRanges is empty. - void prepare() const; + //! Compute span indices and local parameters, then sort by span. + //! @param theUVPoints array of UV points to process (modified in place) + void computeSpansAndSort(NCollection_Array1& theUVPoints) const; + + // Private helper overloads for grid -> linear evaluation + NCollection_Array1 EvaluatePointsD1( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams) const; + NCollection_Array1 EvaluatePointsD2( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams) const; + NCollection_Array1 EvaluatePointsD3( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams) const; + NCollection_Array1 EvaluatePointsDN(const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams, + int theNU, + int theNV) const; private: Handle(Geom_BSplineSurface) myGeom; - - // Raw parameters (set by user) - NCollection_Array1 myRawUParams; - NCollection_Array1 myRawVParams; - - // Pre-computed parameters with span indices (0-based indexing internally) - mutable NCollection_Array1 myUParams; - mutable NCollection_Array1 myVParams; - - // Pre-computed span ranges for optimized iteration (empty = not prepared) - mutable NCollection_Array1 myUSpanRanges; - mutable NCollection_Array1 myVSpanRanges; - - // Cache for efficient evaluation within spans - mutable Handle(BSplSLib_Cache) myCache; }; #endif // _GeomGridEval_BSplineSurface_HeaderFile diff --git a/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_BezierCurve.cxx b/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_BezierCurve.cxx index 1e21c07ebc..af3846a042 100644 --- a/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_BezierCurve.cxx +++ b/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_BezierCurve.cxx @@ -14,171 +14,140 @@ #include #include +#include #include -//================================================================================================== - -void GeomGridEval_BezierCurve::SetParams(const TColStd_Array1OfReal& theParams) +namespace { - const int aNb = theParams.Size(); - myParams.Resize(1, aNb, false); - for (int i = 1; i <= aNb; ++i) - { - myParams.SetValue(i, theParams.Value(theParams.Lower() + i - 1)); - } - - // Invalidate cache when parameters change - myCache.Nullify(); -} - -//================================================================================================== - -void GeomGridEval_BezierCurve::buildCache() const +//! Creates a BSplCLib_Cache for a Bezier curve. +//! @param theCurve the Bezier curve geometry +//! @return initialized cache ready for evaluation +Handle(BSplCLib_Cache) CreateBezierCache(const Handle(Geom_BezierCurve)& theCurve) { - if (myGeom.IsNull()) - { - return; - } - - const int aDegree = myGeom->Degree(); + const int aDegree = theCurve->Degree(); TColStd_Array1OfReal aFlatKnots(BSplCLib::FlatBezierKnots(aDegree), 1, 2 * (aDegree + 1)); - // Create cache following the pattern from GeomAdaptor_Curve - myCache = new BSplCLib_Cache(aDegree, - myGeom->IsPeriodic(), - aFlatKnots, - myGeom->Poles(), - myGeom->Weights()); - - // Build cache at parameter 0.5 (middle of the single span) - myCache->BuildCache(0.5, aFlatKnots, myGeom->Poles(), myGeom->Weights()); + Handle(BSplCLib_Cache) aCache = new BSplCLib_Cache(aDegree, + theCurve->IsPeriodic(), + aFlatKnots, + theCurve->Poles(), + theCurve->Weights()); + aCache->BuildCache(0.5, aFlatKnots, theCurve->Poles(), theCurve->Weights()); + return aCache; } +} // namespace //================================================================================================== -NCollection_Array1 GeomGridEval_BezierCurve::EvaluateGrid() const +NCollection_Array1 GeomGridEval_BezierCurve::EvaluateGrid( + const TColStd_Array1OfReal& theParams) const { - if (myGeom.IsNull() || myParams.IsEmpty()) + if (myGeom.IsNull() || theParams.IsEmpty()) { return NCollection_Array1(); } - // Build cache if needed - if (myCache.IsNull()) - { - buildCache(); - } - - const int aNb = myParams.Size(); + const int aNb = theParams.Size(); NCollection_Array1 aResult(1, aNb); - // Single span Bezier - use cache for all points - for (int i = 1; i <= aNb; ++i) + Handle(BSplCLib_Cache) aCache = CreateBezierCache(myGeom); + + for (int i = theParams.Lower(); i <= theParams.Upper(); ++i) { gp_Pnt aP; - myCache->D0(myParams.Value(i), aP); - aResult.SetValue(i, aP); + aCache->D0(theParams.Value(i), aP); + aResult.SetValue(i - theParams.Lower() + 1, aP); } return aResult; } //================================================================================================== -NCollection_Array1 GeomGridEval_BezierCurve::EvaluateGridD1() const +NCollection_Array1 GeomGridEval_BezierCurve::EvaluateGridD1( + const TColStd_Array1OfReal& theParams) const { - if (myGeom.IsNull() || myParams.IsEmpty()) + if (myGeom.IsNull() || theParams.IsEmpty()) { return NCollection_Array1(); } - // Build cache if needed - if (myCache.IsNull()) - { - buildCache(); - } - - const int aNb = myParams.Size(); + const int aNb = theParams.Size(); NCollection_Array1 aResult(1, aNb); - // Single span Bezier - use cache for all points - for (int i = 1; i <= aNb; ++i) + Handle(BSplCLib_Cache) aCache = CreateBezierCache(myGeom); + + for (int i = theParams.Lower(); i <= theParams.Upper(); ++i) { gp_Pnt aP; gp_Vec aD1; - myCache->D1(myParams.Value(i), aP, aD1); - aResult.ChangeValue(i) = {aP, aD1}; + aCache->D1(theParams.Value(i), aP, aD1); + aResult.ChangeValue(i - theParams.Lower() + 1) = {aP, aD1}; } return aResult; } //================================================================================================== -NCollection_Array1 GeomGridEval_BezierCurve::EvaluateGridD2() const +NCollection_Array1 GeomGridEval_BezierCurve::EvaluateGridD2( + const TColStd_Array1OfReal& theParams) const { - if (myGeom.IsNull() || myParams.IsEmpty()) + if (myGeom.IsNull() || theParams.IsEmpty()) { return NCollection_Array1(); } - // Build cache if needed - if (myCache.IsNull()) - { - buildCache(); - } - - const int aNb = myParams.Size(); + const int aNb = theParams.Size(); NCollection_Array1 aResult(1, aNb); - // Single span Bezier - use cache for all points - for (int i = 1; i <= aNb; ++i) + Handle(BSplCLib_Cache) aCache = CreateBezierCache(myGeom); + + for (int i = theParams.Lower(); i <= theParams.Upper(); ++i) { gp_Pnt aP; gp_Vec aD1, aD2; - myCache->D2(myParams.Value(i), aP, aD1, aD2); - aResult.ChangeValue(i) = {aP, aD1, aD2}; + aCache->D2(theParams.Value(i), aP, aD1, aD2); + aResult.ChangeValue(i - theParams.Lower() + 1) = {aP, aD1, aD2}; } return aResult; } //================================================================================================== -NCollection_Array1 GeomGridEval_BezierCurve::EvaluateGridD3() const +NCollection_Array1 GeomGridEval_BezierCurve::EvaluateGridD3( + const TColStd_Array1OfReal& theParams) const { - if (myGeom.IsNull() || myParams.IsEmpty()) + if (myGeom.IsNull() || theParams.IsEmpty()) { return NCollection_Array1(); } - // Build cache if needed - if (myCache.IsNull()) - { - buildCache(); - } - - const int aNb = myParams.Size(); + const int aNb = theParams.Size(); NCollection_Array1 aResult(1, aNb); - // Single span Bezier - use cache for all points - for (int i = 1; i <= aNb; ++i) + Handle(BSplCLib_Cache) aCache = CreateBezierCache(myGeom); + + for (int i = theParams.Lower(); i <= theParams.Upper(); ++i) { gp_Pnt aP; gp_Vec aD1, aD2, aD3; - myCache->D3(myParams.Value(i), aP, aD1, aD2, aD3); - aResult.ChangeValue(i) = {aP, 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 GeomGridEval_BezierCurve::EvaluateGridDN(int theN) const +NCollection_Array1 GeomGridEval_BezierCurve::EvaluateGridDN( + const TColStd_Array1OfReal& theParams, + int theN) const { - if (myGeom.IsNull() || myParams.IsEmpty() || theN < 1) + if (myGeom.IsNull() || theParams.IsEmpty() || theN < 1) { return NCollection_Array1(); } - const int aNb = myParams.Size(); + const int aNb = theParams.Size(); NCollection_Array1 aResult(1, aNb); // For Bezier curves, derivatives become zero when order exceeds degree @@ -201,10 +170,10 @@ NCollection_Array1 GeomGridEval_BezierCurve::EvaluateGridDN(int theN) co TColStd_Array1OfReal aFlatKnots(BSplCLib::FlatBezierKnots(aDegree), 1, 2 * (aDegree + 1)); // Bezier has a single span (index 0 with flat knots), non-periodic - for (int i = 1; i <= aNb; ++i) + for (int i = theParams.Lower(); i <= theParams.Upper(); ++i) { gp_Vec aDN; - BSplCLib::DN(myParams.Value(i), + BSplCLib::DN(theParams.Value(i), theN, 0, // span index (single span for Bezier with flat knots) aDegree, @@ -214,7 +183,7 @@ NCollection_Array1 GeomGridEval_BezierCurve::EvaluateGridDN(int theN) co aFlatKnots, nullptr, // no multiplicities with flat knots aDN); - aResult.SetValue(i, aDN); + aResult.SetValue(i - theParams.Lower() + 1, aDN); } return aResult; } diff --git a/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_BezierCurve.hxx b/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_BezierCurve.hxx index 9759cb650d..cf99bbe2f6 100644 --- a/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_BezierCurve.hxx +++ b/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_BezierCurve.hxx @@ -29,8 +29,7 @@ //! Usage: //! @code //! GeomGridEval_BezierCurve anEvaluator(myGeomBezier); -//! anEvaluator.SetParams(myParams); -//! NCollection_Array1 aGrid = anEvaluator.EvaluateGrid(); +//! NCollection_Array1 aGrid = anEvaluator.EvaluateGrid(myParams); //! @endcode class GeomGridEval_BezierCurve { @@ -50,47 +49,45 @@ public: GeomGridEval_BezierCurve(GeomGridEval_BezierCurve&&) = delete; GeomGridEval_BezierCurve& operator=(GeomGridEval_BezierCurve&&) = delete; - //! Set parameter values. - //! @param theParams array of parameter values - Standard_EXPORT void SetParams(const TColStd_Array1OfReal& theParams); - //! Returns the geometry handle. const Handle(Geom_BezierCurve)& Geometry() const { return myGeom; } - //! Returns number of parameters. - int NbParams() const { return myParams.Size(); } - //! 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 set - Standard_EXPORT NCollection_Array1 EvaluateGrid() const; + //! or empty array if geometry is null or no parameters + Standard_EXPORT NCollection_Array1 EvaluateGrid( + const TColStd_Array1OfReal& 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 EvaluateGridD1() const; + Standard_EXPORT NCollection_Array1 EvaluateGridD1( + const TColStd_Array1OfReal& 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 EvaluateGridD2() const; + Standard_EXPORT NCollection_Array1 EvaluateGridD2( + const TColStd_Array1OfReal& 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 EvaluateGridD3() const; + Standard_EXPORT NCollection_Array1 EvaluateGridD3( + const TColStd_Array1OfReal& 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 EvaluateGridDN(int theN) const; + Standard_EXPORT NCollection_Array1 EvaluateGridDN(const TColStd_Array1OfReal& theParams, + int theN) const; private: - //! Build the cache if not already built. - void buildCache() const; - - Handle(Geom_BezierCurve) myGeom; - NCollection_Array1 myParams; - mutable Handle(BSplCLib_Cache) myCache; + Handle(Geom_BezierCurve) myGeom; }; #endif // _GeomGridEval_BezierCurve_HeaderFile diff --git a/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_BezierSurface.cxx b/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_BezierSurface.cxx index 5502ba6261..7fbf94d47a 100644 --- a/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_BezierSurface.cxx +++ b/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_BezierSurface.cxx @@ -27,76 +27,53 @@ namespace //! For small grids (e.g., 1x4), cache-based surface evaluation is faster than //! extracting an isoline curve and setting up a curve evaluator. constexpr int THE_ISOLINE_THRESHOLD = 8; -} // namespace -//================================================================================================== - -void GeomGridEval_BezierSurface::SetUVParams(const TColStd_Array1OfReal& theUParams, - const TColStd_Array1OfReal& theVParams) +//! Create and build cache for Bezier surface evaluation. +//! Bezier surfaces are single-span, so cache is built once at parameter (0.5, 0.5). +//! @param theGeom the Bezier surface geometry +//! @return the built cache +Handle(BSplSLib_Cache) buildBezierCache(const Handle(Geom_BezierSurface)& theGeom) { - const int aNbU = theUParams.Size(); - const int aNbV = theVParams.Size(); - - myUParams.Resize(0, aNbU - 1, false); - for (int i = 0; i < aNbU; ++i) - { - myUParams.SetValue(i, theUParams.Value(theUParams.Lower() + i)); - } - - myVParams.Resize(0, aNbV - 1, false); - for (int j = 0; j < aNbV; ++j) - { - myVParams.SetValue(j, theVParams.Value(theVParams.Lower() + j)); - } - - // Invalidate cache when parameters change - myCache.Nullify(); -} - -//================================================================================================== - -void GeomGridEval_BezierSurface::buildCache() const -{ - if (myGeom.IsNull()) - { - return; - } - - const int aUDegree = myGeom->UDegree(); - const int aVDegree = myGeom->VDegree(); + const int aUDegree = theGeom->UDegree(); + const int aVDegree = theGeom->VDegree(); // Use pre-defined flat knots from BSplCLib TColStd_Array1OfReal aUFlatKnots(BSplCLib::FlatBezierKnots(aUDegree), 1, 2 * (aUDegree + 1)); TColStd_Array1OfReal aVFlatKnots(BSplCLib::FlatBezierKnots(aVDegree), 1, 2 * (aVDegree + 1)); // Get poles and weights directly (const references, no copy) - const TColgp_Array2OfPnt& aPoles = myGeom->Poles(); - const TColStd_Array2OfReal* aWeights = myGeom->Weights(); + const TColgp_Array2OfPnt& aPoles = theGeom->Poles(); + const TColStd_Array2OfReal* aWeights = theGeom->Weights(); // Create cache (Bezier is non-periodic) - myCache = new BSplSLib_Cache(aUDegree, - false, // not periodic - aUFlatKnots, - aVDegree, - false, // not periodic - aVFlatKnots, - aWeights); + Handle(BSplSLib_Cache) aCache = new BSplSLib_Cache(aUDegree, + false, // not periodic + aUFlatKnots, + aVDegree, + false, // not periodic + aVFlatKnots, + aWeights); // Build cache at parameter 0.5 (middle of single span) - myCache->BuildCache(0.5, 0.5, aUFlatKnots, aVFlatKnots, aPoles, aWeights); + aCache->BuildCache(0.5, 0.5, aUFlatKnots, aVFlatKnots, aPoles, aWeights); + + return aCache; } +} // namespace //================================================================================================== -NCollection_Array2 GeomGridEval_BezierSurface::EvaluateGrid() const +NCollection_Array2 GeomGridEval_BezierSurface::EvaluateGrid( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams) const { - if (myGeom.IsNull() || myUParams.IsEmpty() || myVParams.IsEmpty()) + if (myGeom.IsNull() || theUParams.IsEmpty() || theVParams.IsEmpty()) { return NCollection_Array2(); } - const int aNbU = myUParams.Size(); - const int aNbV = myVParams.Size(); + const int aNbU = theUParams.Size(); + const int aNbV = theVParams.Size(); // Check for V-isoline case (Nx1) - use 1D curve evaluation // For U-isoline (1xN), cache-based surface evaluation is efficient since U span is fixed. @@ -110,15 +87,15 @@ NCollection_Array2 GeomGridEval_BezierSurface::EvaluateGrid() const { OCC_CATCH_SIGNALS // Extract V-isoline curve (parameterized by U) - Handle(Geom_Curve) aCurve = myGeom->VIso(myVParams.Value(0)); + Handle(Geom_Curve) aCurve = myGeom->VIso(theVParams.Value(theVParams.Lower())); if (!aCurve.IsNull()) { // Use unified curve evaluator GeomGridEval_Curve aCurveEval; aCurveEval.Initialize(aCurve); - aCurveEval.SetParams(myUParams); - NCollection_Array1 aCurveResult = aCurveEval.EvaluateGrid(); + + NCollection_Array1 aCurveResult = aCurveEval.EvaluateGrid(theUParams); // Reshape 1D curve result to 2D surface result (Nx1 grid) NCollection_Array2 aResult(1, aNbU, 1, 1); @@ -135,22 +112,19 @@ NCollection_Array2 GeomGridEval_BezierSurface::EvaluateGrid() const } } - // Build cache if needed - if (myCache.IsNull()) - { - buildCache(); - } + // Build cache (Bezier is single span, cache is built once) + Handle(BSplSLib_Cache) aCache = buildBezierCache(myGeom); NCollection_Array2 aResult(1, aNbU, 1, aNbV); // Single span - use cache for all points for (int i = 0; i < aNbU; ++i) { - const double aU = myUParams.Value(i); + const double aU = theUParams.Value(theUParams.Lower() + i); for (int j = 0; j < aNbV; ++j) { gp_Pnt aPoint; - myCache->D0(aU, myVParams.Value(j), aPoint); + aCache->D0(aU, theVParams.Value(theVParams.Lower() + j), aPoint); aResult.SetValue(i + 1, j + 1, aPoint); } } @@ -160,32 +134,31 @@ NCollection_Array2 GeomGridEval_BezierSurface::EvaluateGrid() const //================================================================================================== -NCollection_Array2 GeomGridEval_BezierSurface::EvaluateGridD1() const +NCollection_Array2 GeomGridEval_BezierSurface::EvaluateGridD1( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams) const { - if (myGeom.IsNull() || myUParams.IsEmpty() || myVParams.IsEmpty()) + if (myGeom.IsNull() || theUParams.IsEmpty() || theVParams.IsEmpty()) { return NCollection_Array2(); } - // Build cache if needed - if (myCache.IsNull()) - { - buildCache(); - } + // Build cache (Bezier is single span, cache is built once) + Handle(BSplSLib_Cache) aCache = buildBezierCache(myGeom); - const int aNbU = myUParams.Size(); - const int aNbV = myVParams.Size(); + const int aNbU = theUParams.Size(); + const int aNbV = theVParams.Size(); NCollection_Array2 aResult(1, aNbU, 1, aNbV); // Single span - use cache for all points for (int i = 0; i < aNbU; ++i) { - const double aU = myUParams.Value(i); + const double aU = theUParams.Value(theUParams.Lower() + i); for (int j = 0; j < aNbV; ++j) { gp_Pnt aPoint; gp_Vec aD1U, aD1V; - myCache->D1(aU, myVParams.Value(j), aPoint, aD1U, aD1V); + aCache->D1(aU, theVParams.Value(theVParams.Lower() + j), aPoint, aD1U, aD1V); aResult.ChangeValue(i + 1, j + 1) = {aPoint, aD1U, aD1V}; } } @@ -195,32 +168,32 @@ NCollection_Array2 GeomGridEval_BezierSurface::EvaluateGri //================================================================================================== -NCollection_Array2 GeomGridEval_BezierSurface::EvaluateGridD2() const +NCollection_Array2 GeomGridEval_BezierSurface::EvaluateGridD2( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams) const { - if (myGeom.IsNull() || myUParams.IsEmpty() || myVParams.IsEmpty()) + if (myGeom.IsNull() || theUParams.IsEmpty() || theVParams.IsEmpty()) { return NCollection_Array2(); } - // Build cache if needed - if (myCache.IsNull()) - { - buildCache(); - } + // Build cache (Bezier is single span, cache is built once) + Handle(BSplSLib_Cache) aCache = buildBezierCache(myGeom); - const int aNbU = myUParams.Size(); - const int aNbV = myVParams.Size(); + const int aNbU = theUParams.Size(); + const int aNbV = theVParams.Size(); NCollection_Array2 aResult(1, aNbU, 1, aNbV); // Single span - use cache for all points for (int i = 0; i < aNbU; ++i) { - const double aU = myUParams.Value(i); + const double aU = theUParams.Value(theUParams.Lower() + i); for (int j = 0; j < aNbV; ++j) { gp_Pnt aPoint; gp_Vec aD1U, aD1V, aD2U, aD2V, aD2UV; - myCache->D2(aU, myVParams.Value(j), aPoint, aD1U, aD1V, aD2U, aD2V, aD2UV); + aCache + ->D2(aU, theVParams.Value(theVParams.Lower() + j), aPoint, aD1U, aD1V, aD2U, aD2V, aD2UV); aResult.ChangeValue(i + 1, j + 1) = {aPoint, aD1U, aD1V, aD2U, aD2V, aD2UV}; } } @@ -230,15 +203,17 @@ NCollection_Array2 GeomGridEval_BezierSurface::EvaluateGri //================================================================================================== -NCollection_Array2 GeomGridEval_BezierSurface::EvaluateGridD3() const +NCollection_Array2 GeomGridEval_BezierSurface::EvaluateGridD3( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams) const { - if (myGeom.IsNull() || myUParams.IsEmpty() || myVParams.IsEmpty()) + if (myGeom.IsNull() || theUParams.IsEmpty() || theVParams.IsEmpty()) { return NCollection_Array2(); } - const int aNbU = myUParams.Size(); - const int aNbV = myVParams.Size(); + const int aNbU = theUParams.Size(); + const int aNbV = theVParams.Size(); NCollection_Array2 aResult(1, aNbU, 1, aNbV); // Get degrees and create Bezier flat knots @@ -257,14 +232,14 @@ NCollection_Array2 GeomGridEval_BezierSurface::EvaluateGri // Bezier surface is single span (span index = 0), non-periodic for (int i = 0; i < aNbU; ++i) { - const double aU = myUParams.Value(i); + const double aU = theUParams.Value(theUParams.Lower() + i); for (int j = 0; j < aNbV; ++j) { gp_Pnt aPoint; gp_Vec aD1U, aD1V, aD2U, aD2V, aD2UV, aD3U, aD3V, aD3UUV, aD3UVV; BSplSLib::D3(aU, - myVParams.Value(j), + theVParams.Value(theVParams.Lower() + j), 0, // U span index (single span for Bezier) 0, // V span index (single span for Bezier) aPoles, @@ -301,16 +276,20 @@ NCollection_Array2 GeomGridEval_BezierSurface::EvaluateGri //================================================================================================== -NCollection_Array2 GeomGridEval_BezierSurface::EvaluateGridDN(int theNU, int theNV) const +NCollection_Array2 GeomGridEval_BezierSurface::EvaluateGridDN( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams, + int theNU, + int theNV) const { - if (myGeom.IsNull() || myUParams.IsEmpty() || myVParams.IsEmpty() || theNU < 0 || theNV < 0 + if (myGeom.IsNull() || theUParams.IsEmpty() || theVParams.IsEmpty() || theNU < 0 || theNV < 0 || (theNU + theNV) < 1) { return NCollection_Array2(); } - const int aNbU = myUParams.Size(); - const int aNbV = myVParams.Size(); + const int aNbU = theUParams.Size(); + const int aNbV = theVParams.Size(); NCollection_Array2 aResult(1, aNbU, 1, aNbV); @@ -344,12 +323,12 @@ NCollection_Array2 GeomGridEval_BezierSurface::EvaluateGridDN(int theNU, // Bezier has a single span (index 0 with flat knots), non-periodic for (int i = 0; i < aNbU; ++i) { - const double aU = myUParams.Value(i); + const double aU = theUParams.Value(theUParams.Lower() + i); for (int j = 0; j < aNbV; ++j) { gp_Vec aDN; BSplSLib::DN(aU, - myVParams.Value(j), + theVParams.Value(theVParams.Lower() + j), theNU, theNV, 0, // U span index (single span for Bezier with flat knots) @@ -373,3 +352,222 @@ NCollection_Array2 GeomGridEval_BezierSurface::EvaluateGridDN(int theNU, return aResult; } + +//================================================================================================== + +NCollection_Array1 GeomGridEval_BezierSurface::EvaluatePoints( + const NCollection_Array1& theUVPairs) const +{ + if (myGeom.IsNull() || theUVPairs.IsEmpty()) + { + return NCollection_Array1(); + } + + // Build cache (Bezier is single span, cache is built once) + Handle(BSplSLib_Cache) aCache = buildBezierCache(myGeom); + + const int aNbPts = theUVPairs.Size(); + NCollection_Array1 aResult(1, aNbPts); + + for (int i = 0; i < aNbPts; ++i) + { + const gp_Pnt2d& aUV = theUVPairs.Value(theUVPairs.Lower() + i); + gp_Pnt aPoint; + aCache->D0(aUV.X(), aUV.Y(), aPoint); + aResult.SetValue(i + 1, aPoint); + } + + return aResult; +} + +//================================================================================================== + +NCollection_Array1 GeomGridEval_BezierSurface::EvaluatePointsD1( + const NCollection_Array1& theUVPairs) const +{ + if (myGeom.IsNull() || theUVPairs.IsEmpty()) + { + return NCollection_Array1(); + } + + // Build cache (Bezier is single span, cache is built once) + Handle(BSplSLib_Cache) aCache = buildBezierCache(myGeom); + + const int aNbPts = theUVPairs.Size(); + NCollection_Array1 aResult(1, aNbPts); + + for (int i = 0; i < aNbPts; ++i) + { + const gp_Pnt2d& aUV = theUVPairs.Value(theUVPairs.Lower() + i); + gp_Pnt aPoint; + gp_Vec aD1U, aD1V; + aCache->D1(aUV.X(), aUV.Y(), aPoint, aD1U, aD1V); + aResult.ChangeValue(i + 1) = {aPoint, aD1U, aD1V}; + } + + return aResult; +} + +//================================================================================================== + +NCollection_Array1 GeomGridEval_BezierSurface::EvaluatePointsD2( + const NCollection_Array1& theUVPairs) const +{ + if (myGeom.IsNull() || theUVPairs.IsEmpty()) + { + return NCollection_Array1(); + } + + // Build cache (Bezier is single span, cache is built once) + Handle(BSplSLib_Cache) aCache = buildBezierCache(myGeom); + + const int aNbPts = theUVPairs.Size(); + NCollection_Array1 aResult(1, aNbPts); + + for (int i = 0; i < aNbPts; ++i) + { + const gp_Pnt2d& aUV = theUVPairs.Value(theUVPairs.Lower() + i); + gp_Pnt aPoint; + gp_Vec aD1U, aD1V, aD2U, aD2V, aD2UV; + aCache->D2(aUV.X(), aUV.Y(), aPoint, aD1U, aD1V, aD2U, aD2V, aD2UV); + aResult.ChangeValue(i + 1) = {aPoint, aD1U, aD1V, aD2U, aD2V, aD2UV}; + } + + return aResult; +} + +//================================================================================================== + +NCollection_Array1 GeomGridEval_BezierSurface::EvaluatePointsD3( + const NCollection_Array1& theUVPairs) const +{ + if (myGeom.IsNull() || theUVPairs.IsEmpty()) + { + return NCollection_Array1(); + } + + const int aNbPts = theUVPairs.Size(); + NCollection_Array1 aResult(1, aNbPts); + + // Get degrees and create Bezier flat knots + const int aUDegree = myGeom->UDegree(); + const int aVDegree = myGeom->VDegree(); + + TColStd_Array1OfReal aUFlatKnots(BSplCLib::FlatBezierKnots(aUDegree), 1, 2 * (aUDegree + 1)); + TColStd_Array1OfReal aVFlatKnots(BSplCLib::FlatBezierKnots(aVDegree), 1, 2 * (aVDegree + 1)); + + // Get poles and weights + const TColgp_Array2OfPnt& aPoles = myGeom->Poles(); + const TColStd_Array2OfReal* aWeights = myGeom->Weights(); + const bool isRational = (aWeights != nullptr); + + // D3 evaluation using BSplSLib::D3 directly + for (int i = 0; i < aNbPts; ++i) + { + const gp_Pnt2d& aUV = theUVPairs.Value(theUVPairs.Lower() + i); + gp_Pnt aPoint; + gp_Vec aD1U, aD1V, aD2U, aD2V, aD2UV, aD3U, aD3V, aD3UUV, aD3UVV; + + BSplSLib::D3(aUV.X(), + aUV.Y(), + 0, // U span index (single span for Bezier) + 0, // V span index (single span for Bezier) + aPoles, + aWeights, + aUFlatKnots, + aVFlatKnots, + nullptr, // U multiplicities (nullptr for flat knots) + nullptr, // V multiplicities (nullptr for flat knots) + aUDegree, + aVDegree, + isRational, + isRational, + false, // not U periodic + false, // not V periodic + aPoint, + aD1U, + aD1V, + aD2U, + aD2V, + aD2UV, + aD3U, + aD3V, + aD3UUV, + aD3UVV); + + aResult.ChangeValue(i + + 1) = {aPoint, aD1U, aD1V, aD2U, aD2V, aD2UV, aD3U, aD3V, aD3UUV, aD3UVV}; + } + + return aResult; +} + +//================================================================================================== + +NCollection_Array1 GeomGridEval_BezierSurface::EvaluatePointsDN( + const NCollection_Array1& theUVPairs, + int theNU, + int theNV) const +{ + if (myGeom.IsNull() || theUVPairs.IsEmpty() || theNU < 0 || theNV < 0 || (theNU + theNV) < 1) + { + return NCollection_Array1(); + } + + const int aNbPts = theUVPairs.Size(); + + NCollection_Array1 aResult(1, aNbPts); + + // For Bezier surfaces, derivatives become zero when order exceeds degree in that direction + const int aUDegree = myGeom->UDegree(); + const int aVDegree = myGeom->VDegree(); + + if (theNU > aUDegree || theNV > aVDegree) + { + // All derivatives are zero + const gp_Vec aZeroVec(0.0, 0.0, 0.0); + for (int i = 1; i <= aNbPts; ++i) + { + aResult.SetValue(i, aZeroVec); + } + return aResult; + } + + // Get poles and weights from geometry + const TColgp_Array2OfPnt& aPoles = myGeom->Poles(); + const TColStd_Array2OfReal* aWeights = myGeom->Weights(); + const bool isRational = (aWeights != nullptr); + + // Use pre-defined flat knots from BSplCLib + TColStd_Array1OfReal aUFlatKnots(BSplCLib::FlatBezierKnots(aUDegree), 1, 2 * (aUDegree + 1)); + TColStd_Array1OfReal aVFlatKnots(BSplCLib::FlatBezierKnots(aVDegree), 1, 2 * (aVDegree + 1)); + + // Bezier has a single span (index 0 with flat knots), non-periodic + for (int i = 0; i < aNbPts; ++i) + { + const gp_Pnt2d& aUV = theUVPairs.Value(theUVPairs.Lower() + i); + gp_Vec aDN; + BSplSLib::DN(aUV.X(), + aUV.Y(), + theNU, + theNV, + 0, // U span index (single span for Bezier with flat knots) + 0, // V span index (single span for Bezier with flat knots) + aPoles, + aWeights, + aUFlatKnots, + aVFlatKnots, + nullptr, // no U multiplicities with flat knots + nullptr, // no V multiplicities with flat knots + aUDegree, + aVDegree, + isRational, + isRational, + false, // not U-periodic + false, // not V-periodic + aDN); + aResult.SetValue(i + 1, aDN); + } + + return aResult; +} diff --git a/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_BezierSurface.hxx b/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_BezierSurface.hxx index bbb3e46b6d..da4a3b0a78 100644 --- a/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_BezierSurface.hxx +++ b/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_BezierSurface.hxx @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -31,8 +32,7 @@ //! Usage: //! @code //! GeomGridEval_BezierSurface anEvaluator(myGeomBezier); -//! anEvaluator.SetUVParams(myUParams, myVParams); -//! NCollection_Array2 aGrid = anEvaluator.EvaluateGrid(); +//! NCollection_Array2 aGrid = anEvaluator.EvaluateGrid(myUParams, myVParams); //! @endcode class GeomGridEval_BezierSurface { @@ -52,59 +52,99 @@ public: GeomGridEval_BezierSurface(GeomGridEval_BezierSurface&&) = delete; GeomGridEval_BezierSurface& operator=(GeomGridEval_BezierSurface&&) = delete; - //! Set UV parameters from two 1D arrays. - //! @param theUParams array of U parameter values - //! @param theVParams array of V parameter values - Standard_EXPORT void SetUVParams(const TColStd_Array1OfReal& theUParams, - const TColStd_Array1OfReal& theVParams); - //! Returns the geometry handle. const Handle(Geom_BezierSurface)& Geometry() const { return myGeom; } - //! Returns number of U parameters. - int NbUParams() const { return myUParams.Size(); } - - //! Returns number of V parameters. - int NbVParams() const { return myVParams.Size(); } - //! Evaluate all grid points. + //! @param[in] theUParams array of U parameter values + //! @param[in] theVParams array of V parameter values //! @return 2D array of evaluated points (1-based indexing), //! or empty array if geometry is null or no parameters set - Standard_EXPORT NCollection_Array2 EvaluateGrid() const; + Standard_EXPORT NCollection_Array2 EvaluateGrid( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams) const; //! Evaluate all grid points with first partial derivatives. + //! @param[in] theUParams array of U parameter values + //! @param[in] theVParams array of V parameter values //! @return 2D array of SurfD1 (1-based indexing), //! or empty array if geometry is null or no parameters set - Standard_EXPORT NCollection_Array2 EvaluateGridD1() const; + Standard_EXPORT NCollection_Array2 EvaluateGridD1( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams) const; //! Evaluate all grid points with first and second partial derivatives. + //! @param[in] theUParams array of U parameter values + //! @param[in] theVParams array of V parameter values //! @return 2D array of SurfD2 (1-based indexing), //! or empty array if geometry is null or no parameters set - Standard_EXPORT NCollection_Array2 EvaluateGridD2() const; + Standard_EXPORT NCollection_Array2 EvaluateGridD2( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams) const; //! Evaluate all grid points with derivatives up to third order. //! Uses direct Geom_BezierSurface::D3 evaluation. + //! @param[in] theUParams array of U parameter values + //! @param[in] theVParams array of V parameter values //! @return 2D array of SurfD3 (1-based indexing), //! or empty array if geometry is null or no parameters set - Standard_EXPORT NCollection_Array2 EvaluateGridD3() const; + Standard_EXPORT NCollection_Array2 EvaluateGridD3( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams) const; //! Evaluate partial derivative d^(NU+NV)S/(dU^NU dV^NV) at all grid points. //! For orders 1-3, reuses EvaluateGridD1/D2/D3. //! For orders > 3, uses geometry DN method. - //! @param theNU derivative order in U direction - //! @param theNV derivative order in V direction + //! @param[in] theUParams array of U parameter values + //! @param[in] theVParams array of V parameter values + //! @param[in] theNU derivative order in U direction + //! @param[in] theNV derivative order in V direction //! @return 2D array of derivative vectors (1-based indexing) - Standard_EXPORT NCollection_Array2 EvaluateGridDN(int theNU, int theNV) const; + Standard_EXPORT NCollection_Array2 EvaluateGridDN(const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams, + int theNU, + int theNV) const; + + //! Evaluate points at arbitrary UV pairs. + //! @param[in] theUVPairs array of UV coordinate pairs (U=X(), V=Y()) + //! @return array of evaluated points (1-based indexing), + //! or empty array if geometry is null or no parameters set + Standard_EXPORT NCollection_Array1 EvaluatePoints( + const NCollection_Array1& theUVPairs) const; + + //! Evaluate points with first partial derivatives at arbitrary UV pairs. + //! @param[in] theUVPairs array of UV coordinate pairs (U=X(), V=Y()) + //! @return array of SurfD1 (1-based indexing), + //! or empty array if geometry is null or no parameters set + Standard_EXPORT NCollection_Array1 EvaluatePointsD1( + const NCollection_Array1& theUVPairs) const; + + //! Evaluate points with first and second partial derivatives at arbitrary UV pairs. + //! @param[in] theUVPairs array of UV coordinate pairs (U=X(), V=Y()) + //! @return array of SurfD2 (1-based indexing), + //! or empty array if geometry is null or no parameters set + Standard_EXPORT NCollection_Array1 EvaluatePointsD2( + const NCollection_Array1& theUVPairs) const; + + //! Evaluate points with derivatives up to third order at arbitrary UV pairs. + //! @param[in] theUVPairs array of UV coordinate pairs (U=X(), V=Y()) + //! @return array of SurfD3 (1-based indexing), + //! or empty array if geometry is null or no parameters set + Standard_EXPORT NCollection_Array1 EvaluatePointsD3( + const NCollection_Array1& theUVPairs) const; + + //! Evaluate partial derivative d^(NU+NV)S/(dU^NU dV^NV) at arbitrary UV pairs. + //! @param[in] theUVPairs array of UV coordinate pairs (U=X(), V=Y()) + //! @param[in] theNU derivative order in U direction + //! @param[in] theNV derivative order in V direction + //! @return array of derivative vectors (1-based indexing) + Standard_EXPORT NCollection_Array1 EvaluatePointsDN( + const NCollection_Array1& theUVPairs, + int theNU, + int theNV) const; private: - //! Build cache for the Bezier surface (single span). - void buildCache() const; - -private: - Handle(Geom_BezierSurface) myGeom; - NCollection_Array1 myUParams; - NCollection_Array1 myVParams; - mutable Handle(BSplSLib_Cache) myCache; + Handle(Geom_BezierSurface) myGeom; }; #endif // _GeomGridEval_BezierSurface_HeaderFile diff --git a/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_Circle.cxx b/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_Circle.cxx index c8c3a6d103..555d6e8599 100644 --- a/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_Circle.cxx +++ b/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_Circle.cxx @@ -19,25 +19,16 @@ //================================================================================================== -void GeomGridEval_Circle::SetParams(const TColStd_Array1OfReal& theParams) +NCollection_Array1 GeomGridEval_Circle::EvaluateGrid( + const TColStd_Array1OfReal& theParams) const { - myParams.Resize(theParams.Lower(), theParams.Upper(), false); - for (int i = theParams.Lower(); i <= theParams.Upper(); ++i) - { - myParams.SetValue(i, theParams.Value(i)); - } -} - -//================================================================================================== - -NCollection_Array1 GeomGridEval_Circle::EvaluateGrid() const -{ - if (myGeom.IsNull() || myParams.IsEmpty()) + if (myGeom.IsNull() || theParams.IsEmpty()) { return NCollection_Array1(); } - NCollection_Array1 aResult(myParams.Lower(), myParams.Upper()); + const int aNb = theParams.Size(); + NCollection_Array1 aResult(1, aNb); // Extract circle data from geometry const gp_Circ& aCirc = myGeom->Circ(); @@ -57,13 +48,13 @@ NCollection_Array1 GeomGridEval_Circle::EvaluateGrid() const const double aYY = aYDir.Y(); const double aYZ = aYDir.Z(); - for (int i = myParams.Lower(); i <= myParams.Upper(); ++i) + for (int i = theParams.Lower(); i <= theParams.Upper(); ++i) { - const double u = myParams.Value(i); + const double u = theParams.Value(i); const double cosU = std::cos(u); const double sinU = std::sin(u); - aResult.SetValue(i, + aResult.SetValue(i - theParams.Lower() + 1, gp_Pnt(aCX + aRadius * (cosU * aXX + sinU * aYX), aCY + aRadius * (cosU * aXY + sinU * aYY), aCZ + aRadius * (cosU * aXZ + sinU * aYZ))); @@ -73,14 +64,16 @@ NCollection_Array1 GeomGridEval_Circle::EvaluateGrid() const //================================================================================================== -NCollection_Array1 GeomGridEval_Circle::EvaluateGridD1() const +NCollection_Array1 GeomGridEval_Circle::EvaluateGridD1( + const TColStd_Array1OfReal& theParams) const { - if (myGeom.IsNull() || myParams.IsEmpty()) + if (myGeom.IsNull() || theParams.IsEmpty()) { return NCollection_Array1(); } - NCollection_Array1 aResult(myParams.Lower(), myParams.Upper()); + const int aNb = theParams.Size(); + NCollection_Array1 aResult(1, aNb); const gp_Circ& aCirc = myGeom->Circ(); const gp_Pnt& aCenter = aCirc.Location(); @@ -98,34 +91,37 @@ NCollection_Array1 GeomGridEval_Circle::EvaluateGridD1() const double aYY = aYDir.Y(); const double aYZ = aYDir.Z(); - for (int i = myParams.Lower(); i <= myParams.Upper(); ++i) + for (int i = theParams.Lower(); i <= theParams.Upper(); ++i) { - const double u = myParams.Value(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) = {gp_Pnt(aCX + aRadius * (cosU * aXX + sinU * aYX), - aCY + aRadius * (cosU * aXY + sinU * aYY), - aCZ + aRadius * (cosU * aXZ + sinU * aYZ)), - gp_Vec(aRadius * (-sinU * aXX + cosU * aYX), - aRadius * (-sinU * aXY + cosU * aYY), - aRadius * (-sinU * aXZ + cosU * aYZ))}; + aResult.ChangeValue(i - theParams.Lower() + + 1) = {gp_Pnt(aCX + aRadius * (cosU * aXX + sinU * aYX), + aCY + aRadius * (cosU * aXY + sinU * aYY), + aCZ + aRadius * (cosU * aXZ + sinU * aYZ)), + gp_Vec(aRadius * (-sinU * aXX + cosU * aYX), + aRadius * (-sinU * aXY + cosU * aYY), + aRadius * (-sinU * aXZ + cosU * aYZ))}; } return aResult; } //================================================================================================== -NCollection_Array1 GeomGridEval_Circle::EvaluateGridD2() const +NCollection_Array1 GeomGridEval_Circle::EvaluateGridD2( + const TColStd_Array1OfReal& theParams) const { - if (myGeom.IsNull() || myParams.IsEmpty()) + if (myGeom.IsNull() || theParams.IsEmpty()) { return NCollection_Array1(); } - NCollection_Array1 aResult(myParams.Lower(), myParams.Upper()); + const int aNb = theParams.Size(); + NCollection_Array1 aResult(1, aNb); const gp_Circ& aCirc = myGeom->Circ(); const gp_Pnt& aCenter = aCirc.Location(); @@ -143,38 +139,41 @@ NCollection_Array1 GeomGridEval_Circle::EvaluateGridD2() const double aYY = aYDir.Y(); const double aYZ = aYDir.Z(); - for (int i = myParams.Lower(); i <= myParams.Upper(); ++i) + for (int i = theParams.Lower(); i <= theParams.Upper(); ++i) { - const double u = myParams.Value(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) = {gp_Pnt(aCX + aRadius * (cosU * aXX + sinU * aYX), - aCY + aRadius * (cosU * aXY + sinU * aYY), - aCZ + aRadius * (cosU * aXZ + sinU * aYZ)), - gp_Vec(aRadius * (-sinU * aXX + cosU * aYX), - aRadius * (-sinU * aXY + cosU * aYY), - aRadius * (-sinU * aXZ + cosU * aYZ)), - gp_Vec(aRadius * (-cosU * aXX - sinU * aYX), - aRadius * (-cosU * aXY - sinU * aYY), - aRadius * (-cosU * aXZ - sinU * aYZ))}; + aResult.ChangeValue(i - theParams.Lower() + + 1) = {gp_Pnt(aCX + aRadius * (cosU * aXX + sinU * aYX), + aCY + aRadius * (cosU * aXY + sinU * aYY), + aCZ + aRadius * (cosU * aXZ + sinU * aYZ)), + gp_Vec(aRadius * (-sinU * aXX + cosU * aYX), + aRadius * (-sinU * aXY + cosU * aYY), + aRadius * (-sinU * aXZ + cosU * aYZ)), + gp_Vec(aRadius * (-cosU * aXX - sinU * aYX), + aRadius * (-cosU * aXY - sinU * aYY), + aRadius * (-cosU * aXZ - sinU * aYZ))}; } return aResult; } //================================================================================================== -NCollection_Array1 GeomGridEval_Circle::EvaluateGridD3() const +NCollection_Array1 GeomGridEval_Circle::EvaluateGridD3( + const TColStd_Array1OfReal& theParams) const { - if (myGeom.IsNull() || myParams.IsEmpty()) + if (myGeom.IsNull() || theParams.IsEmpty()) { return NCollection_Array1(); } - NCollection_Array1 aResult(myParams.Lower(), myParams.Upper()); + const int aNb = theParams.Size(); + NCollection_Array1 aResult(1, aNb); const gp_Circ& aCirc = myGeom->Circ(); const gp_Pnt& aCenter = aCirc.Location(); @@ -192,9 +191,9 @@ NCollection_Array1 GeomGridEval_Circle::EvaluateGridD3() const double aYY = aYDir.Y(); const double aYZ = aYDir.Z(); - for (int i = myParams.Lower(); i <= myParams.Upper(); ++i) + for (int i = theParams.Lower(); i <= theParams.Upper(); ++i) { - const double u = myParams.Value(i); + const double u = theParams.Value(i); const double cosU = std::cos(u); const double sinU = std::sin(u); @@ -202,32 +201,36 @@ NCollection_Array1 GeomGridEval_Circle::EvaluateGridD3() // 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) = {gp_Pnt(aCX + aRadius * (cosU * aXX + sinU * aYX), - aCY + aRadius * (cosU * aXY + sinU * aYY), - aCZ + aRadius * (cosU * aXZ + sinU * aYZ)), - gp_Vec(aRadius * (-sinU * aXX + cosU * aYX), - aRadius * (-sinU * aXY + cosU * aYY), - aRadius * (-sinU * aXZ + cosU * aYZ)), - gp_Vec(aRadius * (-cosU * aXX - sinU * aYX), - aRadius * (-cosU * aXY - sinU * aYY), - aRadius * (-cosU * aXZ - sinU * aYZ)), - gp_Vec(aRadius * (sinU * aXX - cosU * aYX), - aRadius * (sinU * aXY - cosU * aYY), - aRadius * (sinU * aXZ - cosU * aYZ))}; + aResult.ChangeValue(i - theParams.Lower() + + 1) = {gp_Pnt(aCX + aRadius * (cosU * aXX + sinU * aYX), + aCY + aRadius * (cosU * aXY + sinU * aYY), + aCZ + aRadius * (cosU * aXZ + sinU * aYZ)), + gp_Vec(aRadius * (-sinU * aXX + cosU * aYX), + aRadius * (-sinU * aXY + cosU * aYY), + aRadius * (-sinU * aXZ + cosU * aYZ)), + gp_Vec(aRadius * (-cosU * aXX - sinU * aYX), + aRadius * (-cosU * aXY - sinU * aYY), + aRadius * (-cosU * aXZ - sinU * aYZ)), + gp_Vec(aRadius * (sinU * aXX - cosU * aYX), + aRadius * (sinU * aXY - cosU * aYY), + aRadius * (sinU * aXZ - cosU * aYZ))}; } return aResult; } //================================================================================================== -NCollection_Array1 GeomGridEval_Circle::EvaluateGridDN(int theN) const +NCollection_Array1 GeomGridEval_Circle::EvaluateGridDN( + const TColStd_Array1OfReal& theParams, + int theN) const { - if (myGeom.IsNull() || myParams.IsEmpty() || theN < 1) + if (myGeom.IsNull() || theParams.IsEmpty() || theN < 1) { return NCollection_Array1(); } - NCollection_Array1 aResult(myParams.Lower(), myParams.Upper()); + const int aNb = theParams.Size(); + NCollection_Array1 aResult(1, aNb); const gp_Circ& aCirc = myGeom->Circ(); const gp_Dir& aXDir = aCirc.Position().XDirection(); @@ -248,9 +251,9 @@ NCollection_Array1 GeomGridEval_Circle::EvaluateGridDN(int theN) const // 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 = myParams.Lower(); i <= myParams.Upper(); ++i) + for (int i = theParams.Lower(); i <= theParams.Upper(); ++i) { - const double u = myParams.Value(i); + const double u = theParams.Value(i); const double cosU = std::cos(u); const double sinU = std::sin(u); @@ -275,7 +278,7 @@ NCollection_Array1 GeomGridEval_Circle::EvaluateGridDN(int theN) const break; } - aResult.SetValue(i, + aResult.SetValue(i - theParams.Lower() + 1, gp_Vec(aRadius * (aCoeffX * aXX + aCoeffY * aYX), aRadius * (aCoeffX * aXY + aCoeffY * aYY), aRadius * (aCoeffX * aXZ + aCoeffY * aYZ))); diff --git a/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_Circle.hxx b/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_Circle.hxx index 364a93d6b4..71b5cdb8f1 100644 --- a/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_Circle.hxx +++ b/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_Circle.hxx @@ -28,8 +28,7 @@ //! Usage: //! @code //! GeomGridEval_Circle anEvaluator(myGeomCircle); -//! anEvaluator.SetParams(myParams); -//! NCollection_Array1 aGrid = anEvaluator.EvaluateGrid(); +//! NCollection_Array1 aGrid = anEvaluator.EvaluateGrid(myParams); //! @endcode class GeomGridEval_Circle { @@ -49,42 +48,39 @@ public: GeomGridEval_Circle(GeomGridEval_Circle&&) = delete; GeomGridEval_Circle& operator=(GeomGridEval_Circle&&) = delete; - //! Set parameters for grid evaluation (by const reference). - //! @param theParams array of parameter values (angles in radians) - Standard_EXPORT void SetParams(const TColStd_Array1OfReal& theParams); - - //! Set parameters for grid evaluation (by move). - //! @param theParams array of parameter values to move - void SetParams(NCollection_Array1&& theParams) { myParams = std::move(theParams); } - //! Returns the geometry handle. const Handle(Geom_Circle)& Geometry() const { return myGeom; } - //! Returns number of parameters. - int NbParams() const { return myParams.Size(); } - //! 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 set - Standard_EXPORT NCollection_Array1 EvaluateGrid() const; + //! or empty array if geometry is null or no parameters + Standard_EXPORT NCollection_Array1 EvaluateGrid( + const TColStd_Array1OfReal& 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 set - Standard_EXPORT NCollection_Array1 EvaluateGridD1() const; + //! or empty array if geometry is null or no parameters + Standard_EXPORT NCollection_Array1 EvaluateGridD1( + const TColStd_Array1OfReal& 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 set - Standard_EXPORT NCollection_Array1 EvaluateGridD2() const; + //! or empty array if geometry is null or no parameters + Standard_EXPORT NCollection_Array1 EvaluateGridD2( + const TColStd_Array1OfReal& 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 set - Standard_EXPORT NCollection_Array1 EvaluateGridD3() const; + //! or empty array if geometry is null or no parameters + Standard_EXPORT NCollection_Array1 EvaluateGridD3( + const TColStd_Array1OfReal& theParams) const; //! Evaluate Nth derivative at all grid points. //! Circle has cyclic derivatives with period 4: @@ -92,14 +88,15 @@ public: //! 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 set - Standard_EXPORT NCollection_Array1 EvaluateGridDN(int theN) const; + //! or empty array if geometry is null or no parameters + Standard_EXPORT NCollection_Array1 EvaluateGridDN(const TColStd_Array1OfReal& theParams, + int theN) const; private: - Handle(Geom_Circle) myGeom; - NCollection_Array1 myParams; + Handle(Geom_Circle) myGeom; }; #endif // _GeomGridEval_Circle_HeaderFile diff --git a/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_Cone.cxx b/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_Cone.cxx index 7e065a099c..c817cfa54f 100644 --- a/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_Cone.cxx +++ b/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_Cone.cxx @@ -19,612 +19,507 @@ //================================================================================================== -void GeomGridEval_Cone::SetUVParams(const TColStd_Array1OfReal& theUParams, - const TColStd_Array1OfReal& theVParams) +GeomGridEval_Cone::Data GeomGridEval_Cone::extractData() const { - const int aNbU = theUParams.Size(); - const int aNbV = theVParams.Size(); + const gp_Cone& aCone = myGeom->Cone(); + const gp_Pnt& aCenter = aCone.Location(); + const gp_Dir& aXDir = aCone.Position().XDirection(); + const gp_Dir& aYDir = aCone.Position().YDirection(); + const gp_Dir& aZDir = aCone.Position().Direction(); - myUParams.Resize(1, aNbU, false); - for (int i = 1; i <= aNbU; ++i) - { - myUParams.SetValue(i, theUParams.Value(theUParams.Lower() + i - 1)); - } - - myVParams.Resize(1, aNbV, false); - for (int j = 1; j <= aNbV; ++j) - { - myVParams.SetValue(j, theVParams.Value(theVParams.Lower() + j - 1)); - } + return {aCenter.X(), + aCenter.Y(), + aCenter.Z(), + aXDir.X(), + aXDir.Y(), + aXDir.Z(), + aYDir.X(), + aYDir.Y(), + aYDir.Z(), + aZDir.X(), + aZDir.Y(), + aZDir.Z(), + aCone.RefRadius(), + std::sin(aCone.SemiAngle()), + std::cos(aCone.SemiAngle())}; } //================================================================================================== -NCollection_Array2 GeomGridEval_Cone::EvaluateGrid() const +GeomGridEval_Cone::UContext GeomGridEval_Cone::computeUContext(const Data& theData, double theU) { - if (myGeom.IsNull() || myUParams.IsEmpty() || myVParams.IsEmpty()) - { - return NCollection_Array2(); - } + const double cosU = std::cos(theU); + const double sinU = std::sin(theU); - const int aNbU = myUParams.Size(); - const int aNbV = myVParams.Size(); + // DirU = cosU*XDir + sinU*YDir (radial direction at angle U) + // dDirU = -sinU*XDir + cosU*YDir (derivative of DirU w.r.t. U) + return {cosU, + sinU, + cosU * theData.XX + sinU * theData.YX, + cosU * theData.XY + sinU * theData.YY, + cosU * theData.XZ + sinU * theData.YZ, + -sinU * theData.XX + cosU * theData.YX, + -sinU * theData.XY + cosU * theData.YY, + -sinU * theData.XZ + cosU * theData.YZ}; +} - NCollection_Array2 aResult(1, aNbU, 1, aNbV); +//================================================================================================== - // Extract cone data - const gp_Cone& aCone = myGeom->Cone(); - const gp_Pnt& aCenter = aCone.Location(); - const gp_Dir& aXDir = aCone.Position().XDirection(); - const gp_Dir& aYDir = aCone.Position().YDirection(); - const gp_Dir& aZDir = aCone.Position().Direction(); - const double aRefRadius = aCone.RefRadius(); - const double aSemiAngle = aCone.SemiAngle(); - - const double aCX = aCenter.X(); - const double aCY = aCenter.Y(); - const double aCZ = aCenter.Z(); - const double aXX = aXDir.X(); - const double aXY = aXDir.Y(); - const double aXZ = aXDir.Z(); - const double aYX = aYDir.X(); - const double aYY = aYDir.Y(); - const double aYZ = aYDir.Z(); - const double aZX = aZDir.X(); - const double aZY = aZDir.Y(); - const double aZZ = aZDir.Z(); - - const double sinAng = std::sin(aSemiAngle); - const double cosAng = std::cos(aSemiAngle); - - // Pre-compute V-dependent values - // K(v) = R + v * sin(Ang) +gp_Pnt GeomGridEval_Cone::computeD0(const Data& theData, const UContext& theUCtx, double theV) +{ + // K(v) = RefRadius + v * sin(Ang) + const double K = theData.RefRadius + theV * theData.SinAng; // ZOffset(v) = v * cos(Ang) - NCollection_Array1 aKv(1, aNbV); - NCollection_Array1 aZOffset(1, aNbV); - for (int iV = 1; iV <= aNbV; ++iV) - { - const double v = myVParams.Value(iV); - aKv.SetValue(iV, aRefRadius + v * sinAng); - aZOffset.SetValue(iV, v * cosAng); - } + const double ZOff = theV * theData.CosAng; - for (int iU = 1; iU <= aNbU; ++iU) - { - const double u = myUParams.Value(iU); - const double cosU = std::cos(u); - const double sinU = std::sin(u); - - // DirU = cosU*XDir + sinU*YDir - const double dirUX = cosU * aXX + sinU * aYX; - const double dirUY = cosU * aXY + sinU * aYY; - const double dirUZ = cosU * aXZ + sinU * aYZ; - - for (int iV = 1; iV <= aNbV; ++iV) - { - const double K = aKv.Value(iV); - const double ZOff = aZOffset.Value(iV); - - // P = Center + K(v) * DirU + ZOffset(v) * ZDir - aResult.SetValue(iU, - iV, - gp_Pnt(aCX + K * dirUX + ZOff * aZX, - aCY + K * dirUY + ZOff * aZY, - aCZ + K * dirUZ + ZOff * aZZ)); - } - } - return aResult; + // P = Center + K(v) * DirU + ZOffset(v) * ZDir + return gp_Pnt(theData.CX + K * theUCtx.dirUX + ZOff * theData.ZX, + theData.CY + K * theUCtx.dirUY + ZOff * theData.ZY, + theData.CZ + K * theUCtx.dirUZ + ZOff * theData.ZZ); } //================================================================================================== -NCollection_Array2 GeomGridEval_Cone::EvaluateGridD1() const +GeomGridEval::SurfD1 GeomGridEval_Cone::computeD1(const Data& theData, + const UContext& theUCtx, + double theV) { - if (myGeom.IsNull() || myUParams.IsEmpty() || myVParams.IsEmpty()) - { - return NCollection_Array2(); - } + const double K = theData.RefRadius + theV * theData.SinAng; + const double ZOff = theV * theData.CosAng; - const int aNbU = myUParams.Size(); - const int aNbV = myVParams.Size(); - - NCollection_Array2 aResult(1, aNbU, 1, aNbV); - - const gp_Cone& aCone = myGeom->Cone(); - const gp_Pnt& aCenter = aCone.Location(); - const gp_Dir& aXDir = aCone.Position().XDirection(); - const gp_Dir& aYDir = aCone.Position().YDirection(); - const gp_Dir& aZDir = aCone.Position().Direction(); - const double aRefRadius = aCone.RefRadius(); - const double aSemiAngle = aCone.SemiAngle(); - - const double aCX = aCenter.X(); - const double aCY = aCenter.Y(); - const double aCZ = aCenter.Z(); - const double aXX = aXDir.X(); - const double aXY = aXDir.Y(); - const double aXZ = aXDir.Z(); - const double aYX = aYDir.X(); - const double aYY = aYDir.Y(); - const double aYZ = aYDir.Z(); - const double aZX = aZDir.X(); - const double aZY = aZDir.Y(); - const double aZZ = aZDir.Z(); - - const double sinAng = std::sin(aSemiAngle); - const double cosAng = std::cos(aSemiAngle); - - // Pre-compute V-dependent values - NCollection_Array1 aKv(1, aNbV); - NCollection_Array1 aZOffset(1, aNbV); - for (int iV = 1; iV <= aNbV; ++iV) - { - const double v = myVParams.Value(iV); - aKv.SetValue(iV, aRefRadius + v * sinAng); - aZOffset.SetValue(iV, v * cosAng); - } - - for (int iU = 1; iU <= aNbU; ++iU) - { - const double u = myUParams.Value(iU); - const double cosU = std::cos(u); - const double sinU = std::sin(u); - - // DirU = cosU*XDir + sinU*YDir - const double dirUX = cosU * aXX + sinU * aYX; - const double dirUY = cosU * aXY + sinU * aYY; - const double dirUZ = cosU * aXZ + sinU * aYZ; - - // DerivDirU = -sinU*XDir + cosU*YDir - const double dDirUX = -sinU * aXX + cosU * aYX; - const double dDirUY = -sinU * aXY + cosU * aYY; - const double dDirUZ = -sinU * aXZ + cosU * aYZ; - - // D1V is constant for a given U: sin(Ang)*DirU + cos(Ang)*ZDir - const double dV1 = sinAng * dirUX + cosAng * aZX; - const double dV2 = sinAng * dirUY + cosAng * aZY; - const double dV3 = sinAng * dirUZ + cosAng * aZZ; - - for (int iV = 1; iV <= aNbV; ++iV) - { - const double K = aKv.Value(iV); - const double ZOff = aZOffset.Value(iV); - - // P - const double pX = aCX + K * dirUX + ZOff * aZX; - const double pY = aCY + K * dirUY + ZOff * aZY; - const double pZ = aCZ + K * dirUZ + ZOff * aZZ; - - // D1U = K(v) * DerivDirU - const double dU1 = K * dDirUX; - const double dU2 = K * dDirUY; - const double dU3 = K * dDirUZ; - - aResult.ChangeValue(iU, - iV) = {gp_Pnt(pX, pY, pZ), gp_Vec(dU1, dU2, dU3), gp_Vec(dV1, dV2, dV3)}; - } - } - return aResult; + // D1U = K(v) * dDirU + // D1V = sin(Ang)*DirU + cos(Ang)*ZDir + return {gp_Pnt(theData.CX + K * theUCtx.dirUX + ZOff * theData.ZX, + theData.CY + K * theUCtx.dirUY + ZOff * theData.ZY, + theData.CZ + K * theUCtx.dirUZ + ZOff * theData.ZZ), + gp_Vec(K * theUCtx.dDirUX, K * theUCtx.dDirUY, K * theUCtx.dDirUZ), + gp_Vec(theData.SinAng * theUCtx.dirUX + theData.CosAng * theData.ZX, + theData.SinAng * theUCtx.dirUY + theData.CosAng * theData.ZY, + theData.SinAng * theUCtx.dirUZ + theData.CosAng * theData.ZZ)}; } //================================================================================================== -NCollection_Array2 GeomGridEval_Cone::EvaluateGridD2() const +GeomGridEval::SurfD2 GeomGridEval_Cone::computeD2(const Data& theData, + const UContext& theUCtx, + double theV) { - if (myGeom.IsNull() || myUParams.IsEmpty() || myVParams.IsEmpty()) - { - return NCollection_Array2(); - } + const double K = theData.RefRadius + theV * theData.SinAng; + const double ZOff = theV * theData.CosAng; - const int aNbU = myUParams.Size(); - const int aNbV = myVParams.Size(); + // D2U = K * (-DirU) = -K * DirU + // D2V = 0 + // D2UV = sin(Ang) * dDirU + const gp_Vec aZero(0.0, 0.0, 0.0); - NCollection_Array2 aResult(1, aNbU, 1, aNbV); - - const gp_Cone& aCone = myGeom->Cone(); - const gp_Pnt& aCenter = aCone.Location(); - const gp_Dir& aXDir = aCone.Position().XDirection(); - const gp_Dir& aYDir = aCone.Position().YDirection(); - const gp_Dir& aZDir = aCone.Position().Direction(); - const double aRefRadius = aCone.RefRadius(); - const double aSemiAngle = aCone.SemiAngle(); - - const double aCX = aCenter.X(); - const double aCY = aCenter.Y(); - const double aCZ = aCenter.Z(); - const double aXX = aXDir.X(); - const double aXY = aXDir.Y(); - const double aXZ = aXDir.Z(); - const double aYX = aYDir.X(); - const double aYY = aYDir.Y(); - const double aYZ = aYDir.Z(); - const double aZX = aZDir.X(); - const double aZY = aZDir.Y(); - const double aZZ = aZDir.Z(); - - const double sinAng = std::sin(aSemiAngle); - const double cosAng = std::cos(aSemiAngle); - - // Pre-compute V-dependent values - NCollection_Array1 aKv(1, aNbV); - NCollection_Array1 aZOffset(1, aNbV); - for (int iV = 1; iV <= aNbV; ++iV) - { - const double v = myVParams.Value(iV); - aKv.SetValue(iV, aRefRadius + v * sinAng); - aZOffset.SetValue(iV, v * cosAng); - } - - for (int iU = 1; iU <= aNbU; ++iU) - { - const double u = myUParams.Value(iU); - const double cosU = std::cos(u); - const double sinU = std::sin(u); - - // DirU = cosU*XDir + sinU*YDir - const double dirUX = cosU * aXX + sinU * aYX; - const double dirUY = cosU * aXY + sinU * aYY; - const double dirUZ = cosU * aXZ + sinU * aYZ; - - // DerivDirU = -sinU*XDir + cosU*YDir - const double dDirUX = -sinU * aXX + cosU * aYX; - const double dDirUY = -sinU * aXY + cosU * aYY; - const double dDirUZ = -sinU * aXZ + cosU * aYZ; - - // Deriv2DirU = -cosU*XDir - sinU*YDir = -DirU - const double d2DirUX = -dirUX; - const double d2DirUY = -dirUY; - const double d2DirUZ = -dirUZ; - - // D1V is constant for a given U: sin(Ang)*DirU + cos(Ang)*ZDir - const double dV1 = sinAng * dirUX + cosAng * aZX; - const double dV2 = sinAng * dirUY + cosAng * aZY; - const double dV3 = sinAng * dirUZ + cosAng * aZZ; - - // D2UV = sin(Ang) * DerivDirU - const double d2UV1 = sinAng * dDirUX; - const double d2UV2 = sinAng * dDirUY; - const double d2UV3 = sinAng * dDirUZ; - - // D2V = 0 - const gp_Vec aZeroVec(0.0, 0.0, 0.0); - - for (int iV = 1; iV <= aNbV; ++iV) - { - const double K = aKv.Value(iV); - const double ZOff = aZOffset.Value(iV); - - // P - const double pX = aCX + K * dirUX + ZOff * aZX; - const double pY = aCY + K * dirUY + ZOff * aZY; - const double pZ = aCZ + K * dirUZ + ZOff * aZZ; - - // D1U = K(v) * DerivDirU - const double dU1 = K * dDirUX; - const double dU2 = K * dDirUY; - const double dU3 = K * dDirUZ; - - // D2U = K * Deriv2DirU - const double d2U1 = K * d2DirUX; - const double d2U2 = K * d2DirUY; - const double d2U3 = K * d2DirUZ; - - aResult.ChangeValue(iU, iV) = {gp_Pnt(pX, pY, pZ), - gp_Vec(dU1, dU2, dU3), - gp_Vec(dV1, dV2, dV3), - gp_Vec(d2U1, d2U2, d2U3), - aZeroVec, // D2V - gp_Vec(d2UV1, d2UV2, d2UV3)}; - } - } - return aResult; + return {gp_Pnt(theData.CX + K * theUCtx.dirUX + ZOff * theData.ZX, + theData.CY + K * theUCtx.dirUY + ZOff * theData.ZY, + theData.CZ + K * theUCtx.dirUZ + ZOff * theData.ZZ), + gp_Vec(K * theUCtx.dDirUX, K * theUCtx.dDirUY, K * theUCtx.dDirUZ), + gp_Vec(theData.SinAng * theUCtx.dirUX + theData.CosAng * theData.ZX, + theData.SinAng * theUCtx.dirUY + theData.CosAng * theData.ZY, + theData.SinAng * theUCtx.dirUZ + theData.CosAng * theData.ZZ), + gp_Vec(-K * theUCtx.dirUX, -K * theUCtx.dirUY, -K * theUCtx.dirUZ), + aZero, + gp_Vec(theData.SinAng * theUCtx.dDirUX, + theData.SinAng * theUCtx.dDirUY, + theData.SinAng * theUCtx.dDirUZ)}; } //================================================================================================== -NCollection_Array2 GeomGridEval_Cone::EvaluateGridD3() const +GeomGridEval::SurfD3 GeomGridEval_Cone::computeD3(const Data& theData, + const UContext& theUCtx, + double theV) { - if (myGeom.IsNull() || myUParams.IsEmpty() || myVParams.IsEmpty()) - { - return NCollection_Array2(); - } + const double K = theData.RefRadius + theV * theData.SinAng; + const double ZOff = theV * theData.CosAng; - const int aNbU = myUParams.Size(); - const int aNbV = myVParams.Size(); + // D3U = -K * dDirU = -D1U + // D3V = 0 + // D3UUV = -sin(Ang) * DirU + // D3UVV = 0 + const gp_Vec aZero(0.0, 0.0, 0.0); - NCollection_Array2 aResult(1, aNbU, 1, aNbV); - - const gp_Cone& aCone = myGeom->Cone(); - const gp_Pnt& aCenter = aCone.Location(); - const gp_Dir& aXDir = aCone.Position().XDirection(); - const gp_Dir& aYDir = aCone.Position().YDirection(); - const gp_Dir& aZDir = aCone.Position().Direction(); - const double aRefRadius = aCone.RefRadius(); - const double aSemiAngle = aCone.SemiAngle(); - - const double aCX = aCenter.X(); - const double aCY = aCenter.Y(); - const double aCZ = aCenter.Z(); - const double aXX = aXDir.X(); - const double aXY = aXDir.Y(); - const double aXZ = aXDir.Z(); - const double aYX = aYDir.X(); - const double aYY = aYDir.Y(); - const double aYZ = aYDir.Z(); - const double aZX = aZDir.X(); - const double aZY = aZDir.Y(); - const double aZZ = aZDir.Z(); - - const double sinAng = std::sin(aSemiAngle); - const double cosAng = std::cos(aSemiAngle); - - const gp_Vec aZeroVec(0.0, 0.0, 0.0); - - // Pre-compute V-dependent values - NCollection_Array1 aKv(1, aNbV); - NCollection_Array1 aZOffset(1, aNbV); - for (int iV = 1; iV <= aNbV; ++iV) - { - const double v = myVParams.Value(iV); - aKv.SetValue(iV, aRefRadius + v * sinAng); - aZOffset.SetValue(iV, v * cosAng); - } - - for (int iU = 1; iU <= aNbU; ++iU) - { - const double u = myUParams.Value(iU); - const double cosU = std::cos(u); - const double sinU = std::sin(u); - - // DirU = cosU*XDir + sinU*YDir - const double dirUX = cosU * aXX + sinU * aYX; - const double dirUY = cosU * aXY + sinU * aYY; - const double dirUZ = cosU * aXZ + sinU * aYZ; - - // DerivDirU = -sinU*XDir + cosU*YDir - const double dDirUX = -sinU * aXX + cosU * aYX; - const double dDirUY = -sinU * aXY + cosU * aYY; - const double dDirUZ = -sinU * aXZ + cosU * aYZ; - - // D1V is constant for a given U: sin(Ang)*DirU + cos(Ang)*ZDir - const double dV1 = sinAng * dirUX + cosAng * aZX; - const double dV2 = sinAng * dirUY + cosAng * aZY; - const double dV3 = sinAng * dirUZ + cosAng * aZZ; - - // D2UV = sin(Ang) * DerivDirU - const double d2UV1 = sinAng * dDirUX; - const double d2UV2 = sinAng * dDirUY; - const double d2UV3 = sinAng * dDirUZ; - - // D3UUV = -sin(Ang) * DirU (derivative of D2UV w.r.t. U) - const double d3UUV1 = -sinAng * dirUX; - const double d3UUV2 = -sinAng * dirUY; - const double d3UUV3 = -sinAng * dirUZ; - - for (int iV = 1; iV <= aNbV; ++iV) - { - const double K = aKv.Value(iV); - const double ZOff = aZOffset.Value(iV); - - // P = Center + K * DirU + ZOff * ZDir - const double pX = aCX + K * dirUX + ZOff * aZX; - const double pY = aCY + K * dirUY + ZOff * aZY; - const double pZ = aCZ + K * dirUZ + ZOff * aZZ; - - // D1U = K * DerivDirU - const double dU1 = K * dDirUX; - const double dU2 = K * dDirUY; - const double dU3 = K * dDirUZ; - - // D2U = -K * DirU - const double d2U1 = -K * dirUX; - const double d2U2 = -K * dirUY; - const double d2U3 = -K * dirUZ; - - // D3U = -D1U (derivative of D2U w.r.t. U = -K * DerivDirU) - const double d3U1 = -dU1; - const double d3U2 = -dU2; - const double d3U3 = -dU3; - - aResult.ChangeValue(iU, iV) = {gp_Pnt(pX, pY, pZ), - gp_Vec(dU1, dU2, dU3), - gp_Vec(dV1, dV2, dV3), - gp_Vec(d2U1, d2U2, d2U3), - aZeroVec, // D2V = 0 - gp_Vec(d2UV1, d2UV2, d2UV3), - gp_Vec(d3U1, d3U2, d3U3), - aZeroVec, // D3V = 0 - gp_Vec(d3UUV1, d3UUV2, d3UUV3), - aZeroVec}; // D3UVV = 0 - } - } - return aResult; + return {gp_Pnt(theData.CX + K * theUCtx.dirUX + ZOff * theData.ZX, + theData.CY + K * theUCtx.dirUY + ZOff * theData.ZY, + theData.CZ + K * theUCtx.dirUZ + ZOff * theData.ZZ), + gp_Vec(K * theUCtx.dDirUX, K * theUCtx.dDirUY, K * theUCtx.dDirUZ), + gp_Vec(theData.SinAng * theUCtx.dirUX + theData.CosAng * theData.ZX, + theData.SinAng * theUCtx.dirUY + theData.CosAng * theData.ZY, + theData.SinAng * theUCtx.dirUZ + theData.CosAng * theData.ZZ), + gp_Vec(-K * theUCtx.dirUX, -K * theUCtx.dirUY, -K * theUCtx.dirUZ), + aZero, + gp_Vec(theData.SinAng * theUCtx.dDirUX, + theData.SinAng * theUCtx.dDirUY, + theData.SinAng * theUCtx.dDirUZ), + gp_Vec(-K * theUCtx.dDirUX, -K * theUCtx.dDirUY, -K * theUCtx.dDirUZ), + aZero, + gp_Vec(-theData.SinAng * theUCtx.dirUX, + -theData.SinAng * theUCtx.dirUY, + -theData.SinAng * theUCtx.dirUZ), + aZero}; } //================================================================================================== -NCollection_Array2 GeomGridEval_Cone::EvaluateGridDN(int theNU, int theNV) const +gp_Vec GeomGridEval_Cone::computeDN(const Data& theData, + const UContext& theUCtx, + double theV, + int theNU, + int theNV) { - if (myGeom.IsNull() || myUParams.IsEmpty() || myVParams.IsEmpty() || theNU < 0 || theNV < 0 - || (theNU + theNV) < 1) - { - return NCollection_Array2(); - } - - const int aNbU = myUParams.Size(); - const int aNbV = myVParams.Size(); - - NCollection_Array2 aResult(1, aNbU, 1, aNbV); - // For cone P(u,v) = C + K(v) * DirU(u) + v*cos(Ang)*Z // where K(v) = RefRadius + v*sin(Ang), DirU(u) = cos(u)*X + sin(u)*Y // // V is linear, so: // - All derivatives with NV >= 2 are zero - // - D_{0,1} = sin(Ang)*DirU + cos(Ang)*Z (constant) + // - D_{0,1} = sin(Ang)*DirU + cos(Ang)*Z // - D_{nu,1} = sin(Ang) * d^nu(DirU)/du^nu for nu >= 1 // - D_{nu,0} = K(v) * d^nu(DirU)/du^nu - // - // DirU derivatives cycle with period 4: - // phase 0: cos(u)*X + sin(u)*Y = DirU - // phase 1: -sin(u)*X + cos(u)*Y = DirU' - // phase 2: -cos(u)*X - sin(u)*Y = -DirU - // phase 3: sin(u)*X - cos(u)*Y = -DirU' - // All derivatives with NV >= 2 are zero (V is linear) - if (theNV >= 2) + if (theNV > 1) { - const gp_Vec aZeroVec(0.0, 0.0, 0.0); - for (int iU = 1; iU <= aNbU; ++iU) - { - for (int iV = 1; iV <= aNbV; ++iV) - { - aResult.SetValue(iU, iV, aZeroVec); - } - } - return aResult; + return gp_Vec(0.0, 0.0, 0.0); } - // Extract cone data - const gp_Cone& aCone = myGeom->Cone(); - const gp_Dir& aXDir = aCone.Position().XDirection(); - const gp_Dir& aYDir = aCone.Position().YDirection(); - const gp_Dir& aZDir = aCone.Position().Direction(); - const double aRefRadius = aCone.RefRadius(); - const double aSemiAngle = aCone.SemiAngle(); + // DirU derivatives cycle with period 4: + // phase 0: DirU + // phase 1: dDirU + // phase 2: -DirU + // phase 3: -dDirU + const int aPhase = theNU % 4; - const double aXX = aXDir.X(); - const double aXY = aXDir.Y(); - const double aXZ = aXDir.Z(); - const double aYX = aYDir.X(); - const double aYY = aYDir.Y(); - const double aYZ = aYDir.Z(); - const double aZX = aZDir.X(); - const double aZY = aZDir.Y(); - const double aZZ = aZDir.Z(); - - const double sinAng = std::sin(aSemiAngle); - const double cosAng = std::cos(aSemiAngle); - - // Phase for U derivatives (period 4) - const int aPhaseU = theNU % 4; - - if (theNV == 0) + double dirX, dirY, dirZ; + switch (aPhase) { - // Pure U derivative: D_{nu,0} = K(v) * d^nu(DirU)/du^nu - // Pre-compute K(v) - NCollection_Array1 aKv(1, aNbV); + case 0: + dirX = theUCtx.dirUX; + dirY = theUCtx.dirUY; + dirZ = theUCtx.dirUZ; + break; + case 1: + dirX = theUCtx.dDirUX; + dirY = theUCtx.dDirUY; + dirZ = theUCtx.dDirUZ; + break; + case 2: + dirX = -theUCtx.dirUX; + dirY = -theUCtx.dirUY; + dirZ = -theUCtx.dirUZ; + break; + case 3: + dirX = -theUCtx.dDirUX; + dirY = -theUCtx.dDirUY; + dirZ = -theUCtx.dDirUZ; + break; + default: + dirX = 0.0; + dirY = 0.0; + dirZ = 0.0; + break; + } + + if (theNV == 1) + { + if (theNU == 0) + { + // D_{0,1} = sin(Ang)*DirU + cos(Ang)*Z + return gp_Vec(theData.SinAng * theUCtx.dirUX + theData.CosAng * theData.ZX, + theData.SinAng * theUCtx.dirUY + theData.CosAng * theData.ZY, + theData.SinAng * theUCtx.dirUZ + theData.CosAng * theData.ZZ); + } + + // D_{nu,1} = sin(Ang) * d^nu(DirU)/du^nu for nu >= 1 + return gp_Vec(theData.SinAng * dirX, theData.SinAng * dirY, theData.SinAng * dirZ); + } + + // Pure U derivative (theNV == 0, theNU >= 1) + // D_{nu,0} = K(v) * d^nu(DirU)/du^nu + const double K = theData.RefRadius + theV * theData.SinAng; + return gp_Vec(K * dirX, K * dirY, K * dirZ); +} + +//================================================================================================== + +NCollection_Array2 GeomGridEval_Cone::EvaluateGrid( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams) const +{ + if (myGeom.IsNull() || theUParams.IsEmpty() || theVParams.IsEmpty()) + { + return NCollection_Array2(); + } + + const Data aData = extractData(); + const int aNbU = theUParams.Length(); + const int aNbV = theVParams.Length(); + + NCollection_Array2 aResult(1, aNbU, 1, aNbV); + + for (int iU = 1; iU <= aNbU; ++iU) + { + const double aU = theUParams.Value(theUParams.Lower() + iU - 1); + const UContext aUCtx = computeUContext(aData, aU); + for (int iV = 1; iV <= aNbV; ++iV) { - const double v = myVParams.Value(iV); - aKv.SetValue(iV, aRefRadius + v * sinAng); - } - - for (int iU = 1; iU <= aNbU; ++iU) - { - const double u = myUParams.Value(iU); - const double cosU = std::cos(u); - const double sinU = std::sin(u); - - // Compute d^nu(DirU)/du^nu based on phase - double dirDnX, dirDnY, dirDnZ; - switch (aPhaseU) - { - case 0: // cos(u)*X + sin(u)*Y - dirDnX = cosU * aXX + sinU * aYX; - dirDnY = cosU * aXY + sinU * aYY; - dirDnZ = cosU * aXZ + sinU * aYZ; - break; - case 1: // -sin(u)*X + cos(u)*Y - dirDnX = -sinU * aXX + cosU * aYX; - dirDnY = -sinU * aXY + cosU * aYY; - dirDnZ = -sinU * aXZ + cosU * aYZ; - break; - case 2: // -cos(u)*X - sin(u)*Y - dirDnX = -cosU * aXX - sinU * aYX; - dirDnY = -cosU * aXY - sinU * aYY; - dirDnZ = -cosU * aXZ - sinU * aYZ; - break; - case 3: // sin(u)*X - cos(u)*Y - default: - dirDnX = sinU * aXX - cosU * aYX; - dirDnY = sinU * aXY - cosU * aYY; - dirDnZ = sinU * aXZ - cosU * aYZ; - break; - } - - for (int iV = 1; iV <= aNbV; ++iV) - { - const double K = aKv.Value(iV); - aResult.SetValue(iU, iV, gp_Vec(K * dirDnX, K * dirDnY, K * dirDnZ)); - } - } - } - else // theNV == 1 - { - // Mixed derivative: D_{nu,1} = sin(Ang) * d^nu(DirU)/du^nu for nu >= 1 - // Special case: D_{0,1} = sin(Ang)*DirU + cos(Ang)*Z - - for (int iU = 1; iU <= aNbU; ++iU) - { - const double u = myUParams.Value(iU); - const double cosU = std::cos(u); - const double sinU = std::sin(u); - - double resX, resY, resZ; - - if (theNU == 0) - { - // D_{0,1} = sin(Ang)*DirU + cos(Ang)*Z - const double dirUX = cosU * aXX + sinU * aYX; - const double dirUY = cosU * aXY + sinU * aYY; - const double dirUZ = cosU * aXZ + sinU * aYZ; - - resX = sinAng * dirUX + cosAng * aZX; - resY = sinAng * dirUY + cosAng * aZY; - resZ = sinAng * dirUZ + cosAng * aZZ; - } - else - { - // D_{nu,1} = sin(Ang) * d^nu(DirU)/du^nu - double dirDnX, dirDnY, dirDnZ; - switch (aPhaseU) - { - case 0: - dirDnX = cosU * aXX + sinU * aYX; - dirDnY = cosU * aXY + sinU * aYY; - dirDnZ = cosU * aXZ + sinU * aYZ; - break; - case 1: - dirDnX = -sinU * aXX + cosU * aYX; - dirDnY = -sinU * aXY + cosU * aYY; - dirDnZ = -sinU * aXZ + cosU * aYZ; - break; - case 2: - dirDnX = -cosU * aXX - sinU * aYX; - dirDnY = -cosU * aXY - sinU * aYY; - dirDnZ = -cosU * aXZ - sinU * aYZ; - break; - case 3: - default: - dirDnX = sinU * aXX - cosU * aYX; - dirDnY = sinU * aXY - cosU * aYY; - dirDnZ = sinU * aXZ - cosU * aYZ; - break; - } - resX = sinAng * dirDnX; - resY = sinAng * dirDnY; - resZ = sinAng * dirDnZ; - } - - // Result is constant in V - const gp_Vec aVec(resX, resY, resZ); - for (int iV = 1; iV <= aNbV; ++iV) - { - aResult.SetValue(iU, iV, aVec); - } + const double aV = theVParams.Value(theVParams.Lower() + iV - 1); + aResult.SetValue(iU, iV, computeD0(aData, aUCtx, aV)); } } return aResult; } + +//================================================================================================== + +NCollection_Array2 GeomGridEval_Cone::EvaluateGridD1( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams) const +{ + if (myGeom.IsNull() || theUParams.IsEmpty() || theVParams.IsEmpty()) + { + return NCollection_Array2(); + } + + const Data aData = extractData(); + const int aNbU = theUParams.Length(); + const int aNbV = theVParams.Length(); + + NCollection_Array2 aResult(1, aNbU, 1, aNbV); + + for (int iU = 1; iU <= aNbU; ++iU) + { + const double aU = theUParams.Value(theUParams.Lower() + iU - 1); + const UContext aUCtx = computeUContext(aData, aU); + + for (int iV = 1; iV <= aNbV; ++iV) + { + const double aV = theVParams.Value(theVParams.Lower() + iV - 1); + aResult.SetValue(iU, iV, computeD1(aData, aUCtx, aV)); + } + } + + return aResult; +} + +//================================================================================================== + +NCollection_Array2 GeomGridEval_Cone::EvaluateGridD2( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams) const +{ + if (myGeom.IsNull() || theUParams.IsEmpty() || theVParams.IsEmpty()) + { + return NCollection_Array2(); + } + + const Data aData = extractData(); + const int aNbU = theUParams.Length(); + const int aNbV = theVParams.Length(); + + NCollection_Array2 aResult(1, aNbU, 1, aNbV); + + for (int iU = 1; iU <= aNbU; ++iU) + { + const double aU = theUParams.Value(theUParams.Lower() + iU - 1); + const UContext aUCtx = computeUContext(aData, aU); + + for (int iV = 1; iV <= aNbV; ++iV) + { + const double aV = theVParams.Value(theVParams.Lower() + iV - 1); + aResult.SetValue(iU, iV, computeD2(aData, aUCtx, aV)); + } + } + + return aResult; +} + +//================================================================================================== + +NCollection_Array2 GeomGridEval_Cone::EvaluateGridD3( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams) const +{ + if (myGeom.IsNull() || theUParams.IsEmpty() || theVParams.IsEmpty()) + { + return NCollection_Array2(); + } + + const Data aData = extractData(); + const int aNbU = theUParams.Length(); + const int aNbV = theVParams.Length(); + + NCollection_Array2 aResult(1, aNbU, 1, aNbV); + + for (int iU = 1; iU <= aNbU; ++iU) + { + const double aU = theUParams.Value(theUParams.Lower() + iU - 1); + const UContext aUCtx = computeUContext(aData, aU); + + for (int iV = 1; iV <= aNbV; ++iV) + { + const double aV = theVParams.Value(theVParams.Lower() + iV - 1); + aResult.SetValue(iU, iV, computeD3(aData, aUCtx, aV)); + } + } + + return aResult; +} + +//================================================================================================== + +NCollection_Array2 GeomGridEval_Cone::EvaluateGridDN(const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams, + int theNU, + int theNV) const +{ + if (myGeom.IsNull() || theUParams.IsEmpty() || theVParams.IsEmpty() || theNU < 0 || theNV < 0 + || (theNU + theNV) < 1) + { + return NCollection_Array2(); + } + + const Data aData = extractData(); + const int aNbU = theUParams.Length(); + const int aNbV = theVParams.Length(); + + NCollection_Array2 aResult(1, aNbU, 1, aNbV); + + for (int iU = 1; iU <= aNbU; ++iU) + { + const double aU = theUParams.Value(theUParams.Lower() + iU - 1); + const UContext aUCtx = computeUContext(aData, aU); + + for (int iV = 1; iV <= aNbV; ++iV) + { + const double aV = theVParams.Value(theVParams.Lower() + iV - 1); + aResult.SetValue(iU, iV, computeDN(aData, aUCtx, aV, theNU, theNV)); + } + } + + return aResult; +} + +//================================================================================================== + +NCollection_Array1 GeomGridEval_Cone::EvaluatePoints( + const NCollection_Array1& theUVPairs) const +{ + if (myGeom.IsNull() || theUVPairs.IsEmpty()) + { + return NCollection_Array1(); + } + + const Data aData = extractData(); + const int aNb = theUVPairs.Length(); + NCollection_Array1 aResult(1, aNb); + + for (int i = 1; i <= aNb; ++i) + { + const gp_Pnt2d& aUV = theUVPairs.Value(theUVPairs.Lower() + i - 1); + const UContext aUCtx = computeUContext(aData, aUV.X()); + aResult.SetValue(i, computeD0(aData, aUCtx, aUV.Y())); + } + + return aResult; +} + +//================================================================================================== + +NCollection_Array1 GeomGridEval_Cone::EvaluatePointsD1( + const NCollection_Array1& theUVPairs) const +{ + if (myGeom.IsNull() || theUVPairs.IsEmpty()) + { + return NCollection_Array1(); + } + + const Data aData = extractData(); + const int aNb = theUVPairs.Length(); + NCollection_Array1 aResult(1, aNb); + + for (int i = 1; i <= aNb; ++i) + { + const gp_Pnt2d& aUV = theUVPairs.Value(theUVPairs.Lower() + i - 1); + const UContext aUCtx = computeUContext(aData, aUV.X()); + aResult.SetValue(i, computeD1(aData, aUCtx, aUV.Y())); + } + + return aResult; +} + +//================================================================================================== + +NCollection_Array1 GeomGridEval_Cone::EvaluatePointsD2( + const NCollection_Array1& theUVPairs) const +{ + if (myGeom.IsNull() || theUVPairs.IsEmpty()) + { + return NCollection_Array1(); + } + + const Data aData = extractData(); + const int aNb = theUVPairs.Length(); + NCollection_Array1 aResult(1, aNb); + + for (int i = 1; i <= aNb; ++i) + { + const gp_Pnt2d& aUV = theUVPairs.Value(theUVPairs.Lower() + i - 1); + const UContext aUCtx = computeUContext(aData, aUV.X()); + aResult.SetValue(i, computeD2(aData, aUCtx, aUV.Y())); + } + + return aResult; +} + +//================================================================================================== + +NCollection_Array1 GeomGridEval_Cone::EvaluatePointsD3( + const NCollection_Array1& theUVPairs) const +{ + if (myGeom.IsNull() || theUVPairs.IsEmpty()) + { + return NCollection_Array1(); + } + + const Data aData = extractData(); + const int aNb = theUVPairs.Length(); + NCollection_Array1 aResult(1, aNb); + + for (int i = 1; i <= aNb; ++i) + { + const gp_Pnt2d& aUV = theUVPairs.Value(theUVPairs.Lower() + i - 1); + const UContext aUCtx = computeUContext(aData, aUV.X()); + aResult.SetValue(i, computeD3(aData, aUCtx, aUV.Y())); + } + + return aResult; +} + +//================================================================================================== + +NCollection_Array1 GeomGridEval_Cone::EvaluatePointsDN( + const NCollection_Array1& theUVPairs, + int theNU, + int theNV) const +{ + if (myGeom.IsNull() || theUVPairs.IsEmpty() || theNU < 0 || theNV < 0 || (theNU + theNV) < 1) + { + return NCollection_Array1(); + } + + const Data aData = extractData(); + const int aNb = theUVPairs.Length(); + NCollection_Array1 aResult(1, aNb); + + for (int i = 1; i <= aNb; ++i) + { + const gp_Pnt2d& aUV = theUVPairs.Value(theUVPairs.Lower() + i - 1); + const UContext aUCtx = computeUContext(aData, aUV.X()); + aResult.SetValue(i, computeDN(aData, aUCtx, aUV.Y(), theNU, theNV)); + } + + return aResult; +} diff --git a/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_Cone.hxx b/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_Cone.hxx index abd8b104a9..a002e4643f 100644 --- a/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_Cone.hxx +++ b/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_Cone.hxx @@ -16,6 +16,7 @@ #include #include +#include #include #include #include @@ -33,8 +34,8 @@ //! Usage: //! @code //! GeomGridEval_Cone anEvaluator(myGeomCone); -//! anEvaluator.SetUVParams(myUParams, myVParams); -//! NCollection_Array2 aGrid = anEvaluator.EvaluateGrid(); +//! NCollection_Array2 aGrid = anEvaluator.EvaluateGrid(myUParams, myVParams); +//! NCollection_Array1 aPoints = anEvaluator.EvaluatePoints(myUVPairs); //! @endcode class GeomGridEval_Cone { @@ -54,53 +55,135 @@ public: GeomGridEval_Cone(GeomGridEval_Cone&&) = delete; GeomGridEval_Cone& operator=(GeomGridEval_Cone&&) = delete; - //! Set UV parameters from two 1D arrays. - //! @param theUParams array of U parameter values (angle) - //! @param theVParams array of V parameter values (linear along ruling) - Standard_EXPORT void SetUVParams(const TColStd_Array1OfReal& theUParams, - const TColStd_Array1OfReal& theVParams); - //! Returns the geometry handle. const Handle(Geom_ConicalSurface)& Geometry() const { return myGeom; } - //! Returns number of U parameters. - int NbUParams() const { return myUParams.Size(); } + //! Evaluate grid points at Cartesian product of U and V parameters. + //! @param theUParams array of U parameter values (angle) + //! @param theVParams array of V parameter values (linear along ruling) + //! @return 2D array of evaluated points (1-based indexing) + Standard_EXPORT NCollection_Array2 EvaluateGrid( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams) const; - //! Returns number of V parameters. - int NbVParams() const { return myVParams.Size(); } + //! Evaluate grid points with first partial derivatives. + //! @param theUParams array of U parameter values (angle) + //! @param theVParams array of V parameter values (linear along ruling) + //! @return 2D array of SurfD1 (1-based indexing) + Standard_EXPORT NCollection_Array2 EvaluateGridD1( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams) const; - //! Evaluate all grid points. - //! @return 2D array of evaluated points (1-based indexing), - //! or empty array if geometry is null or no parameters set - Standard_EXPORT NCollection_Array2 EvaluateGrid() const; + //! Evaluate grid points with first and second partial derivatives. + //! @param theUParams array of U parameter values (angle) + //! @param theVParams array of V parameter values (linear along ruling) + //! @return 2D array of SurfD2 (1-based indexing) + Standard_EXPORT NCollection_Array2 EvaluateGridD2( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams) const; - //! Evaluate all grid points with first partial derivatives. - //! @return 2D array of SurfD1 (1-based indexing), - //! or empty array if geometry is null or no parameters set - Standard_EXPORT NCollection_Array2 EvaluateGridD1() const; - - //! Evaluate all grid points with first and second partial derivatives. - //! @return 2D array of SurfD2 (1-based indexing), - //! or empty array if geometry is null or no parameters set - Standard_EXPORT NCollection_Array2 EvaluateGridD2() const; - - //! Evaluate all grid points with derivatives up to third order. - //! @return 2D array of SurfD3 (1-based indexing), - //! or empty array if geometry is null or no parameters set - Standard_EXPORT NCollection_Array2 EvaluateGridD3() const; + //! Evaluate grid points with derivatives up to third order. + //! @param theUParams array of U parameter values (angle) + //! @param theVParams array of V parameter values (linear along ruling) + //! @return 2D array of SurfD3 (1-based indexing) + Standard_EXPORT NCollection_Array2 EvaluateGridD3( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams) const; //! Evaluate partial derivative d^(NU+NV)S/(dU^NU dV^NV) at all grid points. //! For orders 1-3, reuses EvaluateGridD1/D2/D3. //! For orders > 3, uses geometry DN method. + //! @param theUParams array of U parameter values (angle) + //! @param theVParams array of V parameter values (linear along ruling) //! @param theNU derivative order in U direction //! @param theNV derivative order in V direction //! @return 2D array of derivative vectors (1-based indexing) - Standard_EXPORT NCollection_Array2 EvaluateGridDN(int theNU, int theNV) const; + Standard_EXPORT NCollection_Array2 EvaluateGridDN(const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams, + int theNU, + int theNV) const; + + //! Evaluate points at arbitrary UV pairs. + //! @param theUVPairs array of UV coordinate pairs + //! @return 1D array of evaluated points (1-based indexing) + Standard_EXPORT NCollection_Array1 EvaluatePoints( + const NCollection_Array1& theUVPairs) const; + + //! Evaluate points with first partial derivatives. + //! @param theUVPairs array of UV coordinate pairs + //! @return 1D array of SurfD1 (1-based indexing) + Standard_EXPORT NCollection_Array1 EvaluatePointsD1( + const NCollection_Array1& theUVPairs) const; + + //! Evaluate points with first and second partial derivatives. + //! @param theUVPairs array of UV coordinate pairs + //! @return 1D array of SurfD2 (1-based indexing) + Standard_EXPORT NCollection_Array1 EvaluatePointsD2( + const NCollection_Array1& theUVPairs) const; + + //! Evaluate points with derivatives up to third order. + //! @param theUVPairs array of UV coordinate pairs + //! @return 1D array of SurfD3 (1-based indexing) + Standard_EXPORT NCollection_Array1 EvaluatePointsD3( + const NCollection_Array1& theUVPairs) const; + + //! Evaluate partial derivative at all UV pairs. + //! @param theUVPairs array of UV coordinate pairs + //! @param theNU derivative order in U direction + //! @param theNV derivative order in V direction + //! @return 1D array of derivative vectors (1-based indexing) + Standard_EXPORT NCollection_Array1 EvaluatePointsDN( + const NCollection_Array1& theUVPairs, + int theNU, + int theNV) const; private: + //! Pre-extracted cone data for efficient evaluation. + struct Data + { + double CX, CY, CZ; //!< Center coordinates + double XX, XY, XZ; //!< XDir coordinates + double YX, YY, YZ; //!< YDir coordinates + double ZX, ZY, ZZ; //!< ZDir coordinates + double RefRadius; //!< Reference radius + double SinAng; //!< sin(SemiAngle) + double CosAng; //!< cos(SemiAngle) + }; + + //! Pre-computed U-dependent values for optimized grid evaluation. + struct UContext + { + double cosU, sinU; + double dirUX, dirUY, dirUZ; //!< DirU = cosU*XDir + sinU*YDir + double dDirUX, dDirUY, dDirUZ; //!< DerivDirU = -sinU*XDir + cosU*YDir + }; + + //! Extract cone data for evaluation. + Data extractData() const; + + //! Pre-compute U-dependent values. + static UContext computeUContext(const Data& theData, double theU); + + //! Compute point with pre-computed U context. + static gp_Pnt computeD0(const Data& theData, const UContext& theUCtx, double theV); + + //! Compute point with D1 with pre-computed U context. + static GeomGridEval::SurfD1 computeD1(const Data& theData, const UContext& theUCtx, double theV); + + //! Compute point with D2 with pre-computed U context. + static GeomGridEval::SurfD2 computeD2(const Data& theData, const UContext& theUCtx, double theV); + + //! Compute point with D3 with pre-computed U context. + static GeomGridEval::SurfD3 computeD3(const Data& theData, const UContext& theUCtx, double theV); + + //! Compute DN with pre-computed U context. + static gp_Vec computeDN(const Data& theData, + const UContext& theUCtx, + double theV, + int theNU, + int theNV); + Handle(Geom_ConicalSurface) myGeom; - NCollection_Array1 myUParams; - NCollection_Array1 myVParams; }; #endif // _GeomGridEval_Cone_HeaderFile diff --git a/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_Curve.cxx b/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_Curve.cxx index c16eb3591f..31ec554866 100644 --- a/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_Curve.cxx +++ b/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_Curve.cxx @@ -123,21 +123,6 @@ void GeomGridEval_Curve::Initialize(const Handle(Geom_Curve)& theCurve) //================================================================================================== -void GeomGridEval_Curve::SetParams(const TColStd_Array1OfReal& theParams) -{ - std::visit( - [&theParams](auto& theEval) { - using T = std::decay_t; - if constexpr (!std::is_same_v) - { - theEval.SetParams(theParams); - } - }, - myEvaluator); -} - -//================================================================================================== - bool GeomGridEval_Curve::IsInitialized() const { return !std::holds_alternative(myEvaluator); @@ -145,29 +130,11 @@ bool GeomGridEval_Curve::IsInitialized() const //================================================================================================== -int GeomGridEval_Curve::NbParams() const +NCollection_Array1 GeomGridEval_Curve::EvaluateGrid( + const TColStd_Array1OfReal& theParams) const { return std::visit( - [](const auto& theEval) -> int { - using T = std::decay_t; - if constexpr (std::is_same_v) - { - return 0; - } - else - { - return theEval.NbParams(); - } - }, - myEvaluator); -} - -//================================================================================================== - -NCollection_Array1 GeomGridEval_Curve::EvaluateGrid() const -{ - return std::visit( - [](const auto& theEval) -> NCollection_Array1 { + [&theParams](const auto& theEval) -> NCollection_Array1 { using T = std::decay_t; if constexpr (std::is_same_v) { @@ -175,7 +142,7 @@ NCollection_Array1 GeomGridEval_Curve::EvaluateGrid() const } else { - return theEval.EvaluateGrid(); + return theEval.EvaluateGrid(theParams); } }, myEvaluator); @@ -183,10 +150,11 @@ NCollection_Array1 GeomGridEval_Curve::EvaluateGrid() const //================================================================================================== -NCollection_Array1 GeomGridEval_Curve::EvaluateGridD1() const +NCollection_Array1 GeomGridEval_Curve::EvaluateGridD1( + const TColStd_Array1OfReal& theParams) const { return std::visit( - [](const auto& theEval) -> NCollection_Array1 { + [&theParams](const auto& theEval) -> NCollection_Array1 { using T = std::decay_t; if constexpr (std::is_same_v) { @@ -194,7 +162,7 @@ NCollection_Array1 GeomGridEval_Curve::EvaluateGridD1() c } else { - return theEval.EvaluateGridD1(); + return theEval.EvaluateGridD1(theParams); } }, myEvaluator); @@ -202,10 +170,11 @@ NCollection_Array1 GeomGridEval_Curve::EvaluateGridD1() c //================================================================================================== -NCollection_Array1 GeomGridEval_Curve::EvaluateGridD2() const +NCollection_Array1 GeomGridEval_Curve::EvaluateGridD2( + const TColStd_Array1OfReal& theParams) const { return std::visit( - [](const auto& theEval) -> NCollection_Array1 { + [&theParams](const auto& theEval) -> NCollection_Array1 { using T = std::decay_t; if constexpr (std::is_same_v) { @@ -213,7 +182,7 @@ NCollection_Array1 GeomGridEval_Curve::EvaluateGridD2() c } else { - return theEval.EvaluateGridD2(); + return theEval.EvaluateGridD2(theParams); } }, myEvaluator); @@ -221,10 +190,11 @@ NCollection_Array1 GeomGridEval_Curve::EvaluateGridD2() c //================================================================================================== -NCollection_Array1 GeomGridEval_Curve::EvaluateGridD3() const +NCollection_Array1 GeomGridEval_Curve::EvaluateGridD3( + const TColStd_Array1OfReal& theParams) const { return std::visit( - [](const auto& theEval) -> NCollection_Array1 { + [&theParams](const auto& theEval) -> NCollection_Array1 { using T = std::decay_t; if constexpr (std::is_same_v) { @@ -232,7 +202,7 @@ NCollection_Array1 GeomGridEval_Curve::EvaluateGridD3() c } else { - return theEval.EvaluateGridD3(); + return theEval.EvaluateGridD3(theParams); } }, myEvaluator); @@ -240,10 +210,11 @@ NCollection_Array1 GeomGridEval_Curve::EvaluateGridD3() c //================================================================================================== -NCollection_Array1 GeomGridEval_Curve::EvaluateGridDN(int theN) const +NCollection_Array1 GeomGridEval_Curve::EvaluateGridDN(const TColStd_Array1OfReal& theParams, + int theN) const { return std::visit( - [theN](const auto& theEval) -> NCollection_Array1 { + [&theParams, theN](const auto& theEval) -> NCollection_Array1 { using T = std::decay_t; if constexpr (std::is_same_v) { @@ -251,7 +222,7 @@ NCollection_Array1 GeomGridEval_Curve::EvaluateGridDN(int theN) const } else { - return theEval.EvaluateGridDN(theN); + return theEval.EvaluateGridDN(theParams, theN); } }, myEvaluator); diff --git a/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_Curve.hxx b/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_Curve.hxx index 82a1a0d85d..adb0f25b8b 100644 --- a/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_Curve.hxx +++ b/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_Curve.hxx @@ -56,8 +56,7 @@ //! anEval.Initialize(myAdaptorCurve); //! // OR //! anEval.Initialize(myGeomCurve); -//! anEval.SetParams(myParams); -//! NCollection_Array1 aGrid = anEval.EvaluateGrid(); +//! NCollection_Array1 aGrid = anEval.EvaluateGrid(myParams); //! @endcode class GeomGridEval_Curve { @@ -101,36 +100,39 @@ public: //! @param theCurve geometry to evaluate Standard_EXPORT void Initialize(const Handle(Geom_Curve)& theCurve); - //! Set parameters for evaluation. - //! @param theParams array of parameter values (1-based) - Standard_EXPORT void SetParams(const TColStd_Array1OfReal& theParams); - //! Returns true if properly initialized. Standard_EXPORT bool IsInitialized() const; - //! Returns number of parameters set. - Standard_EXPORT int NbParams() const; - - //! Evaluate grid points at all set parameters. + //! Evaluate grid points at all parameters. + //! @param theParams array of parameter values //! @return array of 3D points (1-based indexing) - Standard_EXPORT NCollection_Array1 EvaluateGrid() const; + Standard_EXPORT NCollection_Array1 EvaluateGrid( + const TColStd_Array1OfReal& 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 EvaluateGridD1() const; + Standard_EXPORT NCollection_Array1 EvaluateGridD1( + const TColStd_Array1OfReal& 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 EvaluateGridD2() const; + Standard_EXPORT NCollection_Array1 EvaluateGridD2( + const TColStd_Array1OfReal& 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 EvaluateGridD3() const; + Standard_EXPORT NCollection_Array1 EvaluateGridD3( + const TColStd_Array1OfReal& 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 EvaluateGridDN(int theN) const; + Standard_EXPORT NCollection_Array1 EvaluateGridDN(const TColStd_Array1OfReal& theParams, + int theN) const; //! Returns the detected curve type. GeomAbs_CurveType GetType() const { return myCurveType; } diff --git a/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_Cylinder.cxx b/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_Cylinder.cxx index e14cb5351e..3bb949277b 100644 --- a/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_Cylinder.cxx +++ b/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_Cylinder.cxx @@ -19,337 +19,141 @@ //================================================================================================== -void GeomGridEval_Cylinder::SetUVParams(const TColStd_Array1OfReal& theUParams, - const TColStd_Array1OfReal& theVParams) +GeomGridEval_Cylinder::Data GeomGridEval_Cylinder::extractData() const { - const int aNbU = theUParams.Size(); - const int aNbV = theVParams.Size(); - - myUParams.Resize(1, aNbU, false); - for (int i = 1; i <= aNbU; ++i) - { - myUParams.SetValue(i, theUParams.Value(theUParams.Lower() + i - 1)); - } - - myVParams.Resize(1, aNbV, false); - for (int j = 1; j <= aNbV; ++j) - { - myVParams.SetValue(j, theVParams.Value(theVParams.Lower() + j - 1)); - } -} - -//================================================================================================== - -NCollection_Array2 GeomGridEval_Cylinder::EvaluateGrid() const -{ - if (myGeom.IsNull() || myUParams.IsEmpty() || myVParams.IsEmpty()) - { - return NCollection_Array2(); - } - - const int aNbU = myUParams.Size(); - const int aNbV = myVParams.Size(); - - NCollection_Array2 aResult(1, aNbU, 1, aNbV); - - // Extract cylinder data const gp_Cylinder& aCyl = myGeom->Cylinder(); const gp_Pnt& aCenter = aCyl.Location(); const gp_Dir& aXDir = aCyl.Position().XDirection(); const gp_Dir& aYDir = aCyl.Position().YDirection(); const gp_Dir& aZDir = aCyl.Position().Direction(); - const double aRadius = aCyl.Radius(); - // Pre-extract coordinates - const double aCX = aCenter.X(); - const double aCY = aCenter.Y(); - const double aCZ = aCenter.Z(); - const double aXX = aXDir.X(); - const double aXY = aXDir.Y(); - const double aXZ = aXDir.Z(); - const double aYX = aYDir.X(); - const double aYY = aYDir.Y(); - const double aYZ = aYDir.Z(); - const double aZX = aZDir.X(); - const double aZY = aZDir.Y(); - const double aZZ = aZDir.Z(); - - for (int iU = 1; iU <= aNbU; ++iU) - { - const double u = myUParams.Value(iU); - const double cosU = std::cos(u); - const double sinU = std::sin(u); - - // Pre-calculate U-dependent components - // Base circle point (relative to center) - const double aCircleX = aRadius * (cosU * aXX + sinU * aYX); - const double aCircleY = aRadius * (cosU * aXY + sinU * aYY); - const double aCircleZ = aRadius * (cosU * aXZ + sinU * aYZ); - - for (int iV = 1; iV <= aNbV; ++iV) - { - const double v = myVParams.Value(iV); - - // P = Center + (Circle Point) + v * ZDir - aResult.SetValue( - iU, - iV, - gp_Pnt(aCX + aCircleX + v * aZX, aCY + aCircleY + v * aZY, aCZ + aCircleZ + v * aZZ)); - } - } - return aResult; + return {aCenter.X(), + aCenter.Y(), + aCenter.Z(), + aXDir.X(), + aXDir.Y(), + aXDir.Z(), + aYDir.X(), + aYDir.Y(), + aYDir.Z(), + aZDir.X(), + aZDir.Y(), + aZDir.Z(), + aCyl.Radius()}; } //================================================================================================== -NCollection_Array2 GeomGridEval_Cylinder::EvaluateGridD1() const +GeomGridEval_Cylinder::UContext GeomGridEval_Cylinder::computeUContext(const Data& theData, + double theU) { - if (myGeom.IsNull() || myUParams.IsEmpty() || myVParams.IsEmpty()) - { - return NCollection_Array2(); - } + const double cosU = std::cos(theU); + const double sinU = std::sin(theU); - const int aNbU = myUParams.Size(); - const int aNbV = myVParams.Size(); - - NCollection_Array2 aResult(1, aNbU, 1, aNbV); - - const gp_Cylinder& aCyl = myGeom->Cylinder(); - const gp_Pnt& aCenter = aCyl.Location(); - const gp_Dir& aXDir = aCyl.Position().XDirection(); - const gp_Dir& aYDir = aCyl.Position().YDirection(); - const gp_Dir& aZDir = aCyl.Position().Direction(); - const double aRadius = aCyl.Radius(); - - const double aCX = aCenter.X(); - const double aCY = aCenter.Y(); - const double aCZ = aCenter.Z(); - const double aXX = aXDir.X(); - const double aXY = aXDir.Y(); - const double aXZ = aXDir.Z(); - const double aYX = aYDir.X(); - const double aYY = aYDir.Y(); - const double aYZ = aYDir.Z(); - const double aZX = aZDir.X(); - const double aZY = aZDir.Y(); - const double aZZ = aZDir.Z(); - - for (int iU = 1; iU <= aNbU; ++iU) - { - const double u = myUParams.Value(iU); - const double cosU = std::cos(u); - const double sinU = std::sin(u); - - // Pre-calculate U-dependent components - // P relative to center (without V component) - const double aCircleX = aRadius * (cosU * aXX + sinU * aYX); - const double aCircleY = aRadius * (cosU * aXY + sinU * aYY); - const double aCircleZ = aRadius * (cosU * aXZ + sinU * aYZ); - - // D1U = R * (-sinU * XDir + cosU * YDir) - const double dU1 = aRadius * (-sinU * aXX + cosU * aYX); - const double dU2 = aRadius * (-sinU * aXY + cosU * aYY); - const double dU3 = aRadius * (-sinU * aXZ + cosU * aYZ); - - // D1V = ZDir (constant) - const double dV1 = aZX; - const double dV2 = aZY; - const double dV3 = aZZ; - - for (int iV = 1; iV <= aNbV; ++iV) - { - const double v = myVParams.Value(iV); - - aResult.ChangeValue(iU, iV) = { - gp_Pnt(aCX + aCircleX + v * aZX, aCY + aCircleY + v * aZY, aCZ + aCircleZ + v * aZZ), - gp_Vec(dU1, dU2, dU3), - gp_Vec(dV1, dV2, dV3)}; - } - } - return aResult; + // DirU = cosU*XDir + sinU*YDir (circle point direction at angle U) + // dDirU = -sinU*XDir + cosU*YDir (derivative of DirU w.r.t. U) + return {cosU, + sinU, + cosU * theData.XX + sinU * theData.YX, + cosU * theData.XY + sinU * theData.YY, + cosU * theData.XZ + sinU * theData.YZ, + -sinU * theData.XX + cosU * theData.YX, + -sinU * theData.XY + cosU * theData.YY, + -sinU * theData.XZ + cosU * theData.YZ}; } //================================================================================================== -NCollection_Array2 GeomGridEval_Cylinder::EvaluateGridD2() const +gp_Pnt GeomGridEval_Cylinder::computeD0(const Data& theData, const UContext& theUCtx, double theV) { - if (myGeom.IsNull() || myUParams.IsEmpty() || myVParams.IsEmpty()) - { - return NCollection_Array2(); - } - - const int aNbU = myUParams.Size(); - const int aNbV = myVParams.Size(); - - NCollection_Array2 aResult(1, aNbU, 1, aNbV); - - const gp_Cylinder& aCyl = myGeom->Cylinder(); - const gp_Pnt& aCenter = aCyl.Location(); - const gp_Dir& aXDir = aCyl.Position().XDirection(); - const gp_Dir& aYDir = aCyl.Position().YDirection(); - const gp_Dir& aZDir = aCyl.Position().Direction(); - const double aRadius = aCyl.Radius(); - - const double aCX = aCenter.X(); - const double aCY = aCenter.Y(); - const double aCZ = aCenter.Z(); - const double aXX = aXDir.X(); - const double aXY = aXDir.Y(); - const double aXZ = aXDir.Z(); - const double aYX = aYDir.X(); - const double aYY = aYDir.Y(); - const double aYZ = aYDir.Z(); - const double aZX = aZDir.X(); - const double aZY = aZDir.Y(); - const double aZZ = aZDir.Z(); - - for (int iU = 1; iU <= aNbU; ++iU) - { - const double u = myUParams.Value(iU); - const double cosU = std::cos(u); - const double sinU = std::sin(u); - - // Pre-calculate U-dependent components - const double aCircleX = aRadius * (cosU * aXX + sinU * aYX); - const double aCircleY = aRadius * (cosU * aXY + sinU * aYY); - const double aCircleZ = aRadius * (cosU * aXZ + sinU * aYZ); - - // D1U = R * (-sinU * XDir + cosU * YDir) - const double dU1 = aRadius * (-sinU * aXX + cosU * aYX); - const double dU2 = aRadius * (-sinU * aXY + cosU * aYY); - const double dU3 = aRadius * (-sinU * aXZ + cosU * aYZ); - - // D1V = ZDir - const double dV1 = aZX; - const double dV2 = aZY; - const double dV3 = aZZ; - - // D2U = R * (-cosU * XDir - sinU * YDir) = - (Circle point relative to center) - const double d2U1 = -aCircleX; - const double d2U2 = -aCircleY; - const double d2U3 = -aCircleZ; - - // D2V = 0, D2UV = 0 - - for (int iV = 1; iV <= aNbV; ++iV) - { - const double v = myVParams.Value(iV); - - aResult.ChangeValue(iU, iV) = { - gp_Pnt(aCX + aCircleX + v * aZX, aCY + aCircleY + v * aZY, aCZ + aCircleZ + v * aZZ), - gp_Vec(dU1, dU2, dU3), - gp_Vec(dV1, dV2, dV3), - gp_Vec(d2U1, d2U2, d2U3), - gp_Vec(0.0, 0.0, 0.0), // D2V - gp_Vec(0.0, 0.0, 0.0) // D2UV - }; - } - } - return aResult; + // P = Center + R * DirU + v * ZDir + return gp_Pnt(theData.CX + theData.Radius * theUCtx.dirUX + theV * theData.ZX, + theData.CY + theData.Radius * theUCtx.dirUY + theV * theData.ZY, + theData.CZ + theData.Radius * theUCtx.dirUZ + theV * theData.ZZ); } //================================================================================================== -NCollection_Array2 GeomGridEval_Cylinder::EvaluateGridD3() const +GeomGridEval::SurfD1 GeomGridEval_Cylinder::computeD1(const Data& theData, + const UContext& theUCtx, + double theV) { - if (myGeom.IsNull() || myUParams.IsEmpty() || myVParams.IsEmpty()) - { - return NCollection_Array2(); - } + // D1U = R * dDirU + // D1V = ZDir + return {gp_Pnt(theData.CX + theData.Radius * theUCtx.dirUX + theV * theData.ZX, + theData.CY + theData.Radius * theUCtx.dirUY + theV * theData.ZY, + theData.CZ + theData.Radius * theUCtx.dirUZ + theV * theData.ZZ), + gp_Vec(theData.Radius * theUCtx.dDirUX, + theData.Radius * theUCtx.dDirUY, + theData.Radius * theUCtx.dDirUZ), + gp_Vec(theData.ZX, theData.ZY, theData.ZZ)}; +} - const int aNbU = myUParams.Size(); - const int aNbV = myVParams.Size(); - - NCollection_Array2 aResult(1, aNbU, 1, aNbV); - - const gp_Cylinder& aCyl = myGeom->Cylinder(); - const gp_Pnt& aCenter = aCyl.Location(); - const gp_Dir& aXDir = aCyl.Position().XDirection(); - const gp_Dir& aYDir = aCyl.Position().YDirection(); - const gp_Dir& aZDir = aCyl.Position().Direction(); - const double aRadius = aCyl.Radius(); - - const double aCX = aCenter.X(); - const double aCY = aCenter.Y(); - const double aCZ = aCenter.Z(); - const double aXX = aXDir.X(); - const double aXY = aXDir.Y(); - const double aXZ = aXDir.Z(); - const double aYX = aYDir.X(); - const double aYY = aYDir.Y(); - const double aYZ = aYDir.Z(); - const double aZX = aZDir.X(); - const double aZY = aZDir.Y(); - const double aZZ = aZDir.Z(); +//================================================================================================== +GeomGridEval::SurfD2 GeomGridEval_Cylinder::computeD2(const Data& theData, + const UContext& theUCtx, + double theV) +{ + // D2U = R * (-DirU) = -R * DirU + // D2V = 0 + // D2UV = 0 const gp_Vec aZero(0.0, 0.0, 0.0); - for (int iU = 1; iU <= aNbU; ++iU) - { - const double u = myUParams.Value(iU); - const double cosU = std::cos(u); - const double sinU = std::sin(u); - - // A1 = R * cosU, A2 = R * sinU - const double A1 = aRadius * cosU; - const double A2 = aRadius * sinU; - - // Som1 = A1*X + A2*Y (circle point) - const double aCircleX = A1 * aXX + A2 * aYX; - const double aCircleY = A1 * aXY + A2 * aYY; - const double aCircleZ = A1 * aXZ + A2 * aYZ; - - // D1U = R * (-sinU * X + cosU * Y) - const double dU1 = aRadius * (-sinU * aXX + cosU * aYX); - const double dU2 = aRadius * (-sinU * aXY + cosU * aYY); - const double dU3 = aRadius * (-sinU * aXZ + cosU * aYZ); - - // D2U = -Som1 = - circle point - const double d2U1 = -aCircleX; - const double d2U2 = -aCircleY; - const double d2U3 = -aCircleZ; - - // D3U = -D1U (Vuuu = Dif1 where Dif1 = A2*X - A1*Y, which equals -D1U) - const double d3U1 = -dU1; - const double d3U2 = -dU2; - const double d3U3 = -dU3; - - for (int iV = 1; iV <= aNbV; ++iV) - { - const double v = myVParams.Value(iV); - - aResult.ChangeValue(iU, iV) = { - gp_Pnt(aCX + aCircleX + v * aZX, aCY + aCircleY + v * aZY, aCZ + aCircleZ + v * aZZ), - gp_Vec(dU1, dU2, dU3), - gp_Vec(aZX, aZY, aZZ), // D1V = ZDir - gp_Vec(d2U1, d2U2, d2U3), - aZero, // D2V = 0 - aZero, // D2UV = 0 - gp_Vec(d3U1, d3U2, d3U3), - aZero, // D3V = 0 - aZero, // D3UUV = 0 - aZero // D3UVV = 0 - }; - } - } - return aResult; + return {gp_Pnt(theData.CX + theData.Radius * theUCtx.dirUX + theV * theData.ZX, + theData.CY + theData.Radius * theUCtx.dirUY + theV * theData.ZY, + theData.CZ + theData.Radius * theUCtx.dirUZ + theV * theData.ZZ), + gp_Vec(theData.Radius * theUCtx.dDirUX, + theData.Radius * theUCtx.dDirUY, + theData.Radius * theUCtx.dDirUZ), + gp_Vec(theData.ZX, theData.ZY, theData.ZZ), + gp_Vec(-theData.Radius * theUCtx.dirUX, + -theData.Radius * theUCtx.dirUY, + -theData.Radius * theUCtx.dirUZ), + aZero, + aZero}; } //================================================================================================== -NCollection_Array2 GeomGridEval_Cylinder::EvaluateGridDN(int theNU, int theNV) const +GeomGridEval::SurfD3 GeomGridEval_Cylinder::computeD3(const Data& theData, + const UContext& theUCtx, + double theV) { - if (myGeom.IsNull() || myUParams.IsEmpty() || myVParams.IsEmpty() || theNU < 0 || theNV < 0 - || (theNU + theNV) < 1) - { - return NCollection_Array2(); - } + // D3U = R * (-dDirU) = -D1U + // D3V = 0 + // D3UUV = 0 + // D3UVV = 0 + const gp_Vec aZero(0.0, 0.0, 0.0); - const int aNbU = myUParams.Size(); - const int aNbV = myVParams.Size(); + return {gp_Pnt(theData.CX + theData.Radius * theUCtx.dirUX + theV * theData.ZX, + theData.CY + theData.Radius * theUCtx.dirUY + theV * theData.ZY, + theData.CZ + theData.Radius * theUCtx.dirUZ + theV * theData.ZZ), + gp_Vec(theData.Radius * theUCtx.dDirUX, + theData.Radius * theUCtx.dDirUY, + theData.Radius * theUCtx.dDirUZ), + gp_Vec(theData.ZX, theData.ZY, theData.ZZ), + gp_Vec(-theData.Radius * theUCtx.dirUX, + -theData.Radius * theUCtx.dirUY, + -theData.Radius * theUCtx.dirUZ), + aZero, + aZero, + gp_Vec(-theData.Radius * theUCtx.dDirUX, + -theData.Radius * theUCtx.dDirUY, + -theData.Radius * theUCtx.dDirUZ), + aZero, + aZero, + aZero}; +} - NCollection_Array2 aResult(1, aNbU, 1, aNbV); +//================================================================================================== +gp_Vec GeomGridEval_Cylinder::computeDN(const Data& theData, + const UContext& theUCtx, + double /*theV*/, + int theNU, + int theNV) +{ // For cylinder P(u,v) = C + R*(cos(u)*X + sin(u)*Y) + v*Z: // - V derivatives: only D_{0,1} = Z is non-zero, all D_{nu,nv} = 0 for nv >= 2 // - Mixed derivatives D_{nu,1} = 0 for nu >= 1 (Z term has no U dependence) @@ -357,106 +161,336 @@ NCollection_Array2 GeomGridEval_Cylinder::EvaluateGridDN(int theNU, int if (theNV > 1) { - // All derivatives with NV >= 2 are zero (v is linear) - const gp_Vec aZero(0.0, 0.0, 0.0); - for (int iU = 1; iU <= aNbU; ++iU) - { - for (int iV = 1; iV <= aNbV; ++iV) - { - aResult.SetValue(iU, iV, aZero); - } - } - return aResult; + return gp_Vec(0.0, 0.0, 0.0); } if (theNV == 1) { if (theNU == 0) { - // D_{0,1} = Z (constant) - const gp_Dir& aZDir = myGeom->Cylinder().Position().Direction(); - const gp_Vec aD1V(aZDir.X(), aZDir.Y(), aZDir.Z()); - for (int iU = 1; iU <= aNbU; ++iU) - { - for (int iV = 1; iV <= aNbV; ++iV) - { - aResult.SetValue(iU, iV, aD1V); - } - } + return gp_Vec(theData.ZX, theData.ZY, theData.ZZ); } - else - { - // D_{nu,1} = 0 for nu >= 1 (mixed derivatives are zero) - const gp_Vec aZero(0.0, 0.0, 0.0); - for (int iU = 1; iU <= aNbU; ++iU) - { - for (int iV = 1; iV <= aNbV; ++iV) - { - aResult.SetValue(iU, iV, aZero); - } - } - } - return aResult; + return gp_Vec(0.0, 0.0, 0.0); } // Pure U derivatives (theNV == 0, theNU >= 1) - // Cyclic with period 4: - // Phase 0: cos*X + sin*Y, Phase 1: -sin*X + cos*Y - // Phase 2: -cos*X - sin*Y, Phase 3: sin*X - cos*Y - - const gp_Cylinder& aCyl = myGeom->Cylinder(); - const gp_Dir& aXDir = aCyl.Position().XDirection(); - const gp_Dir& aYDir = aCyl.Position().YDirection(); - const double aRadius = aCyl.Radius(); - - const double aXX = aXDir.X(); - const double aXY = aXDir.Y(); - const double aXZ = aXDir.Z(); - const double aYX = aYDir.X(); - const double aYY = aYDir.Y(); - const double aYZ = aYDir.Z(); - + // d^n/du^n of DirU cycles: DirU, dDirU, -DirU, -dDirU const int aPhase = theNU % 4; + double dirX, dirY, dirZ; + switch (aPhase) + { + case 0: + dirX = theUCtx.dirUX; + dirY = theUCtx.dirUY; + dirZ = theUCtx.dirUZ; + break; + case 1: + dirX = theUCtx.dDirUX; + dirY = theUCtx.dDirUY; + dirZ = theUCtx.dDirUZ; + break; + case 2: + dirX = -theUCtx.dirUX; + dirY = -theUCtx.dirUY; + dirZ = -theUCtx.dirUZ; + break; + case 3: + dirX = -theUCtx.dDirUX; + dirY = -theUCtx.dDirUY; + dirZ = -theUCtx.dDirUZ; + break; + default: + dirX = 0.0; + dirY = 0.0; + dirZ = 0.0; + break; + } + + return gp_Vec(theData.Radius * dirX, theData.Radius * dirY, theData.Radius * dirZ); +} + +//================================================================================================== + +NCollection_Array2 GeomGridEval_Cylinder::EvaluateGrid( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams) const +{ + if (myGeom.IsNull() || theUParams.IsEmpty() || theVParams.IsEmpty()) + { + return NCollection_Array2(); + } + + const Data aData = extractData(); + const int aNbU = theUParams.Length(); + const int aNbV = theVParams.Length(); + + NCollection_Array2 aResult(1, aNbU, 1, aNbV); + for (int iU = 1; iU <= aNbU; ++iU) { - const double u = myUParams.Value(iU); - const double cosU = std::cos(u); - const double sinU = std::sin(u); - - double aCoeffX, aCoeffY; - switch (aPhase) - { - case 0: - aCoeffX = cosU; - aCoeffY = sinU; - break; - case 1: - aCoeffX = -sinU; - aCoeffY = cosU; - break; - case 2: - aCoeffX = -cosU; - aCoeffY = -sinU; - break; - case 3: - aCoeffX = sinU; - aCoeffY = -cosU; - break; - default: - aCoeffX = 0.0; - aCoeffY = 0.0; - break; - } - - const gp_Vec aDerivative(aRadius * (aCoeffX * aXX + aCoeffY * aYX), - aRadius * (aCoeffX * aXY + aCoeffY * aYY), - aRadius * (aCoeffX * aXZ + aCoeffY * aYZ)); + const double aU = theUParams.Value(theUParams.Lower() + iU - 1); + const UContext aUCtx = computeUContext(aData, aU); for (int iV = 1; iV <= aNbV; ++iV) { - aResult.SetValue(iU, iV, aDerivative); + const double aV = theVParams.Value(theVParams.Lower() + iV - 1); + aResult.SetValue(iU, iV, computeD0(aData, aUCtx, aV)); } } + + return aResult; +} + +//================================================================================================== + +NCollection_Array2 GeomGridEval_Cylinder::EvaluateGridD1( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams) const +{ + if (myGeom.IsNull() || theUParams.IsEmpty() || theVParams.IsEmpty()) + { + return NCollection_Array2(); + } + + const Data aData = extractData(); + const int aNbU = theUParams.Length(); + const int aNbV = theVParams.Length(); + + NCollection_Array2 aResult(1, aNbU, 1, aNbV); + + for (int iU = 1; iU <= aNbU; ++iU) + { + const double aU = theUParams.Value(theUParams.Lower() + iU - 1); + const UContext aUCtx = computeUContext(aData, aU); + + for (int iV = 1; iV <= aNbV; ++iV) + { + const double aV = theVParams.Value(theVParams.Lower() + iV - 1); + aResult.SetValue(iU, iV, computeD1(aData, aUCtx, aV)); + } + } + + return aResult; +} + +//================================================================================================== + +NCollection_Array2 GeomGridEval_Cylinder::EvaluateGridD2( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams) const +{ + if (myGeom.IsNull() || theUParams.IsEmpty() || theVParams.IsEmpty()) + { + return NCollection_Array2(); + } + + const Data aData = extractData(); + const int aNbU = theUParams.Length(); + const int aNbV = theVParams.Length(); + + NCollection_Array2 aResult(1, aNbU, 1, aNbV); + + for (int iU = 1; iU <= aNbU; ++iU) + { + const double aU = theUParams.Value(theUParams.Lower() + iU - 1); + const UContext aUCtx = computeUContext(aData, aU); + + for (int iV = 1; iV <= aNbV; ++iV) + { + const double aV = theVParams.Value(theVParams.Lower() + iV - 1); + aResult.SetValue(iU, iV, computeD2(aData, aUCtx, aV)); + } + } + + return aResult; +} + +//================================================================================================== + +NCollection_Array2 GeomGridEval_Cylinder::EvaluateGridD3( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams) const +{ + if (myGeom.IsNull() || theUParams.IsEmpty() || theVParams.IsEmpty()) + { + return NCollection_Array2(); + } + + const Data aData = extractData(); + const int aNbU = theUParams.Length(); + const int aNbV = theVParams.Length(); + + NCollection_Array2 aResult(1, aNbU, 1, aNbV); + + for (int iU = 1; iU <= aNbU; ++iU) + { + const double aU = theUParams.Value(theUParams.Lower() + iU - 1); + const UContext aUCtx = computeUContext(aData, aU); + + for (int iV = 1; iV <= aNbV; ++iV) + { + const double aV = theVParams.Value(theVParams.Lower() + iV - 1); + aResult.SetValue(iU, iV, computeD3(aData, aUCtx, aV)); + } + } + + return aResult; +} + +//================================================================================================== + +NCollection_Array2 GeomGridEval_Cylinder::EvaluateGridDN( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams, + int theNU, + int theNV) const +{ + if (myGeom.IsNull() || theUParams.IsEmpty() || theVParams.IsEmpty() || theNU < 0 || theNV < 0 + || (theNU + theNV) < 1) + { + return NCollection_Array2(); + } + + const Data aData = extractData(); + const int aNbU = theUParams.Length(); + const int aNbV = theVParams.Length(); + + NCollection_Array2 aResult(1, aNbU, 1, aNbV); + + for (int iU = 1; iU <= aNbU; ++iU) + { + const double aU = theUParams.Value(theUParams.Lower() + iU - 1); + const UContext aUCtx = computeUContext(aData, aU); + + for (int iV = 1; iV <= aNbV; ++iV) + { + const double aV = theVParams.Value(theVParams.Lower() + iV - 1); + aResult.SetValue(iU, iV, computeDN(aData, aUCtx, aV, theNU, theNV)); + } + } + + return aResult; +} + +//================================================================================================== + +NCollection_Array1 GeomGridEval_Cylinder::EvaluatePoints( + const NCollection_Array1& theUVPairs) const +{ + if (myGeom.IsNull() || theUVPairs.IsEmpty()) + { + return NCollection_Array1(); + } + + const Data aData = extractData(); + const int aNb = theUVPairs.Length(); + NCollection_Array1 aResult(1, aNb); + + for (int i = 1; i <= aNb; ++i) + { + const gp_Pnt2d& aUV = theUVPairs.Value(theUVPairs.Lower() + i - 1); + const UContext aUCtx = computeUContext(aData, aUV.X()); + aResult.SetValue(i, computeD0(aData, aUCtx, aUV.Y())); + } + + return aResult; +} + +//================================================================================================== + +NCollection_Array1 GeomGridEval_Cylinder::EvaluatePointsD1( + const NCollection_Array1& theUVPairs) const +{ + if (myGeom.IsNull() || theUVPairs.IsEmpty()) + { + return NCollection_Array1(); + } + + const Data aData = extractData(); + const int aNb = theUVPairs.Length(); + NCollection_Array1 aResult(1, aNb); + + for (int i = 1; i <= aNb; ++i) + { + const gp_Pnt2d& aUV = theUVPairs.Value(theUVPairs.Lower() + i - 1); + const UContext aUCtx = computeUContext(aData, aUV.X()); + aResult.SetValue(i, computeD1(aData, aUCtx, aUV.Y())); + } + + return aResult; +} + +//================================================================================================== + +NCollection_Array1 GeomGridEval_Cylinder::EvaluatePointsD2( + const NCollection_Array1& theUVPairs) const +{ + if (myGeom.IsNull() || theUVPairs.IsEmpty()) + { + return NCollection_Array1(); + } + + const Data aData = extractData(); + const int aNb = theUVPairs.Length(); + NCollection_Array1 aResult(1, aNb); + + for (int i = 1; i <= aNb; ++i) + { + const gp_Pnt2d& aUV = theUVPairs.Value(theUVPairs.Lower() + i - 1); + const UContext aUCtx = computeUContext(aData, aUV.X()); + aResult.SetValue(i, computeD2(aData, aUCtx, aUV.Y())); + } + + return aResult; +} + +//================================================================================================== + +NCollection_Array1 GeomGridEval_Cylinder::EvaluatePointsD3( + const NCollection_Array1& theUVPairs) const +{ + if (myGeom.IsNull() || theUVPairs.IsEmpty()) + { + return NCollection_Array1(); + } + + const Data aData = extractData(); + const int aNb = theUVPairs.Length(); + NCollection_Array1 aResult(1, aNb); + + for (int i = 1; i <= aNb; ++i) + { + const gp_Pnt2d& aUV = theUVPairs.Value(theUVPairs.Lower() + i - 1); + const UContext aUCtx = computeUContext(aData, aUV.X()); + aResult.SetValue(i, computeD3(aData, aUCtx, aUV.Y())); + } + + return aResult; +} + +//================================================================================================== + +NCollection_Array1 GeomGridEval_Cylinder::EvaluatePointsDN( + const NCollection_Array1& theUVPairs, + int theNU, + int theNV) const +{ + if (myGeom.IsNull() || theUVPairs.IsEmpty() || theNU < 0 || theNV < 0 || (theNU + theNV) < 1) + { + return NCollection_Array1(); + } + + const Data aData = extractData(); + const int aNb = theUVPairs.Length(); + NCollection_Array1 aResult(1, aNb); + + for (int i = 1; i <= aNb; ++i) + { + const gp_Pnt2d& aUV = theUVPairs.Value(theUVPairs.Lower() + i - 1); + const UContext aUCtx = computeUContext(aData, aUV.X()); + aResult.SetValue(i, computeDN(aData, aUCtx, aUV.Y(), theNU, theNV)); + } + return aResult; } diff --git a/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_Cylinder.hxx b/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_Cylinder.hxx index 1f51f95c38..2090affbd3 100644 --- a/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_Cylinder.hxx +++ b/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_Cylinder.hxx @@ -16,6 +16,7 @@ #include #include +#include #include #include #include @@ -32,8 +33,8 @@ //! Usage: //! @code //! GeomGridEval_Cylinder anEvaluator(myGeomCylinder); -//! anEvaluator.SetUVParams(myUParams, myVParams); -//! NCollection_Array2 aGrid = anEvaluator.EvaluateGrid(); +//! NCollection_Array2 aGrid = anEvaluator.EvaluateGrid(myUParams, myVParams); +//! NCollection_Array1 aPoints = anEvaluator.EvaluatePoints(myUVPairs); //! @endcode class GeomGridEval_Cylinder { @@ -53,55 +54,135 @@ public: GeomGridEval_Cylinder(GeomGridEval_Cylinder&&) = delete; GeomGridEval_Cylinder& operator=(GeomGridEval_Cylinder&&) = delete; - //! Set UV parameters from two 1D arrays. - //! @param theUParams array of U parameter values (angle) - //! @param theVParams array of V parameter values (height) - Standard_EXPORT void SetUVParams(const TColStd_Array1OfReal& theUParams, - const TColStd_Array1OfReal& theVParams); - //! Returns the geometry handle. const Handle(Geom_CylindricalSurface)& Geometry() const { return myGeom; } - //! Returns number of U parameters. - int NbUParams() const { return myUParams.Size(); } + //! Evaluate grid points at Cartesian product of U and V parameters. + //! @param theUParams array of U parameter values (angle) + //! @param theVParams array of V parameter values (height) + //! @return 2D array of evaluated points (1-based indexing) + Standard_EXPORT NCollection_Array2 EvaluateGrid( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams) const; - //! Returns number of V parameters. - int NbVParams() const { return myVParams.Size(); } + //! Evaluate grid points with first partial derivatives. + //! @param theUParams array of U parameter values (angle) + //! @param theVParams array of V parameter values (height) + //! @return 2D array of SurfD1 (1-based indexing) + Standard_EXPORT NCollection_Array2 EvaluateGridD1( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams) const; - //! Evaluate all grid points. - //! @return 2D array of evaluated points (1-based indexing), - //! or empty array if geometry is null or no parameters set - Standard_EXPORT NCollection_Array2 EvaluateGrid() const; + //! Evaluate grid points with first and second partial derivatives. + //! @param theUParams array of U parameter values (angle) + //! @param theVParams array of V parameter values (height) + //! @return 2D array of SurfD2 (1-based indexing) + Standard_EXPORT NCollection_Array2 EvaluateGridD2( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams) const; - //! Evaluate all grid points with first partial derivatives. - //! @return 2D array of SurfD1 (1-based indexing), - //! or empty array if geometry is null or no parameters set - Standard_EXPORT NCollection_Array2 EvaluateGridD1() const; - - //! Evaluate all grid points with first and second partial derivatives. - //! @return 2D array of SurfD2 (1-based indexing), - //! or empty array if geometry is null or no parameters set - Standard_EXPORT NCollection_Array2 EvaluateGridD2() const; - - //! Evaluate all grid points with derivatives up to third order. - //! @return 2D array of SurfD3 (1-based indexing), - //! or empty array if geometry is null or no parameters set - Standard_EXPORT NCollection_Array2 EvaluateGridD3() const; + //! Evaluate grid points with derivatives up to third order. + //! @param theUParams array of U parameter values (angle) + //! @param theVParams array of V parameter values (height) + //! @return 2D array of SurfD3 (1-based indexing) + Standard_EXPORT NCollection_Array2 EvaluateGridD3( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams) const; //! Evaluate partial derivative d^(NU+NV)S/(dU^NU dV^NV) at all grid points. //! For a cylinder: //! - U derivatives are cyclic (period 4): D_nU = R * (cyclic trig) //! - V derivatives: D1V = ZDir, higher = 0 //! - Mixed: D_{nu,nv} = 0 for nv > 1 + //! @param theUParams array of U parameter values (angle) + //! @param theVParams array of V parameter values (height) //! @param theNU derivative order in U direction //! @param theNV derivative order in V direction //! @return 2D array of derivative vectors (1-based indexing) - Standard_EXPORT NCollection_Array2 EvaluateGridDN(int theNU, int theNV) const; + Standard_EXPORT NCollection_Array2 EvaluateGridDN(const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams, + int theNU, + int theNV) const; + + //! Evaluate points at arbitrary UV pairs. + //! @param theUVPairs array of UV coordinate pairs + //! @return 1D array of evaluated points (1-based indexing) + Standard_EXPORT NCollection_Array1 EvaluatePoints( + const NCollection_Array1& theUVPairs) const; + + //! Evaluate points with first partial derivatives. + //! @param theUVPairs array of UV coordinate pairs + //! @return 1D array of SurfD1 (1-based indexing) + Standard_EXPORT NCollection_Array1 EvaluatePointsD1( + const NCollection_Array1& theUVPairs) const; + + //! Evaluate points with first and second partial derivatives. + //! @param theUVPairs array of UV coordinate pairs + //! @return 1D array of SurfD2 (1-based indexing) + Standard_EXPORT NCollection_Array1 EvaluatePointsD2( + const NCollection_Array1& theUVPairs) const; + + //! Evaluate points with derivatives up to third order. + //! @param theUVPairs array of UV coordinate pairs + //! @return 1D array of SurfD3 (1-based indexing) + Standard_EXPORT NCollection_Array1 EvaluatePointsD3( + const NCollection_Array1& theUVPairs) const; + + //! Evaluate partial derivative at all UV pairs. + //! @param theUVPairs array of UV coordinate pairs + //! @param theNU derivative order in U direction + //! @param theNV derivative order in V direction + //! @return 1D array of derivative vectors (1-based indexing) + Standard_EXPORT NCollection_Array1 EvaluatePointsDN( + const NCollection_Array1& theUVPairs, + int theNU, + int theNV) const; private: + //! Pre-extracted cylinder data for efficient evaluation. + struct Data + { + double CX, CY, CZ; //!< Center coordinates + double XX, XY, XZ; //!< XDir coordinates + double YX, YY, YZ; //!< YDir coordinates + double ZX, ZY, ZZ; //!< ZDir coordinates + double Radius; + }; + + //! Pre-computed U-dependent values for optimized grid evaluation. + struct UContext + { + double cosU, sinU; + double dirUX, dirUY, dirUZ; //!< DirU = cosU*XDir + sinU*YDir (circle point direction) + double dDirUX, dDirUY, dDirUZ; //!< DerivDirU = -sinU*XDir + cosU*YDir + }; + + //! Extract cylinder data for evaluation. + Data extractData() const; + + //! Pre-compute U-dependent values. + static UContext computeUContext(const Data& theData, double theU); + + //! Compute point with pre-computed U context. + static gp_Pnt computeD0(const Data& theData, const UContext& theUCtx, double theV); + + //! Compute point with D1 with pre-computed U context. + static GeomGridEval::SurfD1 computeD1(const Data& theData, const UContext& theUCtx, double theV); + + //! Compute point with D2 with pre-computed U context. + static GeomGridEval::SurfD2 computeD2(const Data& theData, const UContext& theUCtx, double theV); + + //! Compute point with D3 with pre-computed U context. + static GeomGridEval::SurfD3 computeD3(const Data& theData, const UContext& theUCtx, double theV); + + //! Compute DN with pre-computed U context. + static gp_Vec computeDN(const Data& theData, + const UContext& theUCtx, + double theV, + int theNU, + int theNV); + Handle(Geom_CylindricalSurface) myGeom; - NCollection_Array1 myUParams; - NCollection_Array1 myVParams; }; #endif // _GeomGridEval_Cylinder_HeaderFile diff --git a/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_Ellipse.cxx b/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_Ellipse.cxx index 60ec9407c9..4615661317 100644 --- a/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_Ellipse.cxx +++ b/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_Ellipse.cxx @@ -19,26 +19,15 @@ //================================================================================================== -void GeomGridEval_Ellipse::SetParams(const TColStd_Array1OfReal& theParams) +NCollection_Array1 GeomGridEval_Ellipse::EvaluateGrid( + const TColStd_Array1OfReal& theParams) const { - const int aNb = theParams.Size(); - myParams.Resize(1, aNb, false); - for (int i = 1; i <= aNb; ++i) - { - myParams.SetValue(i, theParams.Value(theParams.Lower() + i - 1)); - } -} - -//================================================================================================== - -NCollection_Array1 GeomGridEval_Ellipse::EvaluateGrid() const -{ - if (myGeom.IsNull() || myParams.IsEmpty()) + if (myGeom.IsNull() || theParams.IsEmpty()) { return NCollection_Array1(); } - const int aNb = myParams.Size(); + const int aNb = theParams.Size(); NCollection_Array1 aResult(1, aNb); const gp_Elips& anElips = myGeom->Elips(); @@ -58,14 +47,14 @@ NCollection_Array1 GeomGridEval_Ellipse::EvaluateGrid() const const double aYY = aYDir.Y(); const double aYZ = aYDir.Z(); - for (int i = 1; i <= aNb; ++i) + for (int i = theParams.Lower(); i <= theParams.Upper(); ++i) { - const double u = myParams.Value(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, + aResult.SetValue(i - theParams.Lower() + 1, gp_Pnt(aCX + aMajR * cosU * aXX + aMinR * sinU * aYX, aCY + aMajR * cosU * aXY + aMinR * sinU * aYY, aCZ + aMajR * cosU * aXZ + aMinR * sinU * aYZ)); @@ -75,14 +64,15 @@ NCollection_Array1 GeomGridEval_Ellipse::EvaluateGrid() const //================================================================================================== -NCollection_Array1 GeomGridEval_Ellipse::EvaluateGridD1() const +NCollection_Array1 GeomGridEval_Ellipse::EvaluateGridD1( + const TColStd_Array1OfReal& theParams) const { - if (myGeom.IsNull() || myParams.IsEmpty()) + if (myGeom.IsNull() || theParams.IsEmpty()) { return NCollection_Array1(); } - const int aNb = myParams.Size(); + const int aNb = theParams.Size(); NCollection_Array1 aResult(1, aNb); const gp_Elips& anElips = myGeom->Elips(); @@ -102,35 +92,37 @@ NCollection_Array1 GeomGridEval_Ellipse::EvaluateGridD1() const double aYY = aYDir.Y(); const double aYZ = aYDir.Z(); - for (int i = 1; i <= aNb; ++i) + for (int i = theParams.Lower(); i <= theParams.Upper(); ++i) { - const double u = myParams.Value(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) = {gp_Pnt(aCX + aMajR * cosU * aXX + aMinR * sinU * aYX, - aCY + aMajR * cosU * aXY + aMinR * sinU * aYY, - aCZ + aMajR * cosU * aXZ + aMinR * sinU * aYZ), - gp_Vec(-aMajR * sinU * aXX + aMinR * cosU * aYX, - -aMajR * sinU * aXY + aMinR * cosU * aYY, - -aMajR * sinU * aXZ + aMinR * cosU * aYZ)}; + aResult.ChangeValue(i - theParams.Lower() + + 1) = {gp_Pnt(aCX + aMajR * cosU * aXX + aMinR * sinU * aYX, + aCY + aMajR * cosU * aXY + aMinR * sinU * aYY, + aCZ + aMajR * cosU * aXZ + aMinR * sinU * aYZ), + gp_Vec(-aMajR * sinU * aXX + aMinR * cosU * aYX, + -aMajR * sinU * aXY + aMinR * cosU * aYY, + -aMajR * sinU * aXZ + aMinR * cosU * aYZ)}; } return aResult; } //================================================================================================== -NCollection_Array1 GeomGridEval_Ellipse::EvaluateGridD2() const +NCollection_Array1 GeomGridEval_Ellipse::EvaluateGridD2( + const TColStd_Array1OfReal& theParams) const { - if (myGeom.IsNull() || myParams.IsEmpty()) + if (myGeom.IsNull() || theParams.IsEmpty()) { return NCollection_Array1(); } - const int aNb = myParams.Size(); + const int aNb = theParams.Size(); NCollection_Array1 aResult(1, aNb); const gp_Elips& anElips = myGeom->Elips(); @@ -150,9 +142,9 @@ NCollection_Array1 GeomGridEval_Ellipse::EvaluateGridD2() const double aYY = aYDir.Y(); const double aYZ = aYDir.Z(); - for (int i = 1; i <= aNb; ++i) + for (int i = theParams.Lower(); i <= theParams.Upper(); ++i) { - const double u = myParams.Value(i); + const double u = theParams.Value(i); const double cosU = std::cos(u); const double sinU = std::sin(u); @@ -160,29 +152,31 @@ NCollection_Array1 GeomGridEval_Ellipse::EvaluateGridD2() // D1 = -MajorR * sin(u) * XDir + MinorR * cos(u) * YDir // D2 = -MajorR * cos(u) * XDir - MinorR * sin(u) * YDir = -(P - Center) - aResult.ChangeValue(i) = {gp_Pnt(aCX + aMajR * cosU * aXX + aMinR * sinU * aYX, - aCY + aMajR * cosU * aXY + aMinR * sinU * aYY, - aCZ + aMajR * cosU * aXZ + aMinR * sinU * aYZ), - gp_Vec(-aMajR * sinU * aXX + aMinR * cosU * aYX, - -aMajR * sinU * aXY + aMinR * cosU * aYY, - -aMajR * sinU * aXZ + aMinR * cosU * aYZ), - gp_Vec(-aMajR * cosU * aXX - aMinR * sinU * aYX, - -aMajR * cosU * aXY - aMinR * sinU * aYY, - -aMajR * cosU * aXZ - aMinR * sinU * aYZ)}; + aResult.ChangeValue(i - theParams.Lower() + + 1) = {gp_Pnt(aCX + aMajR * cosU * aXX + aMinR * sinU * aYX, + aCY + aMajR * cosU * aXY + aMinR * sinU * aYY, + aCZ + aMajR * cosU * aXZ + aMinR * sinU * aYZ), + gp_Vec(-aMajR * sinU * aXX + aMinR * cosU * aYX, + -aMajR * sinU * aXY + aMinR * cosU * aYY, + -aMajR * sinU * aXZ + aMinR * cosU * aYZ), + gp_Vec(-aMajR * cosU * aXX - aMinR * sinU * aYX, + -aMajR * cosU * aXY - aMinR * sinU * aYY, + -aMajR * cosU * aXZ - aMinR * sinU * aYZ)}; } return aResult; } //================================================================================================== -NCollection_Array1 GeomGridEval_Ellipse::EvaluateGridD3() const +NCollection_Array1 GeomGridEval_Ellipse::EvaluateGridD3( + const TColStd_Array1OfReal& theParams) const { - if (myGeom.IsNull() || myParams.IsEmpty()) + if (myGeom.IsNull() || theParams.IsEmpty()) { return NCollection_Array1(); } - const int aNb = myParams.Size(); + const int aNb = theParams.Size(); NCollection_Array1 aResult(1, aNb); const gp_Elips& anElips = myGeom->Elips(); @@ -202,9 +196,9 @@ NCollection_Array1 GeomGridEval_Ellipse::EvaluateGridD3() const double aYY = aYDir.Y(); const double aYZ = aYDir.Z(); - for (int i = 1; i <= aNb; ++i) + for (int i = theParams.Lower(); i <= theParams.Upper(); ++i) { - const double u = myParams.Value(i); + const double u = theParams.Value(i); const double cosU = std::cos(u); const double sinU = std::sin(u); @@ -213,32 +207,35 @@ NCollection_Array1 GeomGridEval_Ellipse::EvaluateGridD3() // D2 = -MajorR * cos(u) * XDir - MinorR * sin(u) * YDir // D3 = MajorR * sin(u) * XDir - MinorR * cos(u) * YDir = -D1 - aResult.ChangeValue(i) = {gp_Pnt(aCX + aMajR * cosU * aXX + aMinR * sinU * aYX, - aCY + aMajR * cosU * aXY + aMinR * sinU * aYY, - aCZ + aMajR * cosU * aXZ + aMinR * sinU * aYZ), - gp_Vec(-aMajR * sinU * aXX + aMinR * cosU * aYX, - -aMajR * sinU * aXY + aMinR * cosU * aYY, - -aMajR * sinU * aXZ + aMinR * cosU * aYZ), - gp_Vec(-aMajR * cosU * aXX - aMinR * sinU * aYX, - -aMajR * cosU * aXY - aMinR * sinU * aYY, - -aMajR * cosU * aXZ - aMinR * sinU * aYZ), - gp_Vec(aMajR * sinU * aXX - aMinR * cosU * aYX, - aMajR * sinU * aXY - aMinR * cosU * aYY, - aMajR * sinU * aXZ - aMinR * cosU * aYZ)}; + aResult.ChangeValue(i - theParams.Lower() + + 1) = {gp_Pnt(aCX + aMajR * cosU * aXX + aMinR * sinU * aYX, + aCY + aMajR * cosU * aXY + aMinR * sinU * aYY, + aCZ + aMajR * cosU * aXZ + aMinR * sinU * aYZ), + gp_Vec(-aMajR * sinU * aXX + aMinR * cosU * aYX, + -aMajR * sinU * aXY + aMinR * cosU * aYY, + -aMajR * sinU * aXZ + aMinR * cosU * aYZ), + gp_Vec(-aMajR * cosU * aXX - aMinR * sinU * aYX, + -aMajR * cosU * aXY - aMinR * sinU * aYY, + -aMajR * cosU * aXZ - aMinR * sinU * aYZ), + gp_Vec(aMajR * sinU * aXX - aMinR * cosU * aYX, + aMajR * sinU * aXY - aMinR * cosU * aYY, + aMajR * sinU * aXZ - aMinR * cosU * aYZ)}; } return aResult; } //================================================================================================== -NCollection_Array1 GeomGridEval_Ellipse::EvaluateGridDN(int theN) const +NCollection_Array1 GeomGridEval_Ellipse::EvaluateGridDN( + const TColStd_Array1OfReal& theParams, + int theN) const { - if (myGeom.IsNull() || myParams.IsEmpty() || theN < 1) + if (myGeom.IsNull() || theParams.IsEmpty() || theN < 1) { return NCollection_Array1(); } - const int aNb = myParams.Size(); + const int aNb = theParams.Size(); NCollection_Array1 aResult(1, aNb); const gp_Elips& anElips = myGeom->Elips(); @@ -261,9 +258,9 @@ NCollection_Array1 GeomGridEval_Ellipse::EvaluateGridDN(int theN) const // D4 = MajR * cos(u) * X + MinR * sin(u) * Y -> coefficients: (cos, sin) = D0 const int aPhase = (theN - 1) % 4; - for (int i = 1; i <= aNb; ++i) + for (int i = theParams.Lower(); i <= theParams.Upper(); ++i) { - const double u = myParams.Value(i); + const double u = theParams.Value(i); const double cosU = std::cos(u); const double sinU = std::sin(u); @@ -288,7 +285,7 @@ NCollection_Array1 GeomGridEval_Ellipse::EvaluateGridDN(int theN) const break; } - aResult.SetValue(i, + aResult.SetValue(i - theParams.Lower() + 1, gp_Vec(aMajR * aCoeffMajR * aXX + aMinR * aCoeffMinR * aYX, aMajR * aCoeffMajR * aXY + aMinR * aCoeffMinR * aYY, aMajR * aCoeffMajR * aXZ + aMinR * aCoeffMinR * aYZ)); diff --git a/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_Ellipse.hxx b/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_Ellipse.hxx index 28cd7b4441..96dbbdc088 100644 --- a/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_Ellipse.hxx +++ b/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_Ellipse.hxx @@ -29,8 +29,7 @@ //! Usage: //! @code //! GeomGridEval_Ellipse anEvaluator(myGeomEllipse); -//! anEvaluator.SetParams(myParams); -//! NCollection_Array1 aGrid = anEvaluator.EvaluateGrid(); +//! NCollection_Array1 aGrid = anEvaluator.EvaluateGrid(myParams); //! @endcode class GeomGridEval_Ellipse { @@ -50,32 +49,33 @@ public: GeomGridEval_Ellipse(GeomGridEval_Ellipse&&) = delete; GeomGridEval_Ellipse& operator=(GeomGridEval_Ellipse&&) = delete; - //! Set parameter values. - //! @param theParams array of parameter values - Standard_EXPORT void SetParams(const TColStd_Array1OfReal& theParams); - //! Returns the geometry handle. const Handle(Geom_Ellipse)& Geometry() const { return myGeom; } - //! Returns number of parameters. - int NbParams() const { return myParams.Size(); } - //! 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 set - Standard_EXPORT NCollection_Array1 EvaluateGrid() const; + //! or empty array if geometry is null or no parameters + Standard_EXPORT NCollection_Array1 EvaluateGrid( + const TColStd_Array1OfReal& 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 EvaluateGridD1() const; + Standard_EXPORT NCollection_Array1 EvaluateGridD1( + const TColStd_Array1OfReal& 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 EvaluateGridD2() const; + Standard_EXPORT NCollection_Array1 EvaluateGridD2( + const TColStd_Array1OfReal& 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 EvaluateGridD3() const; + Standard_EXPORT NCollection_Array1 EvaluateGridD3( + const TColStd_Array1OfReal& theParams) const; //! Evaluate Nth derivative at all grid points. //! Ellipse has cyclic derivatives with period 4: @@ -83,13 +83,14 @@ public: //! 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) - Standard_EXPORT NCollection_Array1 EvaluateGridDN(int theN) const; + Standard_EXPORT NCollection_Array1 EvaluateGridDN(const TColStd_Array1OfReal& theParams, + int theN) const; private: - Handle(Geom_Ellipse) myGeom; - NCollection_Array1 myParams; + Handle(Geom_Ellipse) myGeom; }; #endif // _GeomGridEval_Ellipse_HeaderFile diff --git a/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_Hyperbola.cxx b/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_Hyperbola.cxx index 81797d3d09..2524b08b60 100644 --- a/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_Hyperbola.cxx +++ b/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_Hyperbola.cxx @@ -19,26 +19,15 @@ //================================================================================================== -void GeomGridEval_Hyperbola::SetParams(const TColStd_Array1OfReal& theParams) +NCollection_Array1 GeomGridEval_Hyperbola::EvaluateGrid( + const TColStd_Array1OfReal& theParams) const { - const int aNb = theParams.Size(); - myParams.Resize(1, aNb, false); - for (int i = 1; i <= aNb; ++i) - { - myParams.SetValue(i, theParams.Value(theParams.Lower() + i - 1)); - } -} - -//================================================================================================== - -NCollection_Array1 GeomGridEval_Hyperbola::EvaluateGrid() const -{ - if (myGeom.IsNull() || myParams.IsEmpty()) + if (myGeom.IsNull() || theParams.IsEmpty()) { return NCollection_Array1(); } - const int aNb = myParams.Size(); + const int aNb = theParams.Size(); NCollection_Array1 aResult(1, aNb); const gp_Hypr& aHypr = myGeom->Hypr(); @@ -58,14 +47,14 @@ NCollection_Array1 GeomGridEval_Hyperbola::EvaluateGrid() const const double aYY = aYDir.Y(); const double aYZ = aYDir.Z(); - for (int i = 1; i <= aNb; ++i) + for (int i = theParams.Lower(); i <= theParams.Upper(); ++i) { - const double u = myParams.Value(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 - aResult.SetValue(i, + aResult.SetValue(i - theParams.Lower() + 1, gp_Pnt(aCX + aMajR * coshU * aXX + aMinR * sinhU * aYX, aCY + aMajR * coshU * aXY + aMinR * sinhU * aYY, aCZ + aMajR * coshU * aXZ + aMinR * sinhU * aYZ)); @@ -75,14 +64,15 @@ NCollection_Array1 GeomGridEval_Hyperbola::EvaluateGrid() const //================================================================================================== -NCollection_Array1 GeomGridEval_Hyperbola::EvaluateGridD1() const +NCollection_Array1 GeomGridEval_Hyperbola::EvaluateGridD1( + const TColStd_Array1OfReal& theParams) const { - if (myGeom.IsNull() || myParams.IsEmpty()) + if (myGeom.IsNull() || theParams.IsEmpty()) { return NCollection_Array1(); } - const int aNb = myParams.Size(); + const int aNb = theParams.Size(); NCollection_Array1 aResult(1, aNb); const gp_Hypr& aHypr = myGeom->Hypr(); @@ -102,35 +92,37 @@ NCollection_Array1 GeomGridEval_Hyperbola::EvaluateGridD1 const double aYY = aYDir.Y(); const double aYZ = aYDir.Z(); - for (int i = 1; i <= aNb; ++i) + for (int i = theParams.Lower(); i <= theParams.Upper(); ++i) { - const double u = myParams.Value(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) = {gp_Pnt(aCX + aMajR * coshU * aXX + aMinR * sinhU * aYX, - aCY + aMajR * coshU * aXY + aMinR * sinhU * aYY, - aCZ + aMajR * coshU * aXZ + aMinR * sinhU * aYZ), - gp_Vec(aMajR * sinhU * aXX + aMinR * coshU * aYX, - aMajR * sinhU * aXY + aMinR * coshU * aYY, - aMajR * sinhU * aXZ + aMinR * coshU * aYZ)}; + aResult.ChangeValue(i - theParams.Lower() + + 1) = {gp_Pnt(aCX + aMajR * coshU * aXX + aMinR * sinhU * aYX, + aCY + aMajR * coshU * aXY + aMinR * sinhU * aYY, + aCZ + aMajR * coshU * aXZ + aMinR * sinhU * aYZ), + gp_Vec(aMajR * sinhU * aXX + aMinR * coshU * aYX, + aMajR * sinhU * aXY + aMinR * coshU * aYY, + aMajR * sinhU * aXZ + aMinR * coshU * aYZ)}; } return aResult; } //================================================================================================== -NCollection_Array1 GeomGridEval_Hyperbola::EvaluateGridD2() const +NCollection_Array1 GeomGridEval_Hyperbola::EvaluateGridD2( + const TColStd_Array1OfReal& theParams) const { - if (myGeom.IsNull() || myParams.IsEmpty()) + if (myGeom.IsNull() || theParams.IsEmpty()) { return NCollection_Array1(); } - const int aNb = myParams.Size(); + const int aNb = theParams.Size(); NCollection_Array1 aResult(1, aNb); const gp_Hypr& aHypr = myGeom->Hypr(); @@ -150,9 +142,9 @@ NCollection_Array1 GeomGridEval_Hyperbola::EvaluateGridD2 const double aYY = aYDir.Y(); const double aYZ = aYDir.Z(); - for (int i = 1; i <= aNb; ++i) + for (int i = theParams.Lower(); i <= theParams.Upper(); ++i) { - const double u = myParams.Value(i); + const double u = theParams.Value(i); const double coshU = std::cosh(u); const double sinhU = std::sinh(u); @@ -160,29 +152,31 @@ NCollection_Array1 GeomGridEval_Hyperbola::EvaluateGridD2 // D1 = MajorR * sinh(u) * XDir + MinorR * cosh(u) * YDir // D2 = MajorR * cosh(u) * XDir + MinorR * sinh(u) * YDir = (P - Center) - aResult.ChangeValue(i) = {gp_Pnt(aCX + aMajR * coshU * aXX + aMinR * sinhU * aYX, - aCY + aMajR * coshU * aXY + aMinR * sinhU * aYY, - aCZ + aMajR * coshU * aXZ + aMinR * sinhU * aYZ), - gp_Vec(aMajR * sinhU * aXX + aMinR * coshU * aYX, - aMajR * sinhU * aXY + aMinR * coshU * aYY, - aMajR * sinhU * aXZ + aMinR * coshU * aYZ), - gp_Vec(aMajR * coshU * aXX + aMinR * sinhU * aYX, - aMajR * coshU * aXY + aMinR * sinhU * aYY, - aMajR * coshU * aXZ + aMinR * sinhU * aYZ)}; + aResult.ChangeValue(i - theParams.Lower() + + 1) = {gp_Pnt(aCX + aMajR * coshU * aXX + aMinR * sinhU * aYX, + aCY + aMajR * coshU * aXY + aMinR * sinhU * aYY, + aCZ + aMajR * coshU * aXZ + aMinR * sinhU * aYZ), + gp_Vec(aMajR * sinhU * aXX + aMinR * coshU * aYX, + aMajR * sinhU * aXY + aMinR * coshU * aYY, + aMajR * sinhU * aXZ + aMinR * coshU * aYZ), + gp_Vec(aMajR * coshU * aXX + aMinR * sinhU * aYX, + aMajR * coshU * aXY + aMinR * sinhU * aYY, + aMajR * coshU * aXZ + aMinR * sinhU * aYZ)}; } return aResult; } //================================================================================================== -NCollection_Array1 GeomGridEval_Hyperbola::EvaluateGridD3() const +NCollection_Array1 GeomGridEval_Hyperbola::EvaluateGridD3( + const TColStd_Array1OfReal& theParams) const { - if (myGeom.IsNull() || myParams.IsEmpty()) + if (myGeom.IsNull() || theParams.IsEmpty()) { return NCollection_Array1(); } - const int aNb = myParams.Size(); + const int aNb = theParams.Size(); NCollection_Array1 aResult(1, aNb); const gp_Hypr& aHypr = myGeom->Hypr(); @@ -202,9 +196,9 @@ NCollection_Array1 GeomGridEval_Hyperbola::EvaluateGridD3 const double aYY = aYDir.Y(); const double aYZ = aYDir.Z(); - for (int i = 1; i <= aNb; ++i) + for (int i = theParams.Lower(); i <= theParams.Upper(); ++i) { - const double u = myParams.Value(i); + const double u = theParams.Value(i); const double coshU = std::cosh(u); const double sinhU = std::sinh(u); @@ -213,32 +207,35 @@ NCollection_Array1 GeomGridEval_Hyperbola::EvaluateGridD3 // D2 = MajorR * cosh(u) * XDir + MinorR * sinh(u) * YDir // D3 = MajorR * sinh(u) * XDir + MinorR * cosh(u) * YDir = D1 - aResult.ChangeValue(i) = {gp_Pnt(aCX + aMajR * coshU * aXX + aMinR * sinhU * aYX, - aCY + aMajR * coshU * aXY + aMinR * sinhU * aYY, - aCZ + aMajR * coshU * aXZ + aMinR * sinhU * aYZ), - gp_Vec(aMajR * sinhU * aXX + aMinR * coshU * aYX, - aMajR * sinhU * aXY + aMinR * coshU * aYY, - aMajR * sinhU * aXZ + aMinR * coshU * aYZ), - gp_Vec(aMajR * coshU * aXX + aMinR * sinhU * aYX, - aMajR * coshU * aXY + aMinR * sinhU * aYY, - aMajR * coshU * aXZ + aMinR * sinhU * aYZ), - gp_Vec(aMajR * sinhU * aXX + aMinR * coshU * aYX, - aMajR * sinhU * aXY + aMinR * coshU * aYY, - aMajR * sinhU * aXZ + aMinR * coshU * aYZ)}; + aResult.ChangeValue(i - theParams.Lower() + + 1) = {gp_Pnt(aCX + aMajR * coshU * aXX + aMinR * sinhU * aYX, + aCY + aMajR * coshU * aXY + aMinR * sinhU * aYY, + aCZ + aMajR * coshU * aXZ + aMinR * sinhU * aYZ), + gp_Vec(aMajR * sinhU * aXX + aMinR * coshU * aYX, + aMajR * sinhU * aXY + aMinR * coshU * aYY, + aMajR * sinhU * aXZ + aMinR * coshU * aYZ), + gp_Vec(aMajR * coshU * aXX + aMinR * sinhU * aYX, + aMajR * coshU * aXY + aMinR * sinhU * aYY, + aMajR * coshU * aXZ + aMinR * sinhU * aYZ), + gp_Vec(aMajR * sinhU * aXX + aMinR * coshU * aYX, + aMajR * sinhU * aXY + aMinR * coshU * aYY, + aMajR * sinhU * aXZ + aMinR * coshU * aYZ)}; } return aResult; } //================================================================================================== -NCollection_Array1 GeomGridEval_Hyperbola::EvaluateGridDN(int theN) const +NCollection_Array1 GeomGridEval_Hyperbola::EvaluateGridDN( + const TColStd_Array1OfReal& theParams, + int theN) const { - if (myGeom.IsNull() || myParams.IsEmpty() || theN < 1) + if (myGeom.IsNull() || theParams.IsEmpty() || theN < 1) { return NCollection_Array1(); } - const int aNb = myParams.Size(); + const int aNb = theParams.Size(); NCollection_Array1 aResult(1, aNb); const gp_Hypr& aHypr = myGeom->Hypr(); @@ -260,16 +257,16 @@ NCollection_Array1 GeomGridEval_Hyperbola::EvaluateGridDN(int theN) cons // D2 = D0, D3 = D1, etc. const bool isOdd = (theN % 2) == 1; - for (int i = 1; i <= aNb; ++i) + for (int i = theParams.Lower(); i <= theParams.Upper(); ++i) { - const double u = myParams.Value(i); + const double u = theParams.Value(i); const double coshU = std::cosh(u); const double sinhU = std::sinh(u); if (isOdd) { // Odd derivatives (D1, D3, D5, ...): coefficients (sinh, cosh) - aResult.SetValue(i, + aResult.SetValue(i - theParams.Lower() + 1, gp_Vec(aMajR * sinhU * aXX + aMinR * coshU * aYX, aMajR * sinhU * aXY + aMinR * coshU * aYY, aMajR * sinhU * aXZ + aMinR * coshU * aYZ)); @@ -277,7 +274,7 @@ NCollection_Array1 GeomGridEval_Hyperbola::EvaluateGridDN(int theN) cons else { // Even derivatives (D2, D4, D6, ...): coefficients (cosh, sinh) = D0 - aResult.SetValue(i, + aResult.SetValue(i - theParams.Lower() + 1, gp_Vec(aMajR * coshU * aXX + aMinR * sinhU * aYX, aMajR * coshU * aXY + aMinR * sinhU * aYY, aMajR * coshU * aXZ + aMinR * sinhU * aYZ)); diff --git a/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_Hyperbola.hxx b/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_Hyperbola.hxx index 8f79cca502..dbfbfbf4a3 100644 --- a/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_Hyperbola.hxx +++ b/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_Hyperbola.hxx @@ -29,8 +29,7 @@ //! Usage: //! @code //! GeomGridEval_Hyperbola anEvaluator(myGeomHyperbola); -//! anEvaluator.SetParams(myParams); -//! NCollection_Array1 aGrid = anEvaluator.EvaluateGrid(); +//! NCollection_Array1 aGrid = anEvaluator.EvaluateGrid(myParams); //! @endcode class GeomGridEval_Hyperbola { @@ -50,45 +49,47 @@ public: GeomGridEval_Hyperbola(GeomGridEval_Hyperbola&&) = delete; GeomGridEval_Hyperbola& operator=(GeomGridEval_Hyperbola&&) = delete; - //! Set parameter values. - //! @param theParams array of parameter values - Standard_EXPORT void SetParams(const TColStd_Array1OfReal& theParams); - //! Returns the geometry handle. const Handle(Geom_Hyperbola)& Geometry() const { return myGeom; } - //! Returns number of parameters. - int NbParams() const { return myParams.Size(); } - //! 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 set - Standard_EXPORT NCollection_Array1 EvaluateGrid() const; + //! or empty array if geometry is null or no parameters + Standard_EXPORT NCollection_Array1 EvaluateGrid( + const TColStd_Array1OfReal& 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 EvaluateGridD1() const; + Standard_EXPORT NCollection_Array1 EvaluateGridD1( + const TColStd_Array1OfReal& 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 EvaluateGridD2() const; + Standard_EXPORT NCollection_Array1 EvaluateGridD2( + const TColStd_Array1OfReal& 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 EvaluateGridD3() const; + Standard_EXPORT NCollection_Array1 EvaluateGridD3( + const TColStd_Array1OfReal& 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 EvaluateGridDN(int theN) const; + Standard_EXPORT NCollection_Array1 EvaluateGridDN(const TColStd_Array1OfReal& theParams, + int theN) const; private: - Handle(Geom_Hyperbola) myGeom; - NCollection_Array1 myParams; + Handle(Geom_Hyperbola) myGeom; }; #endif // _GeomGridEval_Hyperbola_HeaderFile diff --git a/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_Line.hxx b/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_Line.hxx index d2e2a8071b..eba716c2ba 100644 --- a/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_Line.hxx +++ b/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_Line.hxx @@ -27,8 +27,7 @@ //! Usage: //! @code //! GeomGridEval_Line anEvaluator(myGeomLine); -//! anEvaluator.SetParams(myParams); -//! NCollection_Array1 aGrid = anEvaluator.EvaluateGrid(); +//! NCollection_Array1 aGrid = anEvaluator.EvaluateGrid(myParams); //! @endcode class GeomGridEval_Line { @@ -48,38 +47,21 @@ public: GeomGridEval_Line(GeomGridEval_Line&&) = delete; GeomGridEval_Line& operator=(GeomGridEval_Line&&) = delete; - //! Set parameters for grid evaluation (by const reference). - //! @param theParams array of parameter values - void SetParams(const TColStd_Array1OfReal& theParams) - { - myParams.Resize(theParams.Lower(), theParams.Upper(), false); - for (int i = theParams.Lower(); i <= theParams.Upper(); ++i) - { - myParams.SetValue(i, theParams.Value(i)); - } - } - - //! Set parameters for grid evaluation (by move). - //! @param theParams array of parameter values to move - void SetParams(NCollection_Array1&& theParams) { myParams = std::move(theParams); } - //! Returns the geometry handle. const Handle(Geom_Line)& Geometry() const { return myGeom; } - //! Returns number of parameters. - int NbParams() const { return myParams.Size(); } - //! 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 set - NCollection_Array1 EvaluateGrid() const + //! or empty array if geometry is null or no parameters + NCollection_Array1 EvaluateGrid(const TColStd_Array1OfReal& theParams) const { - if (myGeom.IsNull() || myParams.IsEmpty()) + if (myGeom.IsNull() || theParams.IsEmpty()) { return NCollection_Array1(); } - NCollection_Array1 aResult(myParams.Lower(), myParams.Upper()); + NCollection_Array1 aResult(1, theParams.Size()); // Extract line data const gp_Lin& aLin = myGeom->Lin(); @@ -94,26 +76,29 @@ public: const double aDirY = aDir.Y(); const double aDirZ = aDir.Z(); - for (int i = myParams.Lower(); i <= myParams.Upper(); ++i) + for (int i = theParams.Lower(); i <= theParams.Upper(); ++i) { - const double t = myParams.Value(i); - aResult.SetValue(i, gp_Pnt(aLocX + t * aDirX, aLocY + t * aDirY, aLocZ + t * aDirZ)); + const double t = theParams.Value(i); + aResult.SetValue(i - theParams.Lower() + 1, + gp_Pnt(aLocX + t * aDirX, aLocY + t * aDirY, aLocZ + t * aDirZ)); } 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 set - NCollection_Array1 EvaluateGridD1() const + //! or empty array if geometry is null or no parameters + NCollection_Array1 EvaluateGridD1( + const TColStd_Array1OfReal& theParams) const { - if (myGeom.IsNull() || myParams.IsEmpty()) + if (myGeom.IsNull() || theParams.IsEmpty()) { return NCollection_Array1(); } - NCollection_Array1 aResult(myParams.Lower(), myParams.Upper()); + NCollection_Array1 aResult(1, theParams.Size()); const gp_Lin& aLin = myGeom->Lin(); const gp_Pnt& aLoc = aLin.Location(); @@ -129,27 +114,30 @@ public: // D1 is constant for a line const gp_Vec aD1(aDirX, aDirY, aDirZ); - for (int i = myParams.Lower(); i <= myParams.Upper(); ++i) + for (int i = theParams.Lower(); i <= theParams.Upper(); ++i) { - const double t = myParams.Value(i); - aResult.ChangeValue(i) = {gp_Pnt(aLocX + t * aDirX, aLocY + t * aDirY, aLocZ + t * aDirZ), - aD1}; + const double t = theParams.Value(i); + aResult.ChangeValue(i - theParams.Lower() + + 1) = {gp_Pnt(aLocX + t * aDirX, aLocY + t * aDirY, aLocZ + t * aDirZ), + 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 set - NCollection_Array1 EvaluateGridD2() const + //! or empty array if geometry is null or no parameters + NCollection_Array1 EvaluateGridD2( + const TColStd_Array1OfReal& theParams) const { - if (myGeom.IsNull() || myParams.IsEmpty()) + if (myGeom.IsNull() || theParams.IsEmpty()) { return NCollection_Array1(); } - NCollection_Array1 aResult(myParams.Lower(), myParams.Upper()); + NCollection_Array1 aResult(1, theParams.Size()); const gp_Lin& aLin = myGeom->Lin(); const gp_Pnt& aLoc = aLin.Location(); @@ -165,27 +153,30 @@ public: const gp_Vec aD1(aDirX, aDirY, aDirZ); const gp_Vec aD2(0, 0, 0); // Second derivative is zero for a line - for (int i = myParams.Lower(); i <= myParams.Upper(); ++i) + for (int i = theParams.Lower(); i <= theParams.Upper(); ++i) { - const double t = myParams.Value(i); + const double t = theParams.Value(i); aResult.ChangeValue( - i) = {gp_Pnt(aLocX + t * aDirX, aLocY + t * aDirY, aLocZ + t * aDirZ), aD1, aD2}; + i - theParams.Lower() + + 1) = {gp_Pnt(aLocX + t * aDirX, aLocY + t * aDirY, aLocZ + t * aDirZ), 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 set - NCollection_Array1 EvaluateGridD3() const + //! or empty array if geometry is null or no parameters + NCollection_Array1 EvaluateGridD3( + const TColStd_Array1OfReal& theParams) const { - if (myGeom.IsNull() || myParams.IsEmpty()) + if (myGeom.IsNull() || theParams.IsEmpty()) { return NCollection_Array1(); } - NCollection_Array1 aResult(myParams.Lower(), myParams.Upper()); + NCollection_Array1 aResult(1, theParams.Size()); const gp_Lin& aLin = myGeom->Lin(); const gp_Pnt& aLoc = aLin.Location(); @@ -201,35 +192,37 @@ public: const gp_Vec aD1(aDirX, aDirY, aDirZ); const gp_Vec aZero(0, 0, 0); - for (int i = myParams.Lower(); i <= myParams.Upper(); ++i) + for (int i = theParams.Lower(); i <= theParams.Upper(); ++i) { - const double t = myParams.Value(i); + const double t = theParams.Value(i); aResult.ChangeValue( - i) = {gp_Pnt(aLocX + t * aDirX, aLocY + t * aDirY, aLocZ + t * aDirZ), aD1, aZero, aZero}; + i - theParams.Lower() + + 1) = {gp_Pnt(aLocX + t * aDirX, aLocY + t * aDirY, aLocZ + t * aDirZ), 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 set - NCollection_Array1 EvaluateGridDN(int theN) const + //! or empty array if geometry is null or no parameters + NCollection_Array1 EvaluateGridDN(const TColStd_Array1OfReal& theParams, int theN) const { - if (myGeom.IsNull() || myParams.IsEmpty() || theN < 1) + if (myGeom.IsNull() || theParams.IsEmpty() || theN < 1) { return NCollection_Array1(); } - NCollection_Array1 aResult(myParams.Lower(), myParams.Upper()); + NCollection_Array1 aResult(1, theParams.Size()); if (theN == 1) { // D1 is constant for a line (the direction) const gp_Dir& aDir = myGeom->Lin().Direction(); const gp_Vec aD1(aDir.X(), aDir.Y(), aDir.Z()); - for (int i = myParams.Lower(); i <= myParams.Upper(); ++i) + for (int i = 1; i <= theParams.Size(); ++i) { aResult.SetValue(i, aD1); } @@ -238,7 +231,7 @@ public: { // All higher derivatives are zero for a line const gp_Vec aZero(0, 0, 0); - for (int i = myParams.Lower(); i <= myParams.Upper(); ++i) + for (int i = 1; i <= theParams.Size(); ++i) { aResult.SetValue(i, aZero); } @@ -247,8 +240,7 @@ public: } private: - Handle(Geom_Line) myGeom; - NCollection_Array1 myParams; + Handle(Geom_Line) myGeom; }; #endif // _GeomGridEval_Line_HeaderFile diff --git a/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_OffsetCurve.cxx b/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_OffsetCurve.cxx index d48e30485f..b62ec3a4bd 100644 --- a/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_OffsetCurve.cxx +++ b/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_OffsetCurve.cxx @@ -18,22 +18,10 @@ //================================================================================================== -void GeomGridEval_OffsetCurve::SetParams(const TColStd_Array1OfReal& theParams) +NCollection_Array1 GeomGridEval_OffsetCurve::EvaluateGrid( + const TColStd_Array1OfReal& theParams) const { - const int aNbParams = theParams.Size(); - - myParams.Resize(1, aNbParams, false); - for (int i = 1; i <= aNbParams; ++i) - { - myParams.SetValue(i, theParams.Value(theParams.Lower() + i - 1)); - } -} - -//================================================================================================== - -NCollection_Array1 GeomGridEval_OffsetCurve::EvaluateGrid() const -{ - if (myBasis.IsNull() || myParams.IsEmpty()) + if (myBasis.IsNull() || theParams.IsEmpty()) { return NCollection_Array1(); } @@ -42,15 +30,14 @@ NCollection_Array1 GeomGridEval_OffsetCurve::EvaluateGrid() const // Batch evaluate basis curve D1 GeomGridEval_Curve aBasisEval; aBasisEval.Initialize(myBasis); - aBasisEval.SetParams(myParams); - NCollection_Array1 aBasisD1 = aBasisEval.EvaluateGridD1(); + NCollection_Array1 aBasisD1 = aBasisEval.EvaluateGridD1(theParams); if (aBasisD1.IsEmpty()) { return NCollection_Array1(); } - const int aNbParams = myParams.Size(); + const int aNbParams = theParams.Size(); NCollection_Array1 aResult(1, aNbParams); const gp_XYZ aDirXYZ = myDirection.XYZ(); @@ -69,9 +56,10 @@ NCollection_Array1 GeomGridEval_OffsetCurve::EvaluateGrid() const //================================================================================================== -NCollection_Array1 GeomGridEval_OffsetCurve::EvaluateGridD1() const +NCollection_Array1 GeomGridEval_OffsetCurve::EvaluateGridD1( + const TColStd_Array1OfReal& theParams) const { - if (myBasis.IsNull() || myParams.IsEmpty()) + if (myBasis.IsNull() || theParams.IsEmpty()) { return NCollection_Array1(); } @@ -80,15 +68,14 @@ NCollection_Array1 GeomGridEval_OffsetCurve::EvaluateGrid // Batch evaluate basis curve D2 GeomGridEval_Curve aBasisEval; aBasisEval.Initialize(myBasis); - aBasisEval.SetParams(myParams); - NCollection_Array1 aBasisD2 = aBasisEval.EvaluateGridD2(); + NCollection_Array1 aBasisD2 = aBasisEval.EvaluateGridD2(theParams); if (aBasisD2.IsEmpty()) { return NCollection_Array1(); } - const int aNbParams = myParams.Size(); + const int aNbParams = theParams.Size(); NCollection_Array1 aResult(1, aNbParams); const gp_XYZ aDirXYZ = myDirection.XYZ(); @@ -108,9 +95,10 @@ NCollection_Array1 GeomGridEval_OffsetCurve::EvaluateGrid //================================================================================================== -NCollection_Array1 GeomGridEval_OffsetCurve::EvaluateGridD2() const +NCollection_Array1 GeomGridEval_OffsetCurve::EvaluateGridD2( + const TColStd_Array1OfReal& theParams) const { - if (myBasis.IsNull() || myParams.IsEmpty()) + if (myBasis.IsNull() || theParams.IsEmpty()) { return NCollection_Array1(); } @@ -119,15 +107,14 @@ NCollection_Array1 GeomGridEval_OffsetCurve::EvaluateGrid // Batch evaluate basis curve D3 GeomGridEval_Curve aBasisEval; aBasisEval.Initialize(myBasis); - aBasisEval.SetParams(myParams); - NCollection_Array1 aBasisD3 = aBasisEval.EvaluateGridD3(); + NCollection_Array1 aBasisD3 = aBasisEval.EvaluateGridD3(theParams); if (aBasisD3.IsEmpty()) { return NCollection_Array1(); } - const int aNbParams = myParams.Size(); + const int aNbParams = theParams.Size(); NCollection_Array1 aResult(1, aNbParams); const gp_XYZ aDirXYZ = myDirection.XYZ(); @@ -145,13 +132,14 @@ NCollection_Array1 GeomGridEval_OffsetCurve::EvaluateGrid if (aD1.SquareMagnitude() <= gp::Resolution()) { gp_Vec aDummyD4; - isDirectionChange = Geom_OffsetCurveUtils::AdjustDerivative(*myBasis, - 3, - myParams.Value(i), - aD1, - aD2, - aD3, - aDummyD4); + isDirectionChange = + Geom_OffsetCurveUtils::AdjustDerivative(*myBasis, + 3, + theParams.Value(theParams.Lower() + i - 1), + aD1, + aD2, + aD3, + aDummyD4); } Geom_OffsetCurveUtils::CalculateD2(aP, aD1, aD2, aD3, aDirXYZ, myOffset, isDirectionChange); @@ -163,9 +151,10 @@ NCollection_Array1 GeomGridEval_OffsetCurve::EvaluateGrid //================================================================================================== -NCollection_Array1 GeomGridEval_OffsetCurve::EvaluateGridD3() const +NCollection_Array1 GeomGridEval_OffsetCurve::EvaluateGridD3( + const TColStd_Array1OfReal& theParams) const { - if (myBasis.IsNull() || myParams.IsEmpty()) + if (myBasis.IsNull() || theParams.IsEmpty()) { return NCollection_Array1(); } @@ -174,34 +163,35 @@ NCollection_Array1 GeomGridEval_OffsetCurve::EvaluateGrid // Batch evaluate basis curve D3, get D4 individually GeomGridEval_Curve aBasisEval; aBasisEval.Initialize(myBasis); - aBasisEval.SetParams(myParams); - NCollection_Array1 aBasisD3 = aBasisEval.EvaluateGridD3(); + NCollection_Array1 aBasisD3 = aBasisEval.EvaluateGridD3(theParams); if (aBasisD3.IsEmpty()) { return NCollection_Array1(); } - const int aNbParams = myParams.Size(); + const int aNbParams = theParams.Size(); NCollection_Array1 aResult(1, aNbParams); const gp_XYZ aDirXYZ = myDirection.XYZ(); for (int i = 1; i <= aNbParams; ++i) { + const double aParam = theParams.Value(theParams.Lower() + i - 1); + const GeomGridEval::CurveD3& aBasis = aBasisD3.Value(i); gp_Pnt aP = aBasis.Point; gp_Vec aD1 = aBasis.D1; gp_Vec aD2 = aBasis.D2; gp_Vec aD3 = aBasis.D3; - gp_Vec aD4 = myBasis->DN(myParams.Value(i), 4); + gp_Vec aD4 = myBasis->DN(aParam, 4); // Check for direction change at singular points bool isDirectionChange = false; if (aD1.SquareMagnitude() <= gp::Resolution()) { isDirectionChange = - Geom_OffsetCurveUtils::AdjustDerivative(*myBasis, 4, myParams.Value(i), aD1, aD2, aD3, aD4); + Geom_OffsetCurveUtils::AdjustDerivative(*myBasis, 4, aParam, aD1, aD2, aD3, aD4); } Geom_OffsetCurveUtils::CalculateD3(aP, @@ -220,18 +210,21 @@ NCollection_Array1 GeomGridEval_OffsetCurve::EvaluateGrid //================================================================================================== -NCollection_Array1 GeomGridEval_OffsetCurve::EvaluateGridDN(int theN) const +NCollection_Array1 GeomGridEval_OffsetCurve::EvaluateGridDN( + const TColStd_Array1OfReal& theParams, + int theN) const { - if (myBasis.IsNull() || myParams.IsEmpty() || theN < 1) + if (myBasis.IsNull() || theParams.IsEmpty() || theN < 1) { return NCollection_Array1(); } + const int aNbParams = theParams.Size(); + // Reuse optimized grid evaluators for orders 1-3 if (theN == 1) { - NCollection_Array1 aD1Grid = EvaluateGridD1(); - const int aNbParams = myParams.Size(); + NCollection_Array1 aD1Grid = EvaluateGridD1(theParams); NCollection_Array1 aResult(1, aNbParams); for (int i = 1; i <= aNbParams; ++i) { @@ -241,8 +234,7 @@ NCollection_Array1 GeomGridEval_OffsetCurve::EvaluateGridDN(int theN) co } else if (theN == 2) { - NCollection_Array1 aD2Grid = EvaluateGridD2(); - const int aNbParams = myParams.Size(); + NCollection_Array1 aD2Grid = EvaluateGridD2(theParams); NCollection_Array1 aResult(1, aNbParams); for (int i = 1; i <= aNbParams; ++i) { @@ -252,8 +244,7 @@ NCollection_Array1 GeomGridEval_OffsetCurve::EvaluateGridDN(int theN) co } else if (theN == 3) { - NCollection_Array1 aD3Grid = EvaluateGridD3(); - const int aNbParams = myParams.Size(); + NCollection_Array1 aD3Grid = EvaluateGridD3(theParams); NCollection_Array1 aResult(1, aNbParams); for (int i = 1; i <= aNbParams; ++i) { @@ -267,7 +258,6 @@ NCollection_Array1 GeomGridEval_OffsetCurve::EvaluateGridDN(int theN) co // Batch evaluate basis curve DN GeomGridEval_Curve aBasisEval; aBasisEval.Initialize(myBasis); - aBasisEval.SetParams(myParams); - return aBasisEval.EvaluateGridDN(theN); + return aBasisEval.EvaluateGridDN(theParams, theN); } } diff --git a/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_OffsetCurve.hxx b/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_OffsetCurve.hxx index d435cf308e..4e04a63bae 100644 --- a/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_OffsetCurve.hxx +++ b/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_OffsetCurve.hxx @@ -33,8 +33,7 @@ //! Usage: //! @code //! GeomGridEval_OffsetCurve anEvaluator(myGeomOffset); -//! anEvaluator.SetParams(myParams); -//! NCollection_Array1 aGrid = anEvaluator.EvaluateGrid(); +//! NCollection_Array1 aGrid = anEvaluator.EvaluateGrid(myParams); //! @endcode class GeomGridEval_OffsetCurve { @@ -61,50 +60,52 @@ public: GeomGridEval_OffsetCurve(GeomGridEval_OffsetCurve&&) = delete; GeomGridEval_OffsetCurve& operator=(GeomGridEval_OffsetCurve&&) = delete; - //! Set parameters for grid evaluation. - //! @param theParams array of parameter values - Standard_EXPORT void SetParams(const TColStd_Array1OfReal& theParams); - //! Returns the geometry handle. const Handle(Geom_OffsetCurve)& Geometry() const { return myGeom; } - //! Returns number of parameters. - int NbParams() const { return myParams.Size(); } - //! 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 set - Standard_EXPORT NCollection_Array1 EvaluateGrid() const; + //! or empty array if geometry is null or no parameters + Standard_EXPORT NCollection_Array1 EvaluateGrid( + const TColStd_Array1OfReal& 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 set - Standard_EXPORT NCollection_Array1 EvaluateGridD1() const; + //! or empty array if geometry is null or no parameters + Standard_EXPORT NCollection_Array1 EvaluateGridD1( + const TColStd_Array1OfReal& 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 set - Standard_EXPORT NCollection_Array1 EvaluateGridD2() const; + //! or empty array if geometry is null or no parameters + Standard_EXPORT NCollection_Array1 EvaluateGridD2( + const TColStd_Array1OfReal& theParams) const; //! Evaluate all grid points with derivatives up to third order. //! Uses GeomAdaptor_Curve::D3 for evaluation. + //! @param theParams array of parameter values //! @return array of CurveD3 (1-based indexing), - //! or empty array if geometry is null or no parameters set - Standard_EXPORT NCollection_Array1 EvaluateGridD3() const; + //! or empty array if geometry is null or no parameters + Standard_EXPORT NCollection_Array1 EvaluateGridD3( + const TColStd_Array1OfReal& theParams) const; //! Evaluate Nth derivative at all grid points. //! For orders 1-3, reuses EvaluateGridD1/D2/D3. //! For orders > 3, uses geometry 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 EvaluateGridDN(int theN) const; + Standard_EXPORT NCollection_Array1 EvaluateGridDN(const TColStd_Array1OfReal& theParams, + int theN) const; private: - Handle(Geom_OffsetCurve) myGeom; - Handle(Geom_Curve) myBasis; - double myOffset; - gp_Dir myDirection; - NCollection_Array1 myParams; + Handle(Geom_OffsetCurve) myGeom; + Handle(Geom_Curve) myBasis; + double myOffset; + gp_Dir myDirection; }; #endif // _GeomGridEval_OffsetCurve_HeaderFile diff --git a/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_OffsetSurface.cxx b/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_OffsetSurface.cxx index 3cac98439c..e84dd19267 100644 --- a/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_OffsetSurface.cxx +++ b/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_OffsetSurface.cxx @@ -19,30 +19,11 @@ //================================================================================================== -void GeomGridEval_OffsetSurface::SetUVParams(const TColStd_Array1OfReal& theUParams, - const TColStd_Array1OfReal& theVParams) +NCollection_Array2 GeomGridEval_OffsetSurface::EvaluateGrid( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams) const { - const int aNbU = theUParams.Size(); - const int aNbV = theVParams.Size(); - - myUParams.Resize(1, aNbU, false); - for (int i = 1; i <= aNbU; ++i) - { - myUParams.SetValue(i, theUParams.Value(theUParams.Lower() + i - 1)); - } - - myVParams.Resize(1, aNbV, false); - for (int j = 1; j <= aNbV; ++j) - { - myVParams.SetValue(j, theVParams.Value(theVParams.Lower() + j - 1)); - } -} - -//================================================================================================== - -NCollection_Array2 GeomGridEval_OffsetSurface::EvaluateGrid() const -{ - if (myBasis.IsNull() || myUParams.IsEmpty() || myVParams.IsEmpty()) + if (myBasis.IsNull() || theUParams.IsEmpty() || theVParams.IsEmpty()) { return NCollection_Array2(); } @@ -57,21 +38,20 @@ NCollection_Array2 GeomGridEval_OffsetSurface::EvaluateGrid() const // Use the equivalent surface directly GeomGridEval_Surface anEquivEval; anEquivEval.Initialize(anEquivSurf); - anEquivEval.SetUVParams(myUParams, myVParams); - return anEquivEval.EvaluateGrid(); + return anEquivEval.EvaluateGrid(theUParams, theVParams); } } - const int aNbU = myUParams.Size(); - const int aNbV = myVParams.Size(); + const int aNbU = theUParams.Size(); + const int aNbV = theVParams.Size(); NCollection_Array2 aResult(1, aNbU, 1, aNbV); // Batch evaluate basis surface D1 (offset D0 requires basis D1) GeomGridEval_Surface aBasisEval; aBasisEval.Initialize(myBasis); - aBasisEval.SetUVParams(myUParams, myVParams); - NCollection_Array2 aBasisD1 = aBasisEval.EvaluateGridD1(); + NCollection_Array2 aBasisD1 = + aBasisEval.EvaluateGridD1(theUParams, theVParams); if (aBasisD1.IsEmpty()) { @@ -87,12 +67,14 @@ NCollection_Array2 GeomGridEval_OffsetSurface::EvaluateGrid() const for (int i = 1; i <= aNbU; ++i) { + const double aU = theUParams.Value(theUParams.Lower() + i - 1); for (int j = 1; j <= aNbV; ++j) { + const double aV = theVParams.Value(theVParams.Lower() + j - 1); const GeomGridEval::SurfD1& aBasis = aBasisD1.Value(i, j); gp_Pnt aP = aBasis.Point; - Geom_OffsetSurfaceUtils::EvaluateD0(myUParams.Value(i), - myVParams.Value(j), + Geom_OffsetSurfaceUtils::EvaluateD0(aU, + aV, &aBasisAdaptor, myOffset, anOscQuery, @@ -108,9 +90,11 @@ NCollection_Array2 GeomGridEval_OffsetSurface::EvaluateGrid() const //================================================================================================== -NCollection_Array2 GeomGridEval_OffsetSurface::EvaluateGridD1() const +NCollection_Array2 GeomGridEval_OffsetSurface::EvaluateGridD1( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams) const { - if (myBasis.IsNull() || myUParams.IsEmpty() || myVParams.IsEmpty()) + if (myBasis.IsNull() || theUParams.IsEmpty() || theVParams.IsEmpty()) { return NCollection_Array2(); } @@ -123,20 +107,19 @@ NCollection_Array2 GeomGridEval_OffsetSurface::EvaluateGri { GeomGridEval_Surface anEquivEval; anEquivEval.Initialize(anEquivSurf); - anEquivEval.SetUVParams(myUParams, myVParams); - return anEquivEval.EvaluateGridD1(); + return anEquivEval.EvaluateGridD1(theUParams, theVParams); } } - const int aNbU = myUParams.Size(); - const int aNbV = myVParams.Size(); + const int aNbU = theUParams.Size(); + const int aNbV = theVParams.Size(); NCollection_Array2 aResult(1, aNbU, 1, aNbV); // Batch evaluate basis surface D2 (offset D1 requires basis D2) GeomGridEval_Surface aBasisEval; aBasisEval.Initialize(myBasis); - aBasisEval.SetUVParams(myUParams, myVParams); - NCollection_Array2 aBasisD2 = aBasisEval.EvaluateGridD2(); + NCollection_Array2 aBasisD2 = + aBasisEval.EvaluateGridD2(theUParams, theVParams); if (aBasisD2.IsEmpty()) { @@ -148,14 +131,16 @@ NCollection_Array2 GeomGridEval_OffsetSurface::EvaluateGri for (int i = 1; i <= aNbU; ++i) { + const double aU = theUParams.Value(theUParams.Lower() + i - 1); for (int j = 1; j <= aNbV; ++j) { + const double aV = theVParams.Value(theVParams.Lower() + j - 1); const GeomGridEval::SurfD2& aBasis = aBasisD2.Value(i, j); gp_Pnt aP = aBasis.Point; gp_Vec aD1U = aBasis.D1U; gp_Vec aD1V = aBasis.D1V; - Geom_OffsetSurfaceUtils::EvaluateD1(myUParams.Value(i), - myVParams.Value(j), + Geom_OffsetSurfaceUtils::EvaluateD1(aU, + aV, &aBasisAdaptor, myOffset, anOscQuery, @@ -174,9 +159,11 @@ NCollection_Array2 GeomGridEval_OffsetSurface::EvaluateGri //================================================================================================== -NCollection_Array2 GeomGridEval_OffsetSurface::EvaluateGridD2() const +NCollection_Array2 GeomGridEval_OffsetSurface::EvaluateGridD2( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams) const { - if (myBasis.IsNull() || myUParams.IsEmpty() || myVParams.IsEmpty()) + if (myBasis.IsNull() || theUParams.IsEmpty() || theVParams.IsEmpty()) { return NCollection_Array2(); } @@ -189,20 +176,19 @@ NCollection_Array2 GeomGridEval_OffsetSurface::EvaluateGri { GeomGridEval_Surface anEquivEval; anEquivEval.Initialize(anEquivSurf); - anEquivEval.SetUVParams(myUParams, myVParams); - return anEquivEval.EvaluateGridD2(); + return anEquivEval.EvaluateGridD2(theUParams, theVParams); } } - const int aNbU = myUParams.Size(); - const int aNbV = myVParams.Size(); + const int aNbU = theUParams.Size(); + const int aNbV = theVParams.Size(); NCollection_Array2 aResult(1, aNbU, 1, aNbV); // Batch evaluate basis surface D3 (offset D2 requires basis D3) GeomGridEval_Surface aBasisEval; aBasisEval.Initialize(myBasis); - aBasisEval.SetUVParams(myUParams, myVParams); - NCollection_Array2 aBasisD3 = aBasisEval.EvaluateGridD3(); + NCollection_Array2 aBasisD3 = + aBasisEval.EvaluateGridD3(theUParams, theVParams); if (aBasisD3.IsEmpty()) { @@ -214,8 +200,10 @@ NCollection_Array2 GeomGridEval_OffsetSurface::EvaluateGri for (int i = 1; i <= aNbU; ++i) { + const double aU = theUParams.Value(theUParams.Lower() + i - 1); for (int j = 1; j <= aNbV; ++j) { + const double aV = theVParams.Value(theVParams.Lower() + j - 1); const GeomGridEval::SurfD3& aBasis = aBasisD3.Value(i, j); gp_Pnt aP = aBasis.Point; gp_Vec aD1U = aBasis.D1U; @@ -223,8 +211,8 @@ NCollection_Array2 GeomGridEval_OffsetSurface::EvaluateGri gp_Vec aD2U = aBasis.D2U; gp_Vec aD2V = aBasis.D2V; gp_Vec aD2UV = aBasis.D2UV; - Geom_OffsetSurfaceUtils::EvaluateD2(myUParams.Value(i), - myVParams.Value(j), + Geom_OffsetSurfaceUtils::EvaluateD2(aU, + aV, &aBasisAdaptor, myOffset, anOscQuery, @@ -247,9 +235,11 @@ NCollection_Array2 GeomGridEval_OffsetSurface::EvaluateGri //================================================================================================== -NCollection_Array2 GeomGridEval_OffsetSurface::EvaluateGridD3() const +NCollection_Array2 GeomGridEval_OffsetSurface::EvaluateGridD3( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams) const { - if (myBasis.IsNull() || myUParams.IsEmpty() || myVParams.IsEmpty()) + if (myBasis.IsNull() || theUParams.IsEmpty() || theVParams.IsEmpty()) { return NCollection_Array2(); } @@ -262,13 +252,12 @@ NCollection_Array2 GeomGridEval_OffsetSurface::EvaluateGri { GeomGridEval_Surface anEquivEval; anEquivEval.Initialize(anEquivSurf); - anEquivEval.SetUVParams(myUParams, myVParams); - return anEquivEval.EvaluateGridD3(); + return anEquivEval.EvaluateGridD3(theUParams, theVParams); } } - const int aNbU = myUParams.Size(); - const int aNbV = myVParams.Size(); + const int aNbU = theUParams.Size(); + const int aNbV = theVParams.Size(); NCollection_Array2 aResult(1, aNbU, 1, aNbV); GeomAdaptor_Surface aBasisAdaptor(myBasis); @@ -276,12 +265,14 @@ NCollection_Array2 GeomGridEval_OffsetSurface::EvaluateGri for (int i = 1; i <= aNbU; ++i) { + const double aU = theUParams.Value(theUParams.Lower() + i - 1); for (int j = 1; j <= aNbV; ++j) { - gp_Pnt aP; - gp_Vec aD1U, aD1V, aD2U, aD2V, aD2UV, aD3U, aD3V, aD3UUV, aD3UVV; - Geom_OffsetSurfaceUtils::EvaluateD3(myUParams.Value(i), - myVParams.Value(j), + const double aV = theVParams.Value(theVParams.Lower() + j - 1); + gp_Pnt aP; + gp_Vec aD1U, aD1V, aD2U, aD2V, aD2UV, aD3U, aD3V, aD3UUV, aD3UVV; + Geom_OffsetSurfaceUtils::EvaluateD3(aU, + aV, &aBasisAdaptor, myOffset, anOscQuery, @@ -304,9 +295,13 @@ NCollection_Array2 GeomGridEval_OffsetSurface::EvaluateGri //================================================================================================== -NCollection_Array2 GeomGridEval_OffsetSurface::EvaluateGridDN(int theNU, int theNV) const +NCollection_Array2 GeomGridEval_OffsetSurface::EvaluateGridDN( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams, + int theNU, + int theNV) const { - if (myBasis.IsNull() || myUParams.IsEmpty() || myVParams.IsEmpty() || theNU < 0 || theNV < 0 + if (myBasis.IsNull() || theUParams.IsEmpty() || theVParams.IsEmpty() || theNU < 0 || theNV < 0 || (theNU + theNV) < 1) { return NCollection_Array2(); @@ -320,21 +315,20 @@ NCollection_Array2 GeomGridEval_OffsetSurface::EvaluateGridDN(int theNU, { GeomGridEval_Surface anEquivEval; anEquivEval.Initialize(anEquivSurf); - anEquivEval.SetUVParams(myUParams, myVParams); - return anEquivEval.EvaluateGridDN(theNU, theNV); + return anEquivEval.EvaluateGridDN(theUParams, theVParams, theNU, theNV); } } - const int aNbU = myUParams.Size(); - const int aNbV = myVParams.Size(); + const int aNbU = theUParams.Size(); + const int aNbV = theVParams.Size(); NCollection_Array2 aResult(1, aNbU, 1, aNbV); // Batch evaluate basis surface D1 (offset DN requires basis D1) GeomGridEval_Surface aBasisEval; aBasisEval.Initialize(myBasis); - aBasisEval.SetUVParams(myUParams, myVParams); - NCollection_Array2 aBasisD1 = aBasisEval.EvaluateGridD1(); + NCollection_Array2 aBasisD1 = + aBasisEval.EvaluateGridD1(theUParams, theVParams); if (aBasisD1.IsEmpty()) { @@ -346,12 +340,14 @@ NCollection_Array2 GeomGridEval_OffsetSurface::EvaluateGridDN(int theNU, for (int i = 1; i <= aNbU; ++i) { + const double aU = theUParams.Value(theUParams.Lower() + i - 1); for (int j = 1; j <= aNbV; ++j) { + const double aV = theVParams.Value(theVParams.Lower() + j - 1); const GeomGridEval::SurfD1& aBasis = aBasisD1.Value(i, j); gp_Vec aDN; - Geom_OffsetSurfaceUtils::EvaluateDN(myUParams.Value(i), - myVParams.Value(j), + Geom_OffsetSurfaceUtils::EvaluateDN(aU, + aV, theNU, theNV, &aBasisAdaptor, @@ -366,3 +362,308 @@ NCollection_Array2 GeomGridEval_OffsetSurface::EvaluateGridDN(int theNU, return aResult; } + +//================================================================================================== + +NCollection_Array1 GeomGridEval_OffsetSurface::EvaluatePoints( + const NCollection_Array1& theUVPairs) const +{ + if (myBasis.IsNull() || theUVPairs.IsEmpty()) + { + return NCollection_Array1(); + } + + // Fast path: check if offset surface has an equivalent simple surface + if (!myGeom.IsNull()) + { + Handle(Geom_Surface) anEquivSurf = myGeom->Surface(); + if (!anEquivSurf.IsNull() && anEquivSurf.get() != myGeom.get()) + { + GeomGridEval_Surface anEquivEval; + anEquivEval.Initialize(anEquivSurf); + return anEquivEval.EvaluatePoints(theUVPairs); + } + } + + const int aNbPts = theUVPairs.Size(); + + NCollection_Array1 aResult(1, aNbPts); + + // Batch evaluate basis surface D1 (offset D0 requires basis D1) + GeomGridEval_Surface aBasisEval; + aBasisEval.Initialize(myBasis); + NCollection_Array1 aBasisD1 = aBasisEval.EvaluatePointsD1(theUVPairs); + + if (aBasisD1.IsEmpty()) + { + return NCollection_Array1(); + } + + GeomAdaptor_Surface aBasisAdaptor(myBasis); + const Geom_OffsetSurface* anOscQuery = myGeom.get(); + + for (int i = 1; i <= aNbPts; ++i) + { + const gp_Pnt2d& aUV = theUVPairs.Value(theUVPairs.Lower() + i - 1); + const GeomGridEval::SurfD1& aBasis = aBasisD1.Value(i); + gp_Pnt aP = aBasis.Point; + Geom_OffsetSurfaceUtils::EvaluateD0(aUV.X(), + aUV.Y(), + &aBasisAdaptor, + myOffset, + anOscQuery, + aP, + aBasis.D1U, + aBasis.D1V); + aResult.SetValue(i, aP); + } + + return aResult; +} + +//================================================================================================== + +NCollection_Array1 GeomGridEval_OffsetSurface::EvaluatePointsD1( + const NCollection_Array1& theUVPairs) const +{ + if (myBasis.IsNull() || theUVPairs.IsEmpty()) + { + return NCollection_Array1(); + } + + // Fast path: check if offset surface has an equivalent simple surface + if (!myGeom.IsNull()) + { + Handle(Geom_Surface) anEquivSurf = myGeom->Surface(); + if (!anEquivSurf.IsNull() && anEquivSurf.get() != myGeom.get()) + { + GeomGridEval_Surface anEquivEval; + anEquivEval.Initialize(anEquivSurf); + return anEquivEval.EvaluatePointsD1(theUVPairs); + } + } + + const int aNbPts = theUVPairs.Size(); + NCollection_Array1 aResult(1, aNbPts); + + // Batch evaluate basis surface D2 (offset D1 requires basis D2) + GeomGridEval_Surface aBasisEval; + aBasisEval.Initialize(myBasis); + NCollection_Array1 aBasisD2 = aBasisEval.EvaluatePointsD2(theUVPairs); + + if (aBasisD2.IsEmpty()) + { + return NCollection_Array1(); + } + + GeomAdaptor_Surface aBasisAdaptor(myBasis); + const Geom_OffsetSurface* anOscQuery = myGeom.get(); + + for (int i = 1; i <= aNbPts; ++i) + { + const gp_Pnt2d& aUV = theUVPairs.Value(theUVPairs.Lower() + i - 1); + const GeomGridEval::SurfD2& aBasis = aBasisD2.Value(i); + gp_Pnt aP = aBasis.Point; + gp_Vec aD1U = aBasis.D1U; + gp_Vec aD1V = aBasis.D1V; + Geom_OffsetSurfaceUtils::EvaluateD1(aUV.X(), + aUV.Y(), + &aBasisAdaptor, + myOffset, + anOscQuery, + aP, + aD1U, + aD1V, + aBasis.D2U, + aBasis.D2V, + aBasis.D2UV); + aResult.ChangeValue(i) = {aP, aD1U, aD1V}; + } + + return aResult; +} + +//================================================================================================== + +NCollection_Array1 GeomGridEval_OffsetSurface::EvaluatePointsD2( + const NCollection_Array1& theUVPairs) const +{ + if (myBasis.IsNull() || theUVPairs.IsEmpty()) + { + return NCollection_Array1(); + } + + // Fast path: check if offset surface has an equivalent simple surface + if (!myGeom.IsNull()) + { + Handle(Geom_Surface) anEquivSurf = myGeom->Surface(); + if (!anEquivSurf.IsNull() && anEquivSurf.get() != myGeom.get()) + { + GeomGridEval_Surface anEquivEval; + anEquivEval.Initialize(anEquivSurf); + return anEquivEval.EvaluatePointsD2(theUVPairs); + } + } + + const int aNbPts = theUVPairs.Size(); + NCollection_Array1 aResult(1, aNbPts); + + // Batch evaluate basis surface D3 (offset D2 requires basis D3) + GeomGridEval_Surface aBasisEval; + aBasisEval.Initialize(myBasis); + NCollection_Array1 aBasisD3 = aBasisEval.EvaluatePointsD3(theUVPairs); + + if (aBasisD3.IsEmpty()) + { + return NCollection_Array1(); + } + + GeomAdaptor_Surface aBasisAdaptor(myBasis); + const Geom_OffsetSurface* anOscQuery = myGeom.get(); + + for (int i = 1; i <= aNbPts; ++i) + { + const gp_Pnt2d& aUV = theUVPairs.Value(theUVPairs.Lower() + i - 1); + const GeomGridEval::SurfD3& aBasis = aBasisD3.Value(i); + gp_Pnt aP = aBasis.Point; + gp_Vec aD1U = aBasis.D1U; + gp_Vec aD1V = aBasis.D1V; + gp_Vec aD2U = aBasis.D2U; + gp_Vec aD2V = aBasis.D2V; + gp_Vec aD2UV = aBasis.D2UV; + Geom_OffsetSurfaceUtils::EvaluateD2(aUV.X(), + aUV.Y(), + &aBasisAdaptor, + myOffset, + anOscQuery, + aP, + aD1U, + aD1V, + aD2U, + aD2V, + aD2UV, + aBasis.D3U, + aBasis.D3V, + aBasis.D3UUV, + aBasis.D3UVV); + aResult.ChangeValue(i) = {aP, aD1U, aD1V, aD2U, aD2V, aD2UV}; + } + + return aResult; +} + +//================================================================================================== + +NCollection_Array1 GeomGridEval_OffsetSurface::EvaluatePointsD3( + const NCollection_Array1& theUVPairs) const +{ + if (myBasis.IsNull() || theUVPairs.IsEmpty()) + { + return NCollection_Array1(); + } + + // Fast path: check if offset surface has an equivalent simple surface + if (!myGeom.IsNull()) + { + Handle(Geom_Surface) anEquivSurf = myGeom->Surface(); + if (!anEquivSurf.IsNull() && anEquivSurf.get() != myGeom.get()) + { + GeomGridEval_Surface anEquivEval; + anEquivEval.Initialize(anEquivSurf); + return anEquivEval.EvaluatePointsD3(theUVPairs); + } + } + + const int aNbPts = theUVPairs.Size(); + NCollection_Array1 aResult(1, aNbPts); + + GeomAdaptor_Surface aBasisAdaptor(myBasis); + const Geom_OffsetSurface* anOscQuery = myGeom.get(); + + for (int i = 1; i <= aNbPts; ++i) + { + const gp_Pnt2d& aUV = theUVPairs.Value(theUVPairs.Lower() + i - 1); + gp_Pnt aP; + gp_Vec aD1U, aD1V, aD2U, aD2V, aD2UV, aD3U, aD3V, aD3UUV, aD3UVV; + Geom_OffsetSurfaceUtils::EvaluateD3(aUV.X(), + aUV.Y(), + &aBasisAdaptor, + myOffset, + anOscQuery, + aP, + aD1U, + aD1V, + aD2U, + aD2V, + aD2UV, + aD3U, + aD3V, + aD3UUV, + aD3UVV); + aResult.ChangeValue(i) = {aP, aD1U, aD1V, aD2U, aD2V, aD2UV, aD3U, aD3V, aD3UUV, aD3UVV}; + } + + return aResult; +} + +//================================================================================================== + +NCollection_Array1 GeomGridEval_OffsetSurface::EvaluatePointsDN( + const NCollection_Array1& theUVPairs, + int theNU, + int theNV) const +{ + if (myBasis.IsNull() || theUVPairs.IsEmpty() || theNU < 0 || theNV < 0 || (theNU + theNV) < 1) + { + return NCollection_Array1(); + } + + // Fast path: check if offset surface has an equivalent simple surface + if (!myGeom.IsNull()) + { + Handle(Geom_Surface) anEquivSurf = myGeom->Surface(); + if (!anEquivSurf.IsNull() && anEquivSurf.get() != myGeom.get()) + { + GeomGridEval_Surface anEquivEval; + anEquivEval.Initialize(anEquivSurf); + return anEquivEval.EvaluatePointsDN(theUVPairs, theNU, theNV); + } + } + + const int aNbPts = theUVPairs.Size(); + + NCollection_Array1 aResult(1, aNbPts); + + // Batch evaluate basis surface D1 (offset DN requires basis D1) + GeomGridEval_Surface aBasisEval; + aBasisEval.Initialize(myBasis); + NCollection_Array1 aBasisD1 = aBasisEval.EvaluatePointsD1(theUVPairs); + + if (aBasisD1.IsEmpty()) + { + return NCollection_Array1(); + } + + GeomAdaptor_Surface aBasisAdaptor(myBasis); + const Geom_OffsetSurface* anOscQuery = myGeom.get(); + + for (int i = 1; i <= aNbPts; ++i) + { + const gp_Pnt2d& aUV = theUVPairs.Value(theUVPairs.Lower() + i - 1); + const GeomGridEval::SurfD1& aBasis = aBasisD1.Value(i); + gp_Vec aDN; + Geom_OffsetSurfaceUtils::EvaluateDN(aUV.X(), + aUV.Y(), + theNU, + theNV, + &aBasisAdaptor, + myOffset, + anOscQuery, + aDN, + aBasis.D1U, + aBasis.D1V); + aResult.SetValue(i, aDN); + } + + return aResult; +} diff --git a/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_OffsetSurface.hxx b/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_OffsetSurface.hxx index 78f2d11289..0de3da417a 100644 --- a/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_OffsetSurface.hxx +++ b/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_OffsetSurface.hxx @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -34,8 +35,7 @@ //! Usage: //! @code //! GeomGridEval_OffsetSurface anEvaluator(myGeomOffset); -//! anEvaluator.SetUVParams(myUParams, myVParams); -//! NCollection_Array2 aGrid = anEvaluator.EvaluateGrid(); +//! NCollection_Array2 aGrid = anEvaluator.EvaluateGrid(myUParams, myVParams); //! @endcode class GeomGridEval_OffsetSurface { @@ -61,55 +61,100 @@ public: GeomGridEval_OffsetSurface(GeomGridEval_OffsetSurface&&) = delete; GeomGridEval_OffsetSurface& operator=(GeomGridEval_OffsetSurface&&) = delete; - //! Set UV parameters from two 1D arrays. - //! @param theUParams array of U parameter values - //! @param theVParams array of V parameter values - Standard_EXPORT void SetUVParams(const TColStd_Array1OfReal& theUParams, - const TColStd_Array1OfReal& theVParams); - //! Returns the geometry handle. const Handle(Geom_OffsetSurface)& Geometry() const { return myGeom; } - //! Returns number of U parameters. - int NbUParams() const { return myUParams.Size(); } - - //! Returns number of V parameters. - int NbVParams() const { return myVParams.Size(); } - //! Evaluate all grid points. + //! @param[in] theUParams array of U parameter values + //! @param[in] theVParams array of V parameter values //! @return 2D array of evaluated points (1-based indexing), //! or empty array if geometry is null or no parameters set - Standard_EXPORT NCollection_Array2 EvaluateGrid() const; + Standard_EXPORT NCollection_Array2 EvaluateGrid( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams) const; //! Evaluate all grid points with first partial derivatives. + //! @param[in] theUParams array of U parameter values + //! @param[in] theVParams array of V parameter values //! @return 2D array of SurfD1 (1-based indexing), //! or empty array if geometry is null or no parameters set - Standard_EXPORT NCollection_Array2 EvaluateGridD1() const; + Standard_EXPORT NCollection_Array2 EvaluateGridD1( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams) const; //! Evaluate all grid points with first and second partial derivatives. + //! @param[in] theUParams array of U parameter values + //! @param[in] theVParams array of V parameter values //! @return 2D array of SurfD2 (1-based indexing), //! or empty array if geometry is null or no parameters set - Standard_EXPORT NCollection_Array2 EvaluateGridD2() const; + Standard_EXPORT NCollection_Array2 EvaluateGridD2( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams) const; //! Evaluate all grid points with derivatives up to third order. //! Uses GeomAdaptor_Surface::D3 for evaluation. + //! @param[in] theUParams array of U parameter values + //! @param[in] theVParams array of V parameter values //! @return 2D array of SurfD3 (1-based indexing), //! or empty array if geometry is null or no parameters set - Standard_EXPORT NCollection_Array2 EvaluateGridD3() const; + Standard_EXPORT NCollection_Array2 EvaluateGridD3( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams) const; //! Evaluate partial derivative d^(NU+NV)S/(dU^NU dV^NV) at all grid points. //! Uses geometry DN method. - //! @param theNU derivative order in U direction - //! @param theNV derivative order in V direction + //! @param[in] theUParams array of U parameter values + //! @param[in] theVParams array of V parameter values + //! @param[in] theNU derivative order in U direction + //! @param[in] theNV derivative order in V direction //! @return 2D array of derivative vectors (1-based indexing) - Standard_EXPORT NCollection_Array2 EvaluateGridDN(int theNU, int theNV) const; + Standard_EXPORT NCollection_Array2 EvaluateGridDN(const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams, + int theNU, + int theNV) const; + + //! Evaluate points at arbitrary UV pairs. + //! @param[in] theUVPairs array of UV coordinate pairs (U=X(), V=Y()) + //! @return array of evaluated points (1-based indexing), + //! or empty array if geometry is null or no parameters set + Standard_EXPORT NCollection_Array1 EvaluatePoints( + const NCollection_Array1& theUVPairs) const; + + //! Evaluate points with first partial derivatives at arbitrary UV pairs. + //! @param[in] theUVPairs array of UV coordinate pairs (U=X(), V=Y()) + //! @return array of SurfD1 (1-based indexing), + //! or empty array if geometry is null or no parameters set + Standard_EXPORT NCollection_Array1 EvaluatePointsD1( + const NCollection_Array1& theUVPairs) const; + + //! Evaluate points with first and second partial derivatives at arbitrary UV pairs. + //! @param[in] theUVPairs array of UV coordinate pairs (U=X(), V=Y()) + //! @return array of SurfD2 (1-based indexing), + //! or empty array if geometry is null or no parameters set + Standard_EXPORT NCollection_Array1 EvaluatePointsD2( + const NCollection_Array1& theUVPairs) const; + + //! Evaluate points with derivatives up to third order at arbitrary UV pairs. + //! @param[in] theUVPairs array of UV coordinate pairs (U=X(), V=Y()) + //! @return array of SurfD3 (1-based indexing), + //! or empty array if geometry is null or no parameters set + Standard_EXPORT NCollection_Array1 EvaluatePointsD3( + const NCollection_Array1& theUVPairs) const; + + //! Evaluate partial derivative at arbitrary UV pairs. + //! @param[in] theUVPairs array of UV coordinate pairs (U=X(), V=Y()) + //! @param[in] theNU derivative order in U direction + //! @param[in] theNV derivative order in V direction + //! @return array of derivative vectors (1-based indexing) + Standard_EXPORT NCollection_Array1 EvaluatePointsDN( + const NCollection_Array1& theUVPairs, + int theNU, + int theNV) const; private: Handle(Geom_OffsetSurface) myGeom; Handle(Geom_Surface) myBasis; double myOffset; - NCollection_Array1 myUParams; - NCollection_Array1 myVParams; }; #endif // _GeomGridEval_OffsetSurface_HeaderFile diff --git a/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_OtherCurve.cxx b/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_OtherCurve.cxx index dc631d61e3..3b150c1eec 100644 --- a/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_OtherCurve.cxx +++ b/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_OtherCurve.cxx @@ -15,29 +15,20 @@ //================================================================================================== -void GeomGridEval_OtherCurve::SetParams(const TColStd_Array1OfReal& theParams) +NCollection_Array1 GeomGridEval_OtherCurve::EvaluateGrid( + const TColStd_Array1OfReal& theParams) const { - myParams.Resize(theParams.Lower(), theParams.Upper(), false); - for (int i = theParams.Lower(); i <= theParams.Upper(); ++i) - { - myParams.SetValue(i, theParams.Value(i)); - } -} - -//================================================================================================== - -NCollection_Array1 GeomGridEval_OtherCurve::EvaluateGrid() const -{ - if (myParams.IsEmpty()) + if (theParams.IsEmpty()) { return NCollection_Array1(); } - NCollection_Array1 aResult(myParams.Lower(), myParams.Upper()); + const int aNb = theParams.Size(); + NCollection_Array1 aResult(1, aNb); - for (int i = myParams.Lower(); i <= myParams.Upper(); ++i) + for (int i = theParams.Lower(); i <= theParams.Upper(); ++i) { - aResult.SetValue(i, myCurve.get().Value(myParams.Value(i))); + aResult.SetValue(i - theParams.Lower() + 1, myCurve.get().Value(theParams.Value(i))); } return aResult; @@ -45,21 +36,23 @@ NCollection_Array1 GeomGridEval_OtherCurve::EvaluateGrid() const //================================================================================================== -NCollection_Array1 GeomGridEval_OtherCurve::EvaluateGridD1() const +NCollection_Array1 GeomGridEval_OtherCurve::EvaluateGridD1( + const TColStd_Array1OfReal& theParams) const { - if (myParams.IsEmpty()) + if (theParams.IsEmpty()) { return NCollection_Array1(); } - NCollection_Array1 aResult(myParams.Lower(), myParams.Upper()); + const int aNb = theParams.Size(); + NCollection_Array1 aResult(1, aNb); - for (int i = myParams.Lower(); i <= myParams.Upper(); ++i) + for (int i = theParams.Lower(); i <= theParams.Upper(); ++i) { gp_Pnt aPoint; gp_Vec aD1; - myCurve.get().D1(myParams.Value(i), aPoint, aD1); - aResult.ChangeValue(i) = {aPoint, aD1}; + myCurve.get().D1(theParams.Value(i), aPoint, aD1); + aResult.ChangeValue(i - theParams.Lower() + 1) = {aPoint, aD1}; } return aResult; @@ -67,21 +60,23 @@ NCollection_Array1 GeomGridEval_OtherCurve::EvaluateGridD //================================================================================================== -NCollection_Array1 GeomGridEval_OtherCurve::EvaluateGridD2() const +NCollection_Array1 GeomGridEval_OtherCurve::EvaluateGridD2( + const TColStd_Array1OfReal& theParams) const { - if (myParams.IsEmpty()) + if (theParams.IsEmpty()) { return NCollection_Array1(); } - NCollection_Array1 aResult(myParams.Lower(), myParams.Upper()); + const int aNb = theParams.Size(); + NCollection_Array1 aResult(1, aNb); - for (int i = myParams.Lower(); i <= myParams.Upper(); ++i) + for (int i = theParams.Lower(); i <= theParams.Upper(); ++i) { gp_Pnt aPoint; gp_Vec aD1, aD2; - myCurve.get().D2(myParams.Value(i), aPoint, aD1, aD2); - aResult.ChangeValue(i) = {aPoint, aD1, aD2}; + myCurve.get().D2(theParams.Value(i), aPoint, aD1, aD2); + aResult.ChangeValue(i - theParams.Lower() + 1) = {aPoint, aD1, aD2}; } return aResult; @@ -89,21 +84,23 @@ NCollection_Array1 GeomGridEval_OtherCurve::EvaluateGridD //================================================================================================== -NCollection_Array1 GeomGridEval_OtherCurve::EvaluateGridD3() const +NCollection_Array1 GeomGridEval_OtherCurve::EvaluateGridD3( + const TColStd_Array1OfReal& theParams) const { - if (myParams.IsEmpty()) + if (theParams.IsEmpty()) { return NCollection_Array1(); } - NCollection_Array1 aResult(myParams.Lower(), myParams.Upper()); + const int aNb = theParams.Size(); + NCollection_Array1 aResult(1, aNb); - for (int i = myParams.Lower(); i <= myParams.Upper(); ++i) + for (int i = theParams.Lower(); i <= theParams.Upper(); ++i) { gp_Pnt aPoint; gp_Vec aD1, aD2, aD3; - myCurve.get().D3(myParams.Value(i), aPoint, aD1, aD2, aD3); - aResult.ChangeValue(i) = {aPoint, aD1, aD2, aD3}; + myCurve.get().D3(theParams.Value(i), aPoint, aD1, aD2, aD3); + aResult.ChangeValue(i - theParams.Lower() + 1) = {aPoint, aD1, aD2, aD3}; } return aResult; @@ -111,36 +108,39 @@ NCollection_Array1 GeomGridEval_OtherCurve::EvaluateGridD //================================================================================================== -NCollection_Array1 GeomGridEval_OtherCurve::EvaluateGridDN(int theN) const +NCollection_Array1 GeomGridEval_OtherCurve::EvaluateGridDN( + const TColStd_Array1OfReal& theParams, + int theN) const { - if (myParams.IsEmpty() || theN < 1) + if (theParams.IsEmpty() || theN < 1) { return NCollection_Array1(); } - NCollection_Array1 aResult(myParams.Lower(), myParams.Upper()); + const int aNb = theParams.Size(); + NCollection_Array1 aResult(1, aNb); // Reuse existing grid evaluators for orders 1-3 if (theN == 1) { - NCollection_Array1 aD1Grid = EvaluateGridD1(); - for (int i = myParams.Lower(); i <= myParams.Upper(); ++i) + NCollection_Array1 aD1Grid = EvaluateGridD1(theParams); + for (int i = 1; i <= aNb; ++i) { aResult.SetValue(i, aD1Grid.Value(i).D1); } } else if (theN == 2) { - NCollection_Array1 aD2Grid = EvaluateGridD2(); - for (int i = myParams.Lower(); i <= myParams.Upper(); ++i) + NCollection_Array1 aD2Grid = EvaluateGridD2(theParams); + for (int i = 1; i <= aNb; ++i) { aResult.SetValue(i, aD2Grid.Value(i).D2); } } else if (theN == 3) { - NCollection_Array1 aD3Grid = EvaluateGridD3(); - for (int i = myParams.Lower(); i <= myParams.Upper(); ++i) + NCollection_Array1 aD3Grid = EvaluateGridD3(theParams); + for (int i = 1; i <= aNb; ++i) { aResult.SetValue(i, aD3Grid.Value(i).D3); } @@ -148,9 +148,9 @@ NCollection_Array1 GeomGridEval_OtherCurve::EvaluateGridDN(int theN) con else { // For orders > 3, use adaptor DN method - for (int i = myParams.Lower(); i <= myParams.Upper(); ++i) + for (int i = theParams.Lower(); i <= theParams.Upper(); ++i) { - aResult.SetValue(i, myCurve.get().DN(myParams.Value(i), theN)); + aResult.SetValue(i - theParams.Lower() + 1, myCurve.get().DN(theParams.Value(i), theN)); } } return aResult; diff --git a/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_OtherCurve.hxx b/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_OtherCurve.hxx index e15a3d948d..6f89566e01 100644 --- a/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_OtherCurve.hxx +++ b/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_OtherCurve.hxx @@ -34,8 +34,7 @@ //! Usage: //! @code //! GeomGridEval_OtherCurve anEvaluator(myCurveAdaptor); -//! anEvaluator.SetParams(myParams); -//! NCollection_Array1 aGrid = anEvaluator.EvaluateGrid(); +//! NCollection_Array1 aGrid = anEvaluator.EvaluateGrid(myParams); //! @endcode class GeomGridEval_OtherCurve { @@ -55,50 +54,48 @@ public: GeomGridEval_OtherCurve(GeomGridEval_OtherCurve&&) = delete; GeomGridEval_OtherCurve& operator=(GeomGridEval_OtherCurve&&) = delete; - //! Set parameters for grid evaluation (by const reference). - //! @param theParams array of parameter values - Standard_EXPORT void SetParams(const TColStd_Array1OfReal& theParams); - - //! Set parameters for grid evaluation (by move). - //! @param theParams array of parameter values to move - void SetParams(NCollection_Array1&& theParams) { myParams = std::move(theParams); } - //! Returns the curve adaptor reference. const Adaptor3d_Curve& Curve() const { return myCurve.get(); } - //! Returns number of parameters. - int NbParams() const { return myParams.Size(); } - //! Evaluate all grid points. + //! @param theParams array of parameter values //! @return array of evaluated points (1-based indexing), - //! or empty array if curve is null or no parameters set - Standard_EXPORT NCollection_Array1 EvaluateGrid() const; + //! or empty array if no parameters + Standard_EXPORT NCollection_Array1 EvaluateGrid( + const TColStd_Array1OfReal& 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 curve is null or no parameters set - Standard_EXPORT NCollection_Array1 EvaluateGridD1() const; + //! or empty array if no parameters + Standard_EXPORT NCollection_Array1 EvaluateGridD1( + const TColStd_Array1OfReal& 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 curve is null or no parameters set - Standard_EXPORT NCollection_Array1 EvaluateGridD2() const; + //! or empty array if no parameters + Standard_EXPORT NCollection_Array1 EvaluateGridD2( + const TColStd_Array1OfReal& 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 curve is null or no parameters set - Standard_EXPORT NCollection_Array1 EvaluateGridD3() const; + //! or empty array if no parameters + Standard_EXPORT NCollection_Array1 EvaluateGridD3( + const TColStd_Array1OfReal& 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 EvaluateGridDN(int theN) const; + Standard_EXPORT NCollection_Array1 EvaluateGridDN(const TColStd_Array1OfReal& theParams, + int theN) const; private: std::reference_wrapper myCurve; - NCollection_Array1 myParams; }; #endif // _GeomGridEval_OtherCurve_HeaderFile diff --git a/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_OtherSurface.cxx b/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_OtherSurface.cxx index 89d50ebdc2..33c7cff1ba 100644 --- a/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_OtherSurface.cxx +++ b/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_OtherSurface.cxx @@ -15,46 +15,122 @@ //================================================================================================== -void GeomGridEval_OtherSurface::SetUVParams(const TColStd_Array1OfReal& theUParams, - const TColStd_Array1OfReal& theVParams) +void GeomGridEval_OtherSurface::evaluateD0(double theU, double theV, gp_Pnt& thePoint) const { - const int aNbU = theUParams.Size(); - const int aNbV = theVParams.Size(); - - myUParams.Resize(1, aNbU, false); - for (int i = 1; i <= aNbU; ++i) - { - myUParams.SetValue(i, theUParams.Value(theUParams.Lower() + i - 1)); - } - - myVParams.Resize(1, aNbV, false); - for (int j = 1; j <= aNbV; ++j) - { - myVParams.SetValue(j, theVParams.Value(theVParams.Lower() + j - 1)); - } + std::visit([theU, theV, &thePoint](const auto& theSurf) { theSurf->D0(theU, theV, thePoint); }, + mySurface); } //================================================================================================== -NCollection_Array2 GeomGridEval_OtherSurface::EvaluateGrid() const +void GeomGridEval_OtherSurface::evaluateD1(double theU, + double theV, + gp_Pnt& thePoint, + gp_Vec& theD1U, + gp_Vec& theD1V) const { - if (myUParams.IsEmpty() || myVParams.IsEmpty()) + std::visit([theU, theV, &thePoint, &theD1U, &theD1V]( + const auto& theSurf) { theSurf->D1(theU, theV, thePoint, theD1U, theD1V); }, + mySurface); +} + +//================================================================================================== + +void GeomGridEval_OtherSurface::evaluateD2(double theU, + double theV, + gp_Pnt& thePoint, + gp_Vec& theD1U, + gp_Vec& theD1V, + gp_Vec& theD2U, + gp_Vec& theD2V, + gp_Vec& theD2UV) const +{ + std::visit( + [theU, theV, &thePoint, &theD1U, &theD1V, &theD2U, &theD2V, &theD2UV](const auto& theSurf) { + theSurf->D2(theU, theV, thePoint, theD1U, theD1V, theD2U, theD2V, theD2UV); + }, + mySurface); +} + +//================================================================================================== + +void GeomGridEval_OtherSurface::evaluateD3(double theU, + double theV, + gp_Pnt& thePoint, + gp_Vec& theD1U, + gp_Vec& theD1V, + gp_Vec& theD2U, + gp_Vec& theD2V, + gp_Vec& theD2UV, + gp_Vec& theD3U, + gp_Vec& theD3V, + gp_Vec& theD3UUV, + gp_Vec& theD3UVV) const +{ + std::visit( + [theU, + theV, + &thePoint, + &theD1U, + &theD1V, + &theD2U, + &theD2V, + &theD2UV, + &theD3U, + &theD3V, + &theD3UUV, + &theD3UVV](const auto& theSurf) { + theSurf->D3(theU, + theV, + thePoint, + theD1U, + theD1V, + theD2U, + theD2V, + theD2UV, + theD3U, + theD3V, + theD3UUV, + theD3UVV); + }, + mySurface); +} + +//================================================================================================== + +gp_Vec GeomGridEval_OtherSurface::evaluateDN(double theU, double theV, int theNU, int theNV) const +{ + return std::visit( + [theU, theV, theNU, theNV](const auto& theSurf) -> gp_Vec { + return theSurf->DN(theU, theV, theNU, theNV); + }, + mySurface); +} + +//================================================================================================== + +NCollection_Array2 GeomGridEval_OtherSurface::EvaluateGrid( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams) const +{ + const int aNbU = theUParams.Size(); + const int aNbV = theVParams.Size(); + if (aNbU == 0 || aNbV == 0) { return NCollection_Array2(); } - const int aNbU = myUParams.Size(); - const int aNbV = myVParams.Size(); - NCollection_Array2 aResult(1, aNbU, 1, aNbV); for (int iU = 1; iU <= aNbU; ++iU) { - const double u = myUParams.Value(iU); + const double u = theUParams.Value(theUParams.Lower() + iU - 1); for (int iV = 1; iV <= aNbV; ++iV) { - const double v = myVParams.Value(iV); - aResult.SetValue(iU, iV, mySurface.get().Value(u, v)); + const double v = theVParams.Value(theVParams.Lower() + iV - 1); + gp_Pnt aPoint; + evaluateD0(u, v, aPoint); + aResult.SetValue(iU, iV, aPoint); } } @@ -63,27 +139,28 @@ NCollection_Array2 GeomGridEval_OtherSurface::EvaluateGrid() const //================================================================================================== -NCollection_Array2 GeomGridEval_OtherSurface::EvaluateGridD1() const +NCollection_Array2 GeomGridEval_OtherSurface::EvaluateGridD1( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams) const { - if (myUParams.IsEmpty() || myVParams.IsEmpty()) + const int aNbU = theUParams.Size(); + const int aNbV = theVParams.Size(); + if (aNbU == 0 || aNbV == 0) { return NCollection_Array2(); } - const int aNbU = myUParams.Size(); - const int aNbV = myVParams.Size(); - NCollection_Array2 aResult(1, aNbU, 1, aNbV); for (int iU = 1; iU <= aNbU; ++iU) { - const double u = myUParams.Value(iU); + const double u = theUParams.Value(theUParams.Lower() + iU - 1); for (int iV = 1; iV <= aNbV; ++iV) { - const double v = myVParams.Value(iV); + const double v = theVParams.Value(theVParams.Lower() + iV - 1); gp_Pnt aPoint; gp_Vec aD1U, aD1V; - mySurface.get().D1(u, v, aPoint, aD1U, aD1V); + evaluateD1(u, v, aPoint, aD1U, aD1V); aResult.ChangeValue(iU, iV) = {aPoint, aD1U, aD1V}; } } @@ -93,27 +170,28 @@ NCollection_Array2 GeomGridEval_OtherSurface::EvaluateGrid //================================================================================================== -NCollection_Array2 GeomGridEval_OtherSurface::EvaluateGridD2() const +NCollection_Array2 GeomGridEval_OtherSurface::EvaluateGridD2( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams) const { - if (myUParams.IsEmpty() || myVParams.IsEmpty()) + const int aNbU = theUParams.Size(); + const int aNbV = theVParams.Size(); + if (aNbU == 0 || aNbV == 0) { return NCollection_Array2(); } - const int aNbU = myUParams.Size(); - const int aNbV = myVParams.Size(); - NCollection_Array2 aResult(1, aNbU, 1, aNbV); for (int iU = 1; iU <= aNbU; ++iU) { - const double u = myUParams.Value(iU); + const double u = theUParams.Value(theUParams.Lower() + iU - 1); for (int iV = 1; iV <= aNbV; ++iV) { - const double v = myVParams.Value(iV); + const double v = theVParams.Value(theVParams.Lower() + iV - 1); gp_Pnt aPoint; gp_Vec aD1U, aD1V, aD2U, aD2V, aD2UV; - mySurface.get().D2(u, v, aPoint, aD1U, aD1V, aD2U, aD2V, aD2UV); + evaluateD2(u, v, aPoint, aD1U, aD1V, aD2U, aD2V, aD2UV); aResult.ChangeValue(iU, iV) = {aPoint, aD1U, aD1V, aD2U, aD2V, aD2UV}; } } @@ -123,27 +201,28 @@ NCollection_Array2 GeomGridEval_OtherSurface::EvaluateGrid //================================================================================================== -NCollection_Array2 GeomGridEval_OtherSurface::EvaluateGridD3() const +NCollection_Array2 GeomGridEval_OtherSurface::EvaluateGridD3( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams) const { - if (myUParams.IsEmpty() || myVParams.IsEmpty()) + const int aNbU = theUParams.Size(); + const int aNbV = theVParams.Size(); + if (aNbU == 0 || aNbV == 0) { return NCollection_Array2(); } - const int aNbU = myUParams.Size(); - const int aNbV = myVParams.Size(); - NCollection_Array2 aResult(1, aNbU, 1, aNbV); for (int iU = 1; iU <= aNbU; ++iU) { - const double u = myUParams.Value(iU); + const double u = theUParams.Value(theUParams.Lower() + iU - 1); for (int iV = 1; iV <= aNbV; ++iV) { - const double v = myVParams.Value(iV); + const double v = theVParams.Value(theVParams.Lower() + iV - 1); gp_Pnt aPoint; gp_Vec aD1U, aD1V, aD2U, aD2V, aD2UV, aD3U, aD3V, aD3UUV, aD3UVV; - mySurface.get().D3(u, v, aPoint, aD1U, aD1V, aD2U, aD2V, aD2UV, aD3U, aD3V, aD3UUV, aD3UVV); + evaluateD3(u, v, aPoint, aD1U, aD1V, aD2U, aD2V, aD2UV, aD3U, aD3V, aD3UUV, aD3UVV); aResult.ChangeValue(iU, iV) = {aPoint, aD1U, aD1V, aD2U, aD2V, aD2UV, aD3U, aD3V, aD3UUV, aD3UVV}; } @@ -154,29 +233,155 @@ NCollection_Array2 GeomGridEval_OtherSurface::EvaluateGrid //================================================================================================== -NCollection_Array2 GeomGridEval_OtherSurface::EvaluateGridDN(int theNU, int theNV) const +NCollection_Array2 GeomGridEval_OtherSurface::EvaluateGridDN( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams, + int theNU, + int theNV) const { - if (myUParams.IsEmpty() || myVParams.IsEmpty() || theNU < 0 || theNV < 0 || (theNU + theNV) < 1) + const int aNbU = theUParams.Size(); + const int aNbV = theVParams.Size(); + if (aNbU == 0 || aNbV == 0 || theNU < 0 || theNV < 0 || (theNU + theNV) < 1) { return NCollection_Array2(); } - const int aNbU = myUParams.Size(); - const int aNbV = myVParams.Size(); - NCollection_Array2 aResult(1, aNbU, 1, aNbV); - // Use adaptor DN method for all requested derivatives for (int iU = 1; iU <= aNbU; ++iU) { - const double u = myUParams.Value(iU); + const double u = theUParams.Value(theUParams.Lower() + iU - 1); for (int iV = 1; iV <= aNbV; ++iV) { - const double v = myVParams.Value(iV); - const gp_Vec aDN = mySurface.get().DN(u, v, theNU, theNV); + const double v = theVParams.Value(theVParams.Lower() + iV - 1); + const gp_Vec aDN = evaluateDN(u, v, theNU, theNV); aResult.SetValue(iU, iV, aDN); } } return aResult; } + +//================================================================================================== + +NCollection_Array1 GeomGridEval_OtherSurface::EvaluatePoints( + const NCollection_Array1& theUVPairs) const +{ + if (theUVPairs.IsEmpty()) + { + return NCollection_Array1(); + } + + const int aNbPoints = theUVPairs.Size(); + NCollection_Array1 aResult(1, aNbPoints); + + for (int i = 1; i <= aNbPoints; ++i) + { + const gp_Pnt2d& aUV = theUVPairs.Value(theUVPairs.Lower() + i - 1); + gp_Pnt aPoint; + evaluateD0(aUV.X(), aUV.Y(), aPoint); + aResult.SetValue(i, aPoint); + } + + return aResult; +} + +//================================================================================================== + +NCollection_Array1 GeomGridEval_OtherSurface::EvaluatePointsD1( + const NCollection_Array1& theUVPairs) const +{ + if (theUVPairs.IsEmpty()) + { + return NCollection_Array1(); + } + + const int aNbPoints = theUVPairs.Size(); + NCollection_Array1 aResult(1, aNbPoints); + + for (int i = 1; i <= aNbPoints; ++i) + { + const gp_Pnt2d& aUV = theUVPairs.Value(theUVPairs.Lower() + i - 1); + gp_Pnt aPoint; + gp_Vec aD1U, aD1V; + evaluateD1(aUV.X(), aUV.Y(), aPoint, aD1U, aD1V); + aResult.SetValue(i, {aPoint, aD1U, aD1V}); + } + + return aResult; +} + +//================================================================================================== + +NCollection_Array1 GeomGridEval_OtherSurface::EvaluatePointsD2( + const NCollection_Array1& theUVPairs) const +{ + if (theUVPairs.IsEmpty()) + { + return NCollection_Array1(); + } + + const int aNbPoints = theUVPairs.Size(); + NCollection_Array1 aResult(1, aNbPoints); + + for (int i = 1; i <= aNbPoints; ++i) + { + const gp_Pnt2d& aUV = theUVPairs.Value(theUVPairs.Lower() + i - 1); + gp_Pnt aPoint; + gp_Vec aD1U, aD1V, aD2U, aD2V, aD2UV; + evaluateD2(aUV.X(), aUV.Y(), aPoint, aD1U, aD1V, aD2U, aD2V, aD2UV); + aResult.SetValue(i, {aPoint, aD1U, aD1V, aD2U, aD2V, aD2UV}); + } + + return aResult; +} + +//================================================================================================== + +NCollection_Array1 GeomGridEval_OtherSurface::EvaluatePointsD3( + const NCollection_Array1& theUVPairs) const +{ + if (theUVPairs.IsEmpty()) + { + return NCollection_Array1(); + } + + const int aNbPoints = theUVPairs.Size(); + NCollection_Array1 aResult(1, aNbPoints); + + for (int i = 1; i <= aNbPoints; ++i) + { + const gp_Pnt2d& aUV = theUVPairs.Value(theUVPairs.Lower() + i - 1); + gp_Pnt aPoint; + gp_Vec aD1U, aD1V, aD2U, aD2V, aD2UV, aD3U, aD3V, aD3UUV, aD3UVV; + evaluateD3(aUV.X(), aUV.Y(), aPoint, aD1U, aD1V, aD2U, aD2V, aD2UV, aD3U, aD3V, aD3UUV, aD3UVV); + aResult.SetValue(i, {aPoint, aD1U, aD1V, aD2U, aD2V, aD2UV, aD3U, aD3V, aD3UUV, aD3UVV}); + } + + return aResult; +} + +//================================================================================================== + +NCollection_Array1 GeomGridEval_OtherSurface::EvaluatePointsDN( + const NCollection_Array1& theUVPairs, + int theNU, + int theNV) const +{ + if (theUVPairs.IsEmpty() || theNU < 0 || theNV < 0 || (theNU + theNV) < 1) + { + return NCollection_Array1(); + } + + const int aNbPoints = theUVPairs.Size(); + NCollection_Array1 aResult(1, aNbPoints); + + for (int i = 1; i <= aNbPoints; ++i) + { + const gp_Pnt2d& aUV = theUVPairs.Value(theUVPairs.Lower() + i - 1); + const gp_Vec aDN = evaluateDN(aUV.X(), aUV.Y(), theNU, theNV); + aResult.SetValue(i, aDN); + } + + return aResult; +} diff --git a/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_OtherSurface.hxx b/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_OtherSurface.hxx index 68da517ede..e50572f558 100644 --- a/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_OtherSurface.hxx +++ b/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_OtherSurface.hxx @@ -15,37 +15,47 @@ #define _GeomGridEval_OtherSurface_HeaderFile #include +#include #include +#include #include #include #include #include #include -#include +#include -//! @brief Fallback evaluator for unknown surface types. +//! @brief Fallback evaluator for any surface type. //! -//! Uses Adaptor3d_Surface::D0 for point-by-point evaluation. +//! Uses D0/D1/D2/D3/DN methods for point-by-point evaluation. Supports both +//! Adaptor3d_Surface (by pointer) and Handle(Geom_Surface) as input. //! This is the slowest evaluator but handles any surface type. //! -//! @note The surface adaptor reference must remain valid during the lifetime -//! of this evaluator. The evaluator does not take ownership. +//! @note When using adaptor pointer, the adaptor must remain valid +//! during the lifetime of this evaluator. //! //! Usage: //! @code -//! GeomGridEval_OtherSurface anEvaluator(mySurfaceAdaptor); -//! anEvaluator.SetUVParams(myUParams, myVParams); -//! NCollection_Array2 aGrid = anEvaluator.EvaluateGrid(); +//! GeomGridEval_OtherSurface anEvaluator(&mySurfaceAdaptor); +//! NCollection_Array2 aGrid = anEvaluator.EvaluateGrid(myUParams, myVParams); +//! NCollection_Array1 aPoints = anEvaluator.EvaluatePoints(myUVPairs); //! @endcode class GeomGridEval_OtherSurface { public: DEFINE_STANDARD_ALLOC - //! Constructor with surface adaptor reference. - //! @param theSurface reference to surface adaptor (must remain valid) - GeomGridEval_OtherSurface(const Adaptor3d_Surface& theSurface) + //! Constructor with surface adaptor pointer. + //! @param theSurface pointer to surface adaptor (must remain valid) + GeomGridEval_OtherSurface(const Adaptor3d_Surface* theSurface) + : mySurface(theSurface) + { + } + + //! Constructor with geometry handle. + //! @param theSurface handle to Geom_Surface + GeomGridEval_OtherSurface(const Handle(Geom_Surface)& theSurface) : mySurface(theSurface) { } @@ -56,53 +66,120 @@ public: GeomGridEval_OtherSurface(GeomGridEval_OtherSurface&&) = delete; GeomGridEval_OtherSurface& operator=(GeomGridEval_OtherSurface&&) = delete; - //! Set UV parameters from two 1D arrays. + //! Evaluate grid points at Cartesian product of U and V parameters. //! @param theUParams array of U parameter values //! @param theVParams array of V parameter values - Standard_EXPORT void SetUVParams(const TColStd_Array1OfReal& theUParams, - const TColStd_Array1OfReal& theVParams); + //! @return 2D array of evaluated points (1-based indexing) + Standard_EXPORT NCollection_Array2 EvaluateGrid( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams) const; - //! Returns the surface adaptor reference. - const Adaptor3d_Surface& Surface() const { return mySurface.get(); } + //! Evaluate grid points with first partial derivatives. + //! @param theUParams array of U parameter values + //! @param theVParams array of V parameter values + //! @return 2D array of SurfD1 (1-based indexing) + Standard_EXPORT NCollection_Array2 EvaluateGridD1( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams) const; - //! Returns number of U parameters. - int NbUParams() const { return myUParams.Size(); } + //! Evaluate grid points with first and second partial derivatives. + //! @param theUParams array of U parameter values + //! @param theVParams array of V parameter values + //! @return 2D array of SurfD2 (1-based indexing) + Standard_EXPORT NCollection_Array2 EvaluateGridD2( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams) const; - //! Returns number of V parameters. - int NbVParams() const { return myVParams.Size(); } + //! Evaluate grid points with derivatives up to third order. + //! @param theUParams array of U parameter values + //! @param theVParams array of V parameter values + //! @return 2D array of SurfD3 (1-based indexing) + Standard_EXPORT NCollection_Array2 EvaluateGridD3( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams) const; - //! Evaluate all grid points. - //! @return 2D array of evaluated points (1-based indexing), - //! or empty array if surface is null or no parameters set - Standard_EXPORT NCollection_Array2 EvaluateGrid() const; - - //! Evaluate all grid points with first partial derivatives. - //! @return 2D array of SurfD1 (1-based indexing), - //! or empty array if surface is null or no parameters set - Standard_EXPORT NCollection_Array2 EvaluateGridD1() const; - - //! Evaluate all grid points with first and second partial derivatives. - //! @return 2D array of SurfD2 (1-based indexing), - //! or empty array if surface is null or no parameters set - Standard_EXPORT NCollection_Array2 EvaluateGridD2() const; - - //! Evaluate all grid points with derivatives up to third order. - //! Uses Adaptor3d_Surface::D3 for evaluation. - //! @return 2D array of SurfD3 (1-based indexing), - //! or empty array if surface is null or no parameters set - Standard_EXPORT NCollection_Array2 EvaluateGridD3() const; - - //! Evaluate partial derivative d^(NU+NV)S/(dU^NU dV^NV) at all grid points. - //! Uses Adaptor3d_Surface::DN for evaluation. + //! Evaluate partial derivative at all grid points. + //! @param theUParams array of U parameter values + //! @param theVParams array of V parameter values //! @param theNU derivative order in U direction //! @param theNV derivative order in V direction //! @return 2D array of derivative vectors (1-based indexing) - Standard_EXPORT NCollection_Array2 EvaluateGridDN(int theNU, int theNV) const; + Standard_EXPORT NCollection_Array2 EvaluateGridDN(const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams, + int theNU, + int theNV) const; + + //! Evaluate points at arbitrary UV pairs. + //! @param theUVPairs array of UV coordinate pairs + //! @return 1D array of evaluated points (1-based indexing) + Standard_EXPORT NCollection_Array1 EvaluatePoints( + const NCollection_Array1& theUVPairs) const; + + //! Evaluate points with first partial derivatives. + //! @param theUVPairs array of UV coordinate pairs + //! @return 1D array of SurfD1 (1-based indexing) + Standard_EXPORT NCollection_Array1 EvaluatePointsD1( + const NCollection_Array1& theUVPairs) const; + + //! Evaluate points with first and second partial derivatives. + //! @param theUVPairs array of UV coordinate pairs + //! @return 1D array of SurfD2 (1-based indexing) + Standard_EXPORT NCollection_Array1 EvaluatePointsD2( + const NCollection_Array1& theUVPairs) const; + + //! Evaluate points with derivatives up to third order. + //! @param theUVPairs array of UV coordinate pairs + //! @return 1D array of SurfD3 (1-based indexing) + Standard_EXPORT NCollection_Array1 EvaluatePointsD3( + const NCollection_Array1& theUVPairs) const; + + //! Evaluate partial derivative at all UV pairs. + //! @param theUVPairs array of UV coordinate pairs + //! @param theNU derivative order in U direction + //! @param theNV derivative order in V direction + //! @return 1D array of derivative vectors (1-based indexing) + Standard_EXPORT NCollection_Array1 EvaluatePointsDN( + const NCollection_Array1& theUVPairs, + int theNU, + int theNV) const; private: - std::reference_wrapper mySurface; - NCollection_Array1 myUParams; - NCollection_Array1 myVParams; + //! Evaluate D0 at given UV parameters. + void evaluateD0(double theU, double theV, gp_Pnt& thePoint) const; + + //! Evaluate D1 at given UV parameters. + void evaluateD1(double theU, double theV, gp_Pnt& thePoint, gp_Vec& theD1U, gp_Vec& theD1V) const; + + //! Evaluate D2 at given UV parameters. + void evaluateD2(double theU, + double theV, + gp_Pnt& thePoint, + gp_Vec& theD1U, + gp_Vec& theD1V, + gp_Vec& theD2U, + gp_Vec& theD2V, + gp_Vec& theD2UV) const; + + //! Evaluate D3 at given UV parameters. + void evaluateD3(double theU, + double theV, + gp_Pnt& thePoint, + gp_Vec& theD1U, + gp_Vec& theD1V, + gp_Vec& theD2U, + gp_Vec& theD2V, + gp_Vec& theD2UV, + gp_Vec& theD3U, + gp_Vec& theD3V, + gp_Vec& theD3UUV, + gp_Vec& theD3UVV) const; + + //! Evaluate DN at given UV parameters. + gp_Vec evaluateDN(double theU, double theV, int theNU, int theNV) const; + +private: + //! Surface source: either adaptor pointer or geometry handle. + std::variant mySurface; }; #endif // _GeomGridEval_OtherSurface_HeaderFile diff --git a/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_Parabola.cxx b/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_Parabola.cxx index 1db12d30ee..04e752f541 100644 --- a/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_Parabola.cxx +++ b/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_Parabola.cxx @@ -19,26 +19,15 @@ //================================================================================================== -void GeomGridEval_Parabola::SetParams(const TColStd_Array1OfReal& theParams) +NCollection_Array1 GeomGridEval_Parabola::EvaluateGrid( + const TColStd_Array1OfReal& theParams) const { - const int aNb = theParams.Size(); - myParams.Resize(1, aNb, false); - for (int i = 1; i <= aNb; ++i) - { - myParams.SetValue(i, theParams.Value(theParams.Lower() + i - 1)); - } -} - -//================================================================================================== - -NCollection_Array1 GeomGridEval_Parabola::EvaluateGrid() const -{ - if (myGeom.IsNull() || myParams.IsEmpty()) + if (myGeom.IsNull() || theParams.IsEmpty()) { return NCollection_Array1(); } - const int aNb = myParams.Size(); + const int aNb = theParams.Size(); NCollection_Array1 aResult(1, aNb); const gp_Parab& aParab = myGeom->Parab(); @@ -59,14 +48,14 @@ NCollection_Array1 GeomGridEval_Parabola::EvaluateGrid() const const double aCoeff = 1.0 / (4.0 * aFocal); - for (int i = 1; i <= aNb; ++i) + for (int i = theParams.Lower(); i <= theParams.Upper(); ++i) { - const double u = myParams.Value(i); + const double u = theParams.Value(i); // P = Center + (u^2 / 4F) * XDir + u * YDir const double u2Term = u * u * aCoeff; - aResult.SetValue(i, + aResult.SetValue(i - theParams.Lower() + 1, gp_Pnt(aCX + u2Term * aXX + u * aYX, aCY + u2Term * aXY + u * aYY, aCZ + u2Term * aXZ + u * aYZ)); @@ -76,14 +65,15 @@ NCollection_Array1 GeomGridEval_Parabola::EvaluateGrid() const //================================================================================================== -NCollection_Array1 GeomGridEval_Parabola::EvaluateGridD1() const +NCollection_Array1 GeomGridEval_Parabola::EvaluateGridD1( + const TColStd_Array1OfReal& theParams) const { - if (myGeom.IsNull() || myParams.IsEmpty()) + if (myGeom.IsNull() || theParams.IsEmpty()) { return NCollection_Array1(); } - const int aNb = myParams.Size(); + const int aNb = theParams.Size(); NCollection_Array1 aResult(1, aNb); const gp_Parab& aParab = myGeom->Parab(); @@ -105,9 +95,9 @@ NCollection_Array1 GeomGridEval_Parabola::EvaluateGridD1( const double aCoeff = 1.0 / (4.0 * aFocal); const double aCoeff2 = 1.0 / (2.0 * aFocal); // Derivative of u^2/4F is 2u/4F = u/2F - for (int i = 1; i <= aNb; ++i) + for (int i = theParams.Lower(); i <= theParams.Upper(); ++i) { - const double u = myParams.Value(i); + const double u = theParams.Value(i); // P = Center + (u^2 / 4F) * XDir + u * YDir // D1 = (u / 2F) * XDir + YDir @@ -115,24 +105,26 @@ NCollection_Array1 GeomGridEval_Parabola::EvaluateGridD1( const double u2Term = u * u * aCoeff; const double d1Term = u * aCoeff2; - aResult.ChangeValue(i) = {gp_Pnt(aCX + u2Term * aXX + u * aYX, - aCY + u2Term * aXY + u * aYY, - aCZ + u2Term * aXZ + u * aYZ), - gp_Vec(d1Term * aXX + aYX, d1Term * aXY + aYY, d1Term * aXZ + aYZ)}; + aResult.ChangeValue(i - theParams.Lower() + + 1) = {gp_Pnt(aCX + u2Term * aXX + u * aYX, + aCY + u2Term * aXY + u * aYY, + aCZ + u2Term * aXZ + u * aYZ), + gp_Vec(d1Term * aXX + aYX, d1Term * aXY + aYY, d1Term * aXZ + aYZ)}; } return aResult; } //================================================================================================== -NCollection_Array1 GeomGridEval_Parabola::EvaluateGridD2() const +NCollection_Array1 GeomGridEval_Parabola::EvaluateGridD2( + const TColStd_Array1OfReal& theParams) const { - if (myGeom.IsNull() || myParams.IsEmpty()) + if (myGeom.IsNull() || theParams.IsEmpty()) { return NCollection_Array1(); } - const int aNb = myParams.Size(); + const int aNb = theParams.Size(); NCollection_Array1 aResult(1, aNb); const gp_Parab& aParab = myGeom->Parab(); @@ -158,9 +150,9 @@ NCollection_Array1 GeomGridEval_Parabola::EvaluateGridD2( // D2 is constant for parabola: (1/2F) * XDir const gp_Vec aD2(aCoeff3 * aXX, aCoeff3 * aXY, aCoeff3 * aXZ); - for (int i = 1; i <= aNb; ++i) + for (int i = theParams.Lower(); i <= theParams.Upper(); ++i) { - const double u = myParams.Value(i); + const double u = theParams.Value(i); // P = Center + (u^2 / 4F) * XDir + u * YDir // D1 = (u / 2F) * XDir + YDir @@ -169,25 +161,27 @@ NCollection_Array1 GeomGridEval_Parabola::EvaluateGridD2( const double u2Term = u * u * aCoeff; const double d1Term = u * aCoeff2; - aResult.ChangeValue(i) = {gp_Pnt(aCX + u2Term * aXX + u * aYX, - aCY + u2Term * aXY + u * aYY, - aCZ + u2Term * aXZ + u * aYZ), - gp_Vec(d1Term * aXX + aYX, d1Term * aXY + aYY, d1Term * aXZ + aYZ), - aD2}; + aResult.ChangeValue(i - theParams.Lower() + + 1) = {gp_Pnt(aCX + u2Term * aXX + u * aYX, + aCY + u2Term * aXY + u * aYY, + aCZ + u2Term * aXZ + u * aYZ), + gp_Vec(d1Term * aXX + aYX, d1Term * aXY + aYY, d1Term * aXZ + aYZ), + aD2}; } return aResult; } //================================================================================================== -NCollection_Array1 GeomGridEval_Parabola::EvaluateGridD3() const +NCollection_Array1 GeomGridEval_Parabola::EvaluateGridD3( + const TColStd_Array1OfReal& theParams) const { - if (myGeom.IsNull() || myParams.IsEmpty()) + if (myGeom.IsNull() || theParams.IsEmpty()) { return NCollection_Array1(); } - const int aNb = myParams.Size(); + const int aNb = theParams.Size(); NCollection_Array1 aResult(1, aNb); const gp_Parab& aParab = myGeom->Parab(); @@ -213,33 +207,36 @@ NCollection_Array1 GeomGridEval_Parabola::EvaluateGridD3( const gp_Vec aD2(aCoeff3 * aXX, aCoeff3 * aXY, aCoeff3 * aXZ); const gp_Vec aD3(0.0, 0.0, 0.0); // D3 is 0 - for (int i = 1; i <= aNb; ++i) + for (int i = theParams.Lower(); i <= theParams.Upper(); ++i) { - const double u = myParams.Value(i); + const double u = theParams.Value(i); const double u2Term = u * u * aCoeff; const double d1Term = u * aCoeff2; - aResult.ChangeValue(i) = {gp_Pnt(aCX + u2Term * aXX + u * aYX, - aCY + u2Term * aXY + u * aYY, - aCZ + u2Term * aXZ + u * aYZ), - gp_Vec(d1Term * aXX + aYX, d1Term * aXY + aYY, d1Term * aXZ + aYZ), - aD2, - aD3}; + aResult.ChangeValue(i - theParams.Lower() + + 1) = {gp_Pnt(aCX + u2Term * aXX + u * aYX, + aCY + u2Term * aXY + u * aYY, + aCZ + u2Term * aXZ + u * aYZ), + gp_Vec(d1Term * aXX + aYX, d1Term * aXY + aYY, d1Term * aXZ + aYZ), + aD2, + aD3}; } return aResult; } //================================================================================================== -NCollection_Array1 GeomGridEval_Parabola::EvaluateGridDN(int theN) const +NCollection_Array1 GeomGridEval_Parabola::EvaluateGridDN( + const TColStd_Array1OfReal& theParams, + int theN) const { - if (myGeom.IsNull() || myParams.IsEmpty() || theN < 1) + if (myGeom.IsNull() || theParams.IsEmpty() || theN < 1) { return NCollection_Array1(); } - const int aNb = myParams.Size(); + const int aNb = theParams.Size(); NCollection_Array1 aResult(1, aNb); const gp_Parab& aParab = myGeom->Parab(); @@ -259,11 +256,12 @@ NCollection_Array1 GeomGridEval_Parabola::EvaluateGridDN(int theN) const if (theN == 1) { // D1 = (u/2F) * X + Y (depends on u) - for (int i = 1; i <= aNb; ++i) + for (int i = theParams.Lower(); i <= theParams.Upper(); ++i) { - const double u = myParams.Value(i); + const double u = theParams.Value(i); const double d1Term = u * aCoeff2; - aResult.SetValue(i, gp_Vec(d1Term * aXX + aYX, d1Term * aXY + aYY, d1Term * aXZ + aYZ)); + aResult.SetValue(i - theParams.Lower() + 1, + gp_Vec(d1Term * aXX + aYX, d1Term * aXY + aYY, d1Term * aXZ + aYZ)); } } else if (theN == 2) diff --git a/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_Parabola.hxx b/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_Parabola.hxx index a55cf97ae9..0f568d4f41 100644 --- a/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_Parabola.hxx +++ b/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_Parabola.hxx @@ -29,8 +29,7 @@ //! Usage: //! @code //! GeomGridEval_Parabola anEvaluator(myGeomParabola); -//! anEvaluator.SetParams(myParams); -//! NCollection_Array1 aGrid = anEvaluator.EvaluateGrid(); +//! NCollection_Array1 aGrid = anEvaluator.EvaluateGrid(myParams); //! @endcode class GeomGridEval_Parabola { @@ -50,45 +49,47 @@ public: GeomGridEval_Parabola(GeomGridEval_Parabola&&) = delete; GeomGridEval_Parabola& operator=(GeomGridEval_Parabola&&) = delete; - //! Set parameter values. - //! @param theParams array of parameter values - Standard_EXPORT void SetParams(const TColStd_Array1OfReal& theParams); - //! Returns the geometry handle. const Handle(Geom_Parabola)& Geometry() const { return myGeom; } - //! Returns number of parameters. - int NbParams() const { return myParams.Size(); } - //! 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 set - Standard_EXPORT NCollection_Array1 EvaluateGrid() const; + //! or empty array if geometry is null or no parameters + Standard_EXPORT NCollection_Array1 EvaluateGrid( + const TColStd_Array1OfReal& 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 EvaluateGridD1() const; + Standard_EXPORT NCollection_Array1 EvaluateGridD1( + const TColStd_Array1OfReal& 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 EvaluateGridD2() const; + Standard_EXPORT NCollection_Array1 EvaluateGridD2( + const TColStd_Array1OfReal& 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 EvaluateGridD3() const; + Standard_EXPORT NCollection_Array1 EvaluateGridD3( + const TColStd_Array1OfReal& 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 EvaluateGridDN(int theN) const; + Standard_EXPORT NCollection_Array1 EvaluateGridDN(const TColStd_Array1OfReal& theParams, + int theN) const; private: - Handle(Geom_Parabola) myGeom; - NCollection_Array1 myParams; + Handle(Geom_Parabola) myGeom; }; #endif // _GeomGridEval_Parabola_HeaderFile diff --git a/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_Plane.hxx b/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_Plane.hxx index 775429031d..7465792b94 100644 --- a/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_Plane.hxx +++ b/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_Plane.hxx @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -30,8 +31,8 @@ //! Usage: //! @code //! GeomGridEval_Plane anEvaluator(myGeomPlane); -//! anEvaluator.SetUVParams(myUParams, myVParams); -//! NCollection_Array2 aGrid = anEvaluator.EvaluateGrid(); +//! NCollection_Array2 aGrid = anEvaluator.EvaluateGrid(myUParams, myVParams); +//! NCollection_Array1 aPoints = anEvaluator.EvaluatePoints(myUVPairs); //! @endcode class GeomGridEval_Plane { @@ -51,49 +52,23 @@ public: GeomGridEval_Plane(GeomGridEval_Plane&&) = delete; GeomGridEval_Plane& operator=(GeomGridEval_Plane&&) = delete; - //! Set UV parameters from two 1D arrays. - //! @param theUParams array of U parameter values - //! @param theVParams array of V parameter values - void SetUVParams(const TColStd_Array1OfReal& theUParams, const TColStd_Array1OfReal& theVParams) - { - const int aNbU = theUParams.Size(); - const int aNbV = theVParams.Size(); - - myUParams.Resize(1, aNbU, false); - for (int i = 1; i <= aNbU; ++i) - { - myUParams.SetValue(i, theUParams.Value(theUParams.Lower() + i - 1)); - } - - myVParams.Resize(1, aNbV, false); - for (int j = 1; j <= aNbV; ++j) - { - myVParams.SetValue(j, theVParams.Value(theVParams.Lower() + j - 1)); - } - } - //! Returns the geometry handle. const Handle(Geom_Plane)& Geometry() const { return myGeom; } - //! Returns number of U parameters. - int NbUParams() const { return myUParams.Size(); } - - //! Returns number of V parameters. - int NbVParams() const { return myVParams.Size(); } - - //! Evaluate all grid points. - //! @return 2D array of evaluated points (1-based indexing), - //! or empty array if geometry is null or no parameters set - NCollection_Array2 EvaluateGrid() const + //! Evaluate grid points at Cartesian product of U and V parameters. + //! @param theUParams array of U parameter values + //! @param theVParams array of V parameter values + //! @return 2D array of evaluated points (1-based indexing) + NCollection_Array2 EvaluateGrid(const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams) const { - if (myGeom.IsNull() || myUParams.IsEmpty() || myVParams.IsEmpty()) + const int aNbU = theUParams.Size(); + const int aNbV = theVParams.Size(); + if (myGeom.IsNull() || aNbU == 0 || aNbV == 0) { return NCollection_Array2(); } - const int aNbU = myUParams.Size(); - const int aNbV = myVParams.Size(); - NCollection_Array2 aResult(1, aNbU, 1, aNbV); // Extract plane data from geometry @@ -115,34 +90,35 @@ public: for (int iU = 1; iU <= aNbU; ++iU) { - const double u = myUParams.Value(iU); + const double u = theUParams.Value(theUParams.Lower() + iU - 1); const double uX = aLocX + u * aXX; const double uY = aLocY + u * aXY; const double uZ = aLocZ + u * aXZ; for (int iV = 1; iV <= aNbV; ++iV) { - const double v = myVParams.Value(iV); + const double v = theVParams.Value(theVParams.Lower() + iV - 1); aResult.SetValue(iU, iV, gp_Pnt(uX + v * aYX, uY + v * aYY, uZ + v * aYZ)); } } return aResult; } - //! Evaluate all grid points with first partial derivatives. - //! For a plane, D1U = XDir (constant), D1V = YDir (constant). - //! @return 2D array of SurfD1 (1-based indexing), - //! or empty array if geometry is null or no parameters set - NCollection_Array2 EvaluateGridD1() const + //! Evaluate grid points with first partial derivatives. + //! @param theUParams array of U parameter values + //! @param theVParams array of V parameter values + //! @return 2D array of SurfD1 (1-based indexing) + NCollection_Array2 EvaluateGridD1( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams) const { - if (myGeom.IsNull() || myUParams.IsEmpty() || myVParams.IsEmpty()) + const int aNbU = theUParams.Size(); + const int aNbV = theVParams.Size(); + if (myGeom.IsNull() || aNbU == 0 || aNbV == 0) { return NCollection_Array2(); } - const int aNbU = myUParams.Size(); - const int aNbV = myVParams.Size(); - NCollection_Array2 aResult(1, aNbU, 1, aNbV); const gp_Pln& aPln = myGeom->Pln(); @@ -166,14 +142,14 @@ public: for (int iU = 1; iU <= aNbU; ++iU) { - const double u = myUParams.Value(iU); + const double u = theUParams.Value(theUParams.Lower() + iU - 1); const double uX = aLocX + u * aXX; const double uY = aLocY + u * aXY; const double uZ = aLocZ + u * aXZ; for (int iV = 1; iV <= aNbV; ++iV) { - const double v = myVParams.Value(iV); + const double v = theVParams.Value(theVParams.Lower() + iV - 1); aResult.ChangeValue(iU, iV) = {gp_Pnt(uX + v * aYX, uY + v * aYY, uZ + v * aYZ), aD1U, aD1V}; } @@ -181,20 +157,21 @@ public: return aResult; } - //! Evaluate all grid points with first and second partial derivatives. - //! For a plane, all second derivatives are zero. - //! @return 2D array of SurfD2 (1-based indexing), - //! or empty array if geometry is null or no parameters set - NCollection_Array2 EvaluateGridD2() const + //! Evaluate grid points with first and second partial derivatives. + //! @param theUParams array of U parameter values + //! @param theVParams array of V parameter values + //! @return 2D array of SurfD2 (1-based indexing) + NCollection_Array2 EvaluateGridD2( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams) const { - if (myGeom.IsNull() || myUParams.IsEmpty() || myVParams.IsEmpty()) + const int aNbU = theUParams.Size(); + const int aNbV = theVParams.Size(); + if (myGeom.IsNull() || aNbU == 0 || aNbV == 0) { return NCollection_Array2(); } - const int aNbU = myUParams.Size(); - const int aNbV = myVParams.Size(); - NCollection_Array2 aResult(1, aNbU, 1, aNbV); const gp_Pln& aPln = myGeom->Pln(); @@ -218,14 +195,14 @@ public: for (int iU = 1; iU <= aNbU; ++iU) { - const double u = myUParams.Value(iU); + const double u = theUParams.Value(theUParams.Lower() + iU - 1); const double uX = aLocX + u * aXX; const double uY = aLocY + u * aXY; const double uZ = aLocZ + u * aXZ; for (int iV = 1; iV <= aNbV; ++iV) { - const double v = myVParams.Value(iV); + const double v = theVParams.Value(theVParams.Lower() + iV - 1); aResult.ChangeValue( iU, iV) = {gp_Pnt(uX + v * aYX, uY + v * aYY, uZ + v * aYZ), aD1U, aD1V, aZero, aZero, aZero}; @@ -234,20 +211,21 @@ public: return aResult; } - //! Evaluate all grid points with derivatives up to third order. - //! For a plane, all derivatives of order >= 2 are zero. - //! @return 2D array of SurfD3 (1-based indexing), - //! or empty array if geometry is null or no parameters set - NCollection_Array2 EvaluateGridD3() const + //! Evaluate grid points with derivatives up to third order. + //! @param theUParams array of U parameter values + //! @param theVParams array of V parameter values + //! @return 2D array of SurfD3 (1-based indexing) + NCollection_Array2 EvaluateGridD3( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams) const { - if (myGeom.IsNull() || myUParams.IsEmpty() || myVParams.IsEmpty()) + const int aNbU = theUParams.Size(); + const int aNbV = theVParams.Size(); + if (myGeom.IsNull() || aNbU == 0 || aNbV == 0) { return NCollection_Array2(); } - const int aNbU = myUParams.Size(); - const int aNbV = myVParams.Size(); - NCollection_Array2 aResult(1, aNbU, 1, aNbV); const gp_Pln& aPln = myGeom->Pln(); @@ -271,14 +249,14 @@ public: for (int iU = 1; iU <= aNbU; ++iU) { - const double u = myUParams.Value(iU); + const double u = theUParams.Value(theUParams.Lower() + iU - 1); const double uX = aLocX + u * aXX; const double uY = aLocY + u * aXY; const double uZ = aLocZ + u * aXZ; for (int iV = 1; iV <= aNbV; ++iV) { - const double v = myVParams.Value(iV); + const double v = theVParams.Value(theVParams.Lower() + iV - 1); aResult.ChangeValue(iU, iV) = {gp_Pnt(uX + v * aYX, uY + v * aYY, uZ + v * aYZ), aD1U, aD1V, @@ -295,21 +273,23 @@ public: } //! Evaluate partial derivative d^(NU+NV)S/(dU^NU dV^NV) at all grid points. - //! For a plane: D1U = XDir, D1V = YDir, all others = 0. + //! @param theUParams array of U parameter values + //! @param theVParams array of V parameter values //! @param theNU derivative order in U direction //! @param theNV derivative order in V direction //! @return 2D array of derivative vectors (1-based indexing) - NCollection_Array2 EvaluateGridDN(int theNU, int theNV) const + NCollection_Array2 EvaluateGridDN(const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams, + int theNU, + int theNV) const { - if (myGeom.IsNull() || myUParams.IsEmpty() || myVParams.IsEmpty() || theNU < 0 || theNV < 0 - || (theNU + theNV) < 1) + const int aNbU = theUParams.Size(); + const int aNbV = theVParams.Size(); + if (myGeom.IsNull() || aNbU == 0 || aNbV == 0 || theNU < 0 || theNV < 0 || (theNU + theNV) < 1) { return NCollection_Array2(); } - const int aNbU = myUParams.Size(); - const int aNbV = myVParams.Size(); - NCollection_Array2 aResult(1, aNbU, 1, aNbV); // For a plane, only D1U (1,0) and D1V (0,1) are non-zero @@ -339,10 +319,236 @@ public: return aResult; } + //! Evaluate points at arbitrary UV pairs. + //! @param theUVPairs array of UV coordinate pairs + //! @return 1D array of evaluated points (1-based indexing) + NCollection_Array1 EvaluatePoints(const NCollection_Array1& theUVPairs) const + { + if (myGeom.IsNull() || theUVPairs.IsEmpty()) + { + return NCollection_Array1(); + } + + const int aNbPoints = theUVPairs.Size(); + NCollection_Array1 aResult(1, aNbPoints); + + const gp_Pln& aPln = myGeom->Pln(); + const gp_Pnt& aLoc = aPln.Location(); + const gp_Dir& aXDir = aPln.Position().XDirection(); + const gp_Dir& aYDir = aPln.Position().YDirection(); + + const double aLocX = aLoc.X(); + const double aLocY = aLoc.Y(); + const double aLocZ = aLoc.Z(); + const double aXX = aXDir.X(); + const double aXY = aXDir.Y(); + const double aXZ = aXDir.Z(); + const double aYX = aYDir.X(); + const double aYY = aYDir.Y(); + const double aYZ = aYDir.Z(); + + for (int i = 1; i <= aNbPoints; ++i) + { + const gp_Pnt2d& aUV = theUVPairs.Value(theUVPairs.Lower() + i - 1); + const double u = aUV.X(); + const double v = aUV.Y(); + aResult.SetValue( + i, + gp_Pnt(aLocX + u * aXX + v * aYX, aLocY + u * aXY + v * aYY, aLocZ + u * aXZ + v * aYZ)); + } + return aResult; + } + + //! Evaluate points with first partial derivatives. + //! @param theUVPairs array of UV coordinate pairs + //! @return 1D array of SurfD1 (1-based indexing) + NCollection_Array1 EvaluatePointsD1( + const NCollection_Array1& theUVPairs) const + { + if (myGeom.IsNull() || theUVPairs.IsEmpty()) + { + return NCollection_Array1(); + } + + const int aNbPoints = theUVPairs.Size(); + NCollection_Array1 aResult(1, aNbPoints); + + const gp_Pln& aPln = myGeom->Pln(); + const gp_Pnt& aLoc = aPln.Location(); + const gp_Dir& aXDir = aPln.Position().XDirection(); + const gp_Dir& aYDir = aPln.Position().YDirection(); + + const double aLocX = aLoc.X(); + const double aLocY = aLoc.Y(); + const double aLocZ = aLoc.Z(); + const double aXX = aXDir.X(); + const double aXY = aXDir.Y(); + const double aXZ = aXDir.Z(); + const double aYX = aYDir.X(); + const double aYY = aYDir.Y(); + const double aYZ = aYDir.Z(); + + const gp_Vec aD1U(aXX, aXY, aXZ); + const gp_Vec aD1V(aYX, aYY, aYZ); + + for (int i = 1; i <= aNbPoints; ++i) + { + const gp_Pnt2d& aUV = theUVPairs.Value(theUVPairs.Lower() + i - 1); + const double u = aUV.X(); + const double v = aUV.Y(); + aResult.SetValue( + i, + {gp_Pnt(aLocX + u * aXX + v * aYX, aLocY + u * aXY + v * aYY, aLocZ + u * aXZ + v * aYZ), + aD1U, + aD1V}); + } + return aResult; + } + + //! Evaluate points with first and second partial derivatives. + //! @param theUVPairs array of UV coordinate pairs + //! @return 1D array of SurfD2 (1-based indexing) + NCollection_Array1 EvaluatePointsD2( + const NCollection_Array1& theUVPairs) const + { + if (myGeom.IsNull() || theUVPairs.IsEmpty()) + { + return NCollection_Array1(); + } + + const int aNbPoints = theUVPairs.Size(); + NCollection_Array1 aResult(1, aNbPoints); + + const gp_Pln& aPln = myGeom->Pln(); + const gp_Pnt& aLoc = aPln.Location(); + const gp_Dir& aXDir = aPln.Position().XDirection(); + const gp_Dir& aYDir = aPln.Position().YDirection(); + + const double aLocX = aLoc.X(); + const double aLocY = aLoc.Y(); + const double aLocZ = aLoc.Z(); + const double aXX = aXDir.X(); + const double aXY = aXDir.Y(); + const double aXZ = aXDir.Z(); + const double aYX = aYDir.X(); + const double aYY = aYDir.Y(); + const double aYZ = aYDir.Z(); + + const gp_Vec aD1U(aXX, aXY, aXZ); + const gp_Vec aD1V(aYX, aYY, aYZ); + const gp_Vec aZero(0, 0, 0); + + for (int i = 1; i <= aNbPoints; ++i) + { + const gp_Pnt2d& aUV = theUVPairs.Value(theUVPairs.Lower() + i - 1); + const double u = aUV.X(); + const double v = aUV.Y(); + aResult.SetValue( + i, + {gp_Pnt(aLocX + u * aXX + v * aYX, aLocY + u * aXY + v * aYY, aLocZ + u * aXZ + v * aYZ), + aD1U, + aD1V, + aZero, + aZero, + aZero}); + } + return aResult; + } + + //! Evaluate points with derivatives up to third order. + //! @param theUVPairs array of UV coordinate pairs + //! @return 1D array of SurfD3 (1-based indexing) + NCollection_Array1 EvaluatePointsD3( + const NCollection_Array1& theUVPairs) const + { + if (myGeom.IsNull() || theUVPairs.IsEmpty()) + { + return NCollection_Array1(); + } + + const int aNbPoints = theUVPairs.Size(); + NCollection_Array1 aResult(1, aNbPoints); + + const gp_Pln& aPln = myGeom->Pln(); + const gp_Pnt& aLoc = aPln.Location(); + const gp_Dir& aXDir = aPln.Position().XDirection(); + const gp_Dir& aYDir = aPln.Position().YDirection(); + + const double aLocX = aLoc.X(); + const double aLocY = aLoc.Y(); + const double aLocZ = aLoc.Z(); + const double aXX = aXDir.X(); + const double aXY = aXDir.Y(); + const double aXZ = aXDir.Z(); + const double aYX = aYDir.X(); + const double aYY = aYDir.Y(); + const double aYZ = aYDir.Z(); + + const gp_Vec aD1U(aXX, aXY, aXZ); + const gp_Vec aD1V(aYX, aYY, aYZ); + const gp_Vec aZero(0, 0, 0); + + for (int i = 1; i <= aNbPoints; ++i) + { + const gp_Pnt2d& aUV = theUVPairs.Value(theUVPairs.Lower() + i - 1); + const double u = aUV.X(); + const double v = aUV.Y(); + aResult.SetValue( + i, + {gp_Pnt(aLocX + u * aXX + v * aYX, aLocY + u * aXY + v * aYY, aLocZ + u * aXZ + v * aYZ), + aD1U, + aD1V, + aZero, + aZero, + aZero, + aZero, + aZero, + aZero, + aZero}); + } + return aResult; + } + + //! Evaluate partial derivative at all UV pairs. + //! @param theUVPairs array of UV coordinate pairs + //! @param theNU derivative order in U direction + //! @param theNV derivative order in V direction + //! @return 1D array of derivative vectors (1-based indexing) + NCollection_Array1 EvaluatePointsDN(const NCollection_Array1& theUVPairs, + int theNU, + int theNV) const + { + if (myGeom.IsNull() || theUVPairs.IsEmpty() || theNU < 0 || theNV < 0 || (theNU + theNV) < 1) + { + return NCollection_Array1(); + } + + const int aNbPoints = theUVPairs.Size(); + NCollection_Array1 aResult(1, aNbPoints); + + // For a plane, only D1U (1,0) and D1V (0,1) are non-zero + gp_Vec aDerivative(0, 0, 0); + + if (theNU == 1 && theNV == 0) + { + const gp_Dir& aXDir = myGeom->Pln().Position().XDirection(); + aDerivative = gp_Vec(aXDir.X(), aXDir.Y(), aXDir.Z()); + } + else if (theNU == 0 && theNV == 1) + { + const gp_Dir& aYDir = myGeom->Pln().Position().YDirection(); + aDerivative = gp_Vec(aYDir.X(), aYDir.Y(), aYDir.Z()); + } + + for (int i = 1; i <= aNbPoints; ++i) + { + aResult.SetValue(i, aDerivative); + } + return aResult; + } + private: - Handle(Geom_Plane) myGeom; - NCollection_Array1 myUParams; - NCollection_Array1 myVParams; + Handle(Geom_Plane) myGeom; }; #endif // _GeomGridEval_Plane_HeaderFile diff --git a/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_Sphere.cxx b/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_Sphere.cxx index aa1f10bc5c..dbcad405a6 100644 --- a/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_Sphere.cxx +++ b/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_Sphere.cxx @@ -19,560 +19,523 @@ //================================================================================================== -void GeomGridEval_Sphere::SetUVParams(const TColStd_Array1OfReal& theUParams, - const TColStd_Array1OfReal& theVParams) +GeomGridEval_Sphere::Data GeomGridEval_Sphere::extractData() const { - const int aNbU = theUParams.Size(); - const int aNbV = theVParams.Size(); + const gp_Sphere& aSph = myGeom->Sphere(); + const gp_Pnt& aCenter = aSph.Location(); + const gp_Dir& aXDir = aSph.Position().XDirection(); + const gp_Dir& aYDir = aSph.Position().YDirection(); + const gp_Dir& aZDir = aSph.Position().Direction(); - myUParams.Resize(1, aNbU, false); - for (int i = 1; i <= aNbU; ++i) - { - myUParams.SetValue(i, theUParams.Value(theUParams.Lower() + i - 1)); - } - - myVParams.Resize(1, aNbV, false); - for (int j = 1; j <= aNbV; ++j) - { - myVParams.SetValue(j, theVParams.Value(theVParams.Lower() + j - 1)); - } + return {aCenter.X(), + aCenter.Y(), + aCenter.Z(), + aXDir.X(), + aXDir.Y(), + aXDir.Z(), + aYDir.X(), + aYDir.Y(), + aYDir.Z(), + aZDir.X(), + aZDir.Y(), + aZDir.Z(), + aSph.Radius()}; } //================================================================================================== -NCollection_Array2 GeomGridEval_Sphere::EvaluateGrid() const +GeomGridEval_Sphere::UContext GeomGridEval_Sphere::computeUContext(const Data& theData, double theU) { - if (myGeom.IsNull() || myUParams.IsEmpty() || myVParams.IsEmpty()) + const double cosU = std::cos(theU); + const double sinU = std::sin(theU); + + // DirU = cosU*XDir + sinU*YDir (horizontal direction at angle U) + // dDirU = -sinU*XDir + cosU*YDir (derivative of DirU w.r.t. U) + return {cosU, + sinU, + cosU * theData.XX + sinU * theData.YX, + cosU * theData.XY + sinU * theData.YY, + cosU * theData.XZ + sinU * theData.YZ, + -sinU * theData.XX + cosU * theData.YX, + -sinU * theData.XY + cosU * theData.YY, + -sinU * theData.XZ + cosU * theData.YZ}; +} + +//================================================================================================== + +gp_Pnt GeomGridEval_Sphere::computeD0(const Data& theData, const UContext& theUCtx, double theV) +{ + const double cosV = std::cos(theV); + const double sinV = std::sin(theV); + + // P = Center + R * (cosV * DirU + sinV * ZDir) + const double RcosV = theData.Radius * cosV; + const double RsinV = theData.Radius * sinV; + + return gp_Pnt(theData.CX + RcosV * theUCtx.dirUX + RsinV * theData.ZX, + theData.CY + RcosV * theUCtx.dirUY + RsinV * theData.ZY, + theData.CZ + RcosV * theUCtx.dirUZ + RsinV * theData.ZZ); +} + +//================================================================================================== + +GeomGridEval::SurfD1 GeomGridEval_Sphere::computeD1(const Data& theData, + const UContext& theUCtx, + double theV) +{ + const double cosV = std::cos(theV); + const double sinV = std::sin(theV); + + const double RcosV = theData.Radius * cosV; + const double RsinV = theData.Radius * sinV; + + // D1U = R * cosV * dDirU + // D1V = R * (-sinV * DirU + cosV * ZDir) + return {gp_Pnt(theData.CX + RcosV * theUCtx.dirUX + RsinV * theData.ZX, + theData.CY + RcosV * theUCtx.dirUY + RsinV * theData.ZY, + theData.CZ + RcosV * theUCtx.dirUZ + RsinV * theData.ZZ), + gp_Vec(RcosV * theUCtx.dDirUX, RcosV * theUCtx.dDirUY, RcosV * theUCtx.dDirUZ), + gp_Vec(-RsinV * theUCtx.dirUX + RcosV * theData.ZX, + -RsinV * theUCtx.dirUY + RcosV * theData.ZY, + -RsinV * theUCtx.dirUZ + RcosV * theData.ZZ)}; +} + +//================================================================================================== + +GeomGridEval::SurfD2 GeomGridEval_Sphere::computeD2(const Data& theData, + const UContext& theUCtx, + double theV) +{ + const double cosV = std::cos(theV); + const double sinV = std::sin(theV); + + const double RcosV = theData.Radius * cosV; + const double RsinV = theData.Radius * sinV; + + // D2U = R * cosV * (-DirU) = -R * cosV * DirU + // D2V = R * (-cosV * DirU - sinV * ZDir) = -(P - Center) = -relP + // D2UV = d/dV(D1U) = d/dV(R * cosV * dDirU) = -R * sinV * dDirU + return {gp_Pnt(theData.CX + RcosV * theUCtx.dirUX + RsinV * theData.ZX, + theData.CY + RcosV * theUCtx.dirUY + RsinV * theData.ZY, + theData.CZ + RcosV * theUCtx.dirUZ + RsinV * theData.ZZ), + gp_Vec(RcosV * theUCtx.dDirUX, RcosV * theUCtx.dDirUY, RcosV * theUCtx.dDirUZ), + gp_Vec(-RsinV * theUCtx.dirUX + RcosV * theData.ZX, + -RsinV * theUCtx.dirUY + RcosV * theData.ZY, + -RsinV * theUCtx.dirUZ + RcosV * theData.ZZ), + gp_Vec(-RcosV * theUCtx.dirUX, -RcosV * theUCtx.dirUY, -RcosV * theUCtx.dirUZ), + gp_Vec(-RcosV * theUCtx.dirUX - RsinV * theData.ZX, + -RcosV * theUCtx.dirUY - RsinV * theData.ZY, + -RcosV * theUCtx.dirUZ - RsinV * theData.ZZ), + gp_Vec(-RsinV * theUCtx.dDirUX, -RsinV * theUCtx.dDirUY, -RsinV * theUCtx.dDirUZ)}; +} + +//================================================================================================== + +GeomGridEval::SurfD3 GeomGridEval_Sphere::computeD3(const Data& theData, + const UContext& theUCtx, + double theV) +{ + const double cosV = std::cos(theV); + const double sinV = std::sin(theV); + + const double RcosV = theData.Radius * cosV; + const double RsinV = theData.Radius * sinV; + + // D3U = R * cosV * dDirU = D1U + // D3V = R * (sinV * DirU - cosV * ZDir) = -D1V + // D3UUV = d/dV(D2U) = d/dV(-R * cosV * DirU) = R * sinV * DirU + // D3UVV = d/dV(D2UV) = d/dV(-R * sinV * dDirU) = -R * cosV * dDirU + return {gp_Pnt(theData.CX + RcosV * theUCtx.dirUX + RsinV * theData.ZX, + theData.CY + RcosV * theUCtx.dirUY + RsinV * theData.ZY, + theData.CZ + RcosV * theUCtx.dirUZ + RsinV * theData.ZZ), + gp_Vec(RcosV * theUCtx.dDirUX, RcosV * theUCtx.dDirUY, RcosV * theUCtx.dDirUZ), + gp_Vec(-RsinV * theUCtx.dirUX + RcosV * theData.ZX, + -RsinV * theUCtx.dirUY + RcosV * theData.ZY, + -RsinV * theUCtx.dirUZ + RcosV * theData.ZZ), + gp_Vec(-RcosV * theUCtx.dirUX, -RcosV * theUCtx.dirUY, -RcosV * theUCtx.dirUZ), + gp_Vec(-RcosV * theUCtx.dirUX - RsinV * theData.ZX, + -RcosV * theUCtx.dirUY - RsinV * theData.ZY, + -RcosV * theUCtx.dirUZ - RsinV * theData.ZZ), + gp_Vec(-RsinV * theUCtx.dDirUX, -RsinV * theUCtx.dDirUY, -RsinV * theUCtx.dDirUZ), + gp_Vec(-RcosV * theUCtx.dDirUX, -RcosV * theUCtx.dDirUY, -RcosV * theUCtx.dDirUZ), + gp_Vec(RsinV * theUCtx.dirUX - RcosV * theData.ZX, + RsinV * theUCtx.dirUY - RcosV * theData.ZY, + RsinV * theUCtx.dirUZ - RcosV * theData.ZZ), + gp_Vec(RsinV * theUCtx.dirUX, RsinV * theUCtx.dirUY, RsinV * theUCtx.dirUZ), + gp_Vec(-RcosV * theUCtx.dDirUX, -RcosV * theUCtx.dDirUY, -RcosV * theUCtx.dDirUZ)}; +} + +//================================================================================================== + +gp_Vec GeomGridEval_Sphere::computeDN(const Data& theData, + const UContext& theUCtx, + double theV, + int theNU, + int theNV) +{ + const double cosV = std::cos(theV); + const double sinV = std::sin(theV); + + // Cyclic phases for U and V (period 4) + const int aPhaseU = theNU % 4; + const int aPhaseV = theNV % 4; + + // U-phase coefficients: d^n/du^n of cosU and sinU + // n=0: cosU, sinU -> DirU + // n=1: -sinU, cosU -> dDirU + // n=2: -cosU, -sinU -> -DirU + // n=3: sinU, -cosU -> -dDirU + double dirX, dirY, dirZ; + switch (aPhaseU) + { + case 0: + dirX = theUCtx.dirUX; + dirY = theUCtx.dirUY; + dirZ = theUCtx.dirUZ; + break; + case 1: + dirX = theUCtx.dDirUX; + dirY = theUCtx.dDirUY; + dirZ = theUCtx.dDirUZ; + break; + case 2: + dirX = -theUCtx.dirUX; + dirY = -theUCtx.dirUY; + dirZ = -theUCtx.dirUZ; + break; + case 3: + dirX = -theUCtx.dDirUX; + dirY = -theUCtx.dDirUY; + dirZ = -theUCtx.dDirUZ; + break; + default: + dirX = 0.0; + dirY = 0.0; + dirZ = 0.0; + break; + } + + // V-phase coefficients for XY term (cosV) and Z term (sinV) + double aCoeffVXY, aCoeffVZ; + switch (aPhaseV) + { + case 0: + aCoeffVXY = cosV; + aCoeffVZ = sinV; + break; + case 1: + aCoeffVXY = -sinV; + aCoeffVZ = cosV; + break; + case 2: + aCoeffVXY = -cosV; + aCoeffVZ = -sinV; + break; + case 3: + aCoeffVXY = sinV; + aCoeffVZ = -cosV; + break; + default: + aCoeffVXY = 0.0; + aCoeffVZ = 0.0; + break; + } + + // Z contribution only if NU == 0 (no U derivative on Z term) + double aZTermX = 0.0, aZTermY = 0.0, aZTermZ = 0.0; + if (theNU == 0) + { + aZTermX = aCoeffVZ * theData.ZX; + aZTermY = aCoeffVZ * theData.ZY; + aZTermZ = aCoeffVZ * theData.ZZ; + } + + return gp_Vec(theData.Radius * (aCoeffVXY * dirX + aZTermX), + theData.Radius * (aCoeffVXY * dirY + aZTermY), + theData.Radius * (aCoeffVXY * dirZ + aZTermZ)); +} + +//================================================================================================== + +NCollection_Array2 GeomGridEval_Sphere::EvaluateGrid( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams) const +{ + if (myGeom.IsNull() || theUParams.IsEmpty() || theVParams.IsEmpty()) { return NCollection_Array2(); } - const int aNbU = myUParams.Size(); - const int aNbV = myVParams.Size(); + const Data aData = extractData(); + const int aNbU = theUParams.Length(); + const int aNbV = theVParams.Length(); NCollection_Array2 aResult(1, aNbU, 1, aNbV); - // Extract sphere data from geometry - const gp_Sphere& aSph = myGeom->Sphere(); - const gp_Pnt& aCenter = aSph.Location(); - const gp_Dir& aXDir = aSph.Position().XDirection(); - const gp_Dir& aYDir = aSph.Position().YDirection(); - const gp_Dir& aZDir = aSph.Position().Direction(); - const double aRadius = aSph.Radius(); - - // Pre-extract coordinates for performance - const double aCX = aCenter.X(); - const double aCY = aCenter.Y(); - const double aCZ = aCenter.Z(); - const double aXX = aXDir.X(); - const double aXY = aXDir.Y(); - const double aXZ = aXDir.Z(); - const double aYX = aYDir.X(); - const double aYY = aYDir.Y(); - const double aYZ = aYDir.Z(); - const double aZX = aZDir.X(); - const double aZY = aZDir.Y(); - const double aZZ = aZDir.Z(); - - // Pre-compute V-dependent values (sin/cos of latitude) - NCollection_Array1 aCosV(1, aNbV); - NCollection_Array1 aSinV(1, aNbV); - for (int iV = 1; iV <= aNbV; ++iV) - { - const double v = myVParams.Value(iV); - aCosV.SetValue(iV, std::cos(v)); - aSinV.SetValue(iV, std::sin(v)); - } - for (int iU = 1; iU <= aNbU; ++iU) { - const double u = myUParams.Value(iU); - const double cosU = std::cos(u); - const double sinU = std::sin(u); + const double aU = theUParams.Value(theUParams.Lower() + iU - 1); + const UContext aUCtx = computeUContext(aData, aU); for (int iV = 1; iV <= aNbV; ++iV) { - const double cosV = aCosV.Value(iV); - const double sinV = aSinV.Value(iV); - - // P = Center + R * (cosV*cosU*XDir + cosV*sinU*YDir + sinV*ZDir) - const double coeff1 = aRadius * cosV * cosU; - const double coeff2 = aRadius * cosV * sinU; - const double coeff3 = aRadius * sinV; - - aResult.SetValue(iU, - iV, - gp_Pnt(aCX + coeff1 * aXX + coeff2 * aYX + coeff3 * aZX, - aCY + coeff1 * aXY + coeff2 * aYY + coeff3 * aZY, - aCZ + coeff1 * aXZ + coeff2 * aYZ + coeff3 * aZZ)); + const double aV = theVParams.Value(theVParams.Lower() + iV - 1); + aResult.SetValue(iU, iV, computeD0(aData, aUCtx, aV)); } } + return aResult; } //================================================================================================== -NCollection_Array2 GeomGridEval_Sphere::EvaluateGridD1() const +NCollection_Array2 GeomGridEval_Sphere::EvaluateGridD1( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams) const { - if (myGeom.IsNull() || myUParams.IsEmpty() || myVParams.IsEmpty()) + if (myGeom.IsNull() || theUParams.IsEmpty() || theVParams.IsEmpty()) { return NCollection_Array2(); } - const int aNbU = myUParams.Size(); - const int aNbV = myVParams.Size(); + const Data aData = extractData(); + const int aNbU = theUParams.Length(); + const int aNbV = theVParams.Length(); NCollection_Array2 aResult(1, aNbU, 1, aNbV); - const gp_Sphere& aSph = myGeom->Sphere(); - const gp_Pnt& aCenter = aSph.Location(); - const gp_Dir& aXDir = aSph.Position().XDirection(); - const gp_Dir& aYDir = aSph.Position().YDirection(); - const gp_Dir& aZDir = aSph.Position().Direction(); - const double aRadius = aSph.Radius(); - - const double aCX = aCenter.X(); - const double aCY = aCenter.Y(); - const double aCZ = aCenter.Z(); - const double aXX = aXDir.X(); - const double aXY = aXDir.Y(); - const double aXZ = aXDir.Z(); - const double aYX = aYDir.X(); - const double aYY = aYDir.Y(); - const double aYZ = aYDir.Z(); - const double aZX = aZDir.X(); - const double aZY = aZDir.Y(); - const double aZZ = aZDir.Z(); - - // Pre-compute V-dependent values - NCollection_Array1 aCosV(1, aNbV); - NCollection_Array1 aSinV(1, aNbV); - for (int iV = 1; iV <= aNbV; ++iV) - { - const double v = myVParams.Value(iV); - aCosV.SetValue(iV, std::cos(v)); - aSinV.SetValue(iV, std::sin(v)); - } - for (int iU = 1; iU <= aNbU; ++iU) { - const double u = myUParams.Value(iU); - const double cosU = std::cos(u); - const double sinU = std::sin(u); + const double aU = theUParams.Value(theUParams.Lower() + iU - 1); + const UContext aUCtx = computeUContext(aData, aU); for (int iV = 1; iV <= aNbV; ++iV) { - const double cosV = aCosV.Value(iV); - const double sinV = aSinV.Value(iV); - - // P = Center + R * (cosV*cosU*XDir + cosV*sinU*YDir + sinV*ZDir) - const double coeff1 = aRadius * cosV * cosU; - const double coeff2 = aRadius * cosV * sinU; - const double coeff3 = aRadius * sinV; - - // D1U = R * cosV * (-sinU*XDir + cosU*YDir) - const double dU1 = aRadius * cosV * (-sinU); - const double dU2 = aRadius * cosV * cosU; - - // D1V = R * (-sinV*cosU*XDir - sinV*sinU*YDir + cosV*ZDir) - const double dV1 = aRadius * (-sinV) * cosU; - const double dV2 = aRadius * (-sinV) * sinU; - const double dV3 = aRadius * cosV; - - aResult.ChangeValue(iU, iV) = { - gp_Pnt(aCX + coeff1 * aXX + coeff2 * aYX + coeff3 * aZX, - aCY + coeff1 * aXY + coeff2 * aYY + coeff3 * aZY, - aCZ + coeff1 * aXZ + coeff2 * aYZ + coeff3 * aZZ), - gp_Vec(dU1 * aXX + dU2 * aYX, dU1 * aXY + dU2 * aYY, dU1 * aXZ + dU2 * aYZ), - gp_Vec(dV1 * aXX + dV2 * aYX + dV3 * aZX, - dV1 * aXY + dV2 * aYY + dV3 * aZY, - dV1 * aXZ + dV2 * aYZ + dV3 * aZZ)}; + const double aV = theVParams.Value(theVParams.Lower() + iV - 1); + aResult.SetValue(iU, iV, computeD1(aData, aUCtx, aV)); } } + return aResult; } //================================================================================================== -NCollection_Array2 GeomGridEval_Sphere::EvaluateGridD2() const +NCollection_Array2 GeomGridEval_Sphere::EvaluateGridD2( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams) const { - if (myGeom.IsNull() || myUParams.IsEmpty() || myVParams.IsEmpty()) + if (myGeom.IsNull() || theUParams.IsEmpty() || theVParams.IsEmpty()) { return NCollection_Array2(); } - const int aNbU = myUParams.Size(); - const int aNbV = myVParams.Size(); + const Data aData = extractData(); + const int aNbU = theUParams.Length(); + const int aNbV = theVParams.Length(); NCollection_Array2 aResult(1, aNbU, 1, aNbV); - const gp_Sphere& aSph = myGeom->Sphere(); - const gp_Pnt& aCenter = aSph.Location(); - const gp_Dir& aXDir = aSph.Position().XDirection(); - const gp_Dir& aYDir = aSph.Position().YDirection(); - const gp_Dir& aZDir = aSph.Position().Direction(); - const double aRadius = aSph.Radius(); - - const double aCX = aCenter.X(); - const double aCY = aCenter.Y(); - const double aCZ = aCenter.Z(); - const double aXX = aXDir.X(); - const double aXY = aXDir.Y(); - const double aXZ = aXDir.Z(); - const double aYX = aYDir.X(); - const double aYY = aYDir.Y(); - const double aYZ = aYDir.Z(); - const double aZX = aZDir.X(); - const double aZY = aZDir.Y(); - const double aZZ = aZDir.Z(); - - // Pre-compute V-dependent values - NCollection_Array1 aCosV(1, aNbV); - NCollection_Array1 aSinV(1, aNbV); - for (int iV = 1; iV <= aNbV; ++iV) - { - const double v = myVParams.Value(iV); - aCosV.SetValue(iV, std::cos(v)); - aSinV.SetValue(iV, std::sin(v)); - } - for (int iU = 1; iU <= aNbU; ++iU) { - const double u = myUParams.Value(iU); - const double cosU = std::cos(u); - const double sinU = std::sin(u); + const double aU = theUParams.Value(theUParams.Lower() + iU - 1); + const UContext aUCtx = computeUContext(aData, aU); for (int iV = 1; iV <= aNbV; ++iV) { - const double cosV = aCosV.Value(iV); - const double sinV = aSinV.Value(iV); - - // P = Center + R * (cosV*cosU*XDir + cosV*sinU*YDir + sinV*ZDir) - const double coeff1 = aRadius * cosV * cosU; - const double coeff2 = aRadius * cosV * sinU; - const double coeff3 = aRadius * sinV; - - // D1U = R * cosV * (-sinU*XDir + cosU*YDir) - const double dU1 = aRadius * cosV * (-sinU); - const double dU2 = aRadius * cosV * cosU; - - // D1V = R * (-sinV*cosU*XDir - sinV*sinU*YDir + cosV*ZDir) - const double dV1 = aRadius * (-sinV) * cosU; - const double dV2 = aRadius * (-sinV) * sinU; - const double dV3 = aRadius * cosV; - - // D2U = R * cosV * (-cosU*XDir - sinU*YDir) - const double d2U1 = aRadius * cosV * (-cosU); - const double d2U2 = aRadius * cosV * (-sinU); - - // D2V = R * (-cosV*cosU*XDir - cosV*sinU*YDir - sinV*ZDir) = -P (relative to center) - const double d2V1 = -coeff1; - const double d2V2 = -coeff2; - const double d2V3 = -coeff3; - - // D2UV = R * (-sinV) * (-sinU*XDir + cosU*YDir) = sinV * R * (sinU*XDir - cosU*YDir) - const double d2UV1 = aRadius * sinV * sinU; - const double d2UV2 = aRadius * sinV * (-cosU); - - aResult.ChangeValue(iU, iV) = { - gp_Pnt(aCX + coeff1 * aXX + coeff2 * aYX + coeff3 * aZX, - aCY + coeff1 * aXY + coeff2 * aYY + coeff3 * aZY, - aCZ + coeff1 * aXZ + coeff2 * aYZ + coeff3 * aZZ), - gp_Vec(dU1 * aXX + dU2 * aYX, dU1 * aXY + dU2 * aYY, dU1 * aXZ + dU2 * aYZ), - gp_Vec(dV1 * aXX + dV2 * aYX + dV3 * aZX, - dV1 * aXY + dV2 * aYY + dV3 * aZY, - dV1 * aXZ + dV2 * aYZ + dV3 * aZZ), - gp_Vec(d2U1 * aXX + d2U2 * aYX, d2U1 * aXY + d2U2 * aYY, d2U1 * aXZ + d2U2 * aYZ), - gp_Vec(d2V1 * aXX + d2V2 * aYX + d2V3 * aZX, - d2V1 * aXY + d2V2 * aYY + d2V3 * aZY, - d2V1 * aXZ + d2V2 * aYZ + d2V3 * aZZ), - gp_Vec(d2UV1 * aXX + d2UV2 * aYX, d2UV1 * aXY + d2UV2 * aYY, d2UV1 * aXZ + d2UV2 * aYZ)}; + const double aV = theVParams.Value(theVParams.Lower() + iV - 1); + aResult.SetValue(iU, iV, computeD2(aData, aUCtx, aV)); } } + return aResult; } //================================================================================================== -NCollection_Array2 GeomGridEval_Sphere::EvaluateGridD3() const +NCollection_Array2 GeomGridEval_Sphere::EvaluateGridD3( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams) const { - if (myGeom.IsNull() || myUParams.IsEmpty() || myVParams.IsEmpty()) + if (myGeom.IsNull() || theUParams.IsEmpty() || theVParams.IsEmpty()) { return NCollection_Array2(); } - const int aNbU = myUParams.Size(); - const int aNbV = myVParams.Size(); + const Data aData = extractData(); + const int aNbU = theUParams.Length(); + const int aNbV = theVParams.Length(); NCollection_Array2 aResult(1, aNbU, 1, aNbV); - const gp_Sphere& aSph = myGeom->Sphere(); - const gp_Pnt& aCenter = aSph.Location(); - const gp_Dir& aXDir = aSph.Position().XDirection(); - const gp_Dir& aYDir = aSph.Position().YDirection(); - const gp_Dir& aZDir = aSph.Position().Direction(); - const double aRadius = aSph.Radius(); - - const double aCX = aCenter.X(); - const double aCY = aCenter.Y(); - const double aCZ = aCenter.Z(); - const double aXX = aXDir.X(); - const double aXY = aXDir.Y(); - const double aXZ = aXDir.Z(); - const double aYX = aYDir.X(); - const double aYY = aYDir.Y(); - const double aYZ = aYDir.Z(); - const double aZX = aZDir.X(); - const double aZY = aZDir.Y(); - const double aZZ = aZDir.Z(); - - // Pre-compute V-dependent values - NCollection_Array1 aCosV(1, aNbV); - NCollection_Array1 aSinV(1, aNbV); - for (int iV = 1; iV <= aNbV; ++iV) - { - const double v = myVParams.Value(iV); - aCosV.SetValue(iV, std::cos(v)); - aSinV.SetValue(iV, std::sin(v)); - } - for (int iU = 1; iU <= aNbU; ++iU) { - const double u = myUParams.Value(iU); - const double cosU = std::cos(u); - const double sinU = std::sin(u); + const double aU = theUParams.Value(theUParams.Lower() + iU - 1); + const UContext aUCtx = computeUContext(aData, aU); for (int iV = 1; iV <= aNbV; ++iV) { - const double cosV = aCosV.Value(iV); - const double sinV = aSinV.Value(iV); - - // R1 = R * cosV, R2 = R * sinV - const double R1 = aRadius * cosV; - const double R2 = aRadius * sinV; - - // A1 = R1 * cosU, A2 = R1 * sinU, A3 = R2 * cosU, A4 = R2 * sinU - const double A1 = R1 * cosU; - const double A2 = R1 * sinU; - const double A3 = R2 * cosU; - const double A4 = R2 * sinU; - - // Som1 = A1*X + A2*Y (R*cosV*Vxy where Vxy = cosU*X + sinU*Y) - const double Som1X = A1 * aXX + A2 * aYX; - const double Som1Y = A1 * aXY + A2 * aYY; - const double Som1Z = A1 * aXZ + A2 * aYZ; - - // Som3 = A3*X + A4*Y (R*sinV*Vxy) - const double Som3X = A3 * aXX + A4 * aYX; - const double Som3Y = A3 * aXY + A4 * aYY; - const double Som3Z = A3 * aXZ + A4 * aYZ; - - // Dif1 = A2*X - A1*Y = R1*sinU*X - R1*cosU*Y = -R*cosV*DVxy - // where DVxy = -sinU*X + cosU*Y - // So actual DVxy component is: -Dif1/R1 gives sinU*X - cosU*Y... let's use direct formula - // D1U = R*cosV*(-sinU*X + cosU*Y) = -A2*X + A1*Y... wait that's wrong sign - // Actually: D1U = R*cosV*DVxy where DVxy = -sinU*X + cosU*Y - // So D1U = R1*(-sinU)*X + R1*cosU*Y = -A2*X/cosU*sinU... simpler: - // D1U_coeff1 = R1*(-sinU), D1U_coeff2 = R1*cosU - const double dU1 = -A2; // R1*(-sinU) = -R*cosV*sinU - const double dU2 = A1; // R1*cosU = R*cosV*cosU - - // D1V = R*(-sinV*cosU*X - sinV*sinU*Y + cosV*Z) = -A3*X - A4*Y + R1*Z - const double dV1 = -A3; - const double dV2 = -A4; - const double dV3 = R1; - - // D2U = -R*cosV*Vxy = -Som1 - const double d2UX = -Som1X; - const double d2UY = -Som1Y; - const double d2UZ = -Som1Z; - - // D2V = -R*cosV*Vxy - R*sinV*Z = -Som1 - R2*Z - const double d2VX = -Som1X - R2 * aZX; - const double d2VY = -Som1Y - R2 * aZY; - const double d2VZ = -Som1Z - R2 * aZZ; - - // D2UV = -R*sinV*DVxy = R*sinV*(sinU*X - cosU*Y) = A4*X - A3*Y - const double d2UVX = A4 * aXX - A3 * aYX; - const double d2UVY = A4 * aXY - A3 * aYY; - const double d2UVZ = A4 * aXZ - A3 * aYZ; - - // D3U = -D1U (Vuuu = -Vu) - const double d3UX = -dU1 * aXX - dU2 * aYX; - const double d3UY = -dU1 * aXY - dU2 * aYY; - const double d3UZ = -dU1 * aXZ - dU2 * aYZ; - - // D3V = -D1V (Vvvv = -Vv) - const double d3VX = -dV1 * aXX - dV2 * aYX - dV3 * aZX; - const double d3VY = -dV1 * aXY - dV2 * aYY - dV3 * aZY; - const double d3VZ = -dV1 * aXZ - dV2 * aYZ - dV3 * aZZ; - - // D3UUV = R*sinV*Vxy = Som3 - const double d3UUVX = Som3X; - const double d3UUVY = Som3Y; - const double d3UUVZ = Som3Z; - - // D3UVV = -D1U (Vuvv = -Vu = Vuuu) - const double d3UVVX = d3UX; - const double d3UVVY = d3UY; - const double d3UVVZ = d3UZ; - - aResult.ChangeValue(iU, iV) = { - gp_Pnt(aCX + Som1X + R2 * aZX, aCY + Som1Y + R2 * aZY, aCZ + Som1Z + R2 * aZZ), - gp_Vec(dU1 * aXX + dU2 * aYX, dU1 * aXY + dU2 * aYY, dU1 * aXZ + dU2 * aYZ), - gp_Vec(dV1 * aXX + dV2 * aYX + dV3 * aZX, - dV1 * aXY + dV2 * aYY + dV3 * aZY, - dV1 * aXZ + dV2 * aYZ + dV3 * aZZ), - gp_Vec(d2UX, d2UY, d2UZ), - gp_Vec(d2VX, d2VY, d2VZ), - gp_Vec(d2UVX, d2UVY, d2UVZ), - gp_Vec(d3UX, d3UY, d3UZ), - gp_Vec(d3VX, d3VY, d3VZ), - gp_Vec(d3UUVX, d3UUVY, d3UUVZ), - gp_Vec(d3UVVX, d3UVVY, d3UVVZ)}; + const double aV = theVParams.Value(theVParams.Lower() + iV - 1); + aResult.SetValue(iU, iV, computeD3(aData, aUCtx, aV)); } } + return aResult; } //================================================================================================== -NCollection_Array2 GeomGridEval_Sphere::EvaluateGridDN(int theNU, int theNV) const +NCollection_Array2 GeomGridEval_Sphere::EvaluateGridDN( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams, + int theNU, + int theNV) const { - if (myGeom.IsNull() || myUParams.IsEmpty() || myVParams.IsEmpty() || theNU < 0 || theNV < 0 + if (myGeom.IsNull() || theUParams.IsEmpty() || theVParams.IsEmpty() || theNU < 0 || theNV < 0 || (theNU + theNV) < 1) { return NCollection_Array2(); } - const int aNbU = myUParams.Size(); - const int aNbV = myVParams.Size(); + const Data aData = extractData(); + const int aNbU = theUParams.Length(); + const int aNbV = theVParams.Length(); NCollection_Array2 aResult(1, aNbU, 1, aNbV); - // For sphere, derivatives are cyclic with period 4 in both U and V - // P(u,v) = C + R * (cosV*cosU*X + cosV*sinU*Y + sinV*Z) - // The derivative pattern depends on (NU % 4, NV % 4) - - const gp_Sphere& aSph = myGeom->Sphere(); - const gp_Dir& aXDir = aSph.Position().XDirection(); - const gp_Dir& aYDir = aSph.Position().YDirection(); - const gp_Dir& aZDir = aSph.Position().Direction(); - const double aRadius = aSph.Radius(); - - const double aXX = aXDir.X(); - const double aXY = aXDir.Y(); - const double aXZ = aXDir.Z(); - const double aYX = aYDir.X(); - const double aYY = aYDir.Y(); - const double aYZ = aYDir.Z(); - const double aZX = aZDir.X(); - const double aZY = aZDir.Y(); - const double aZZ = aZDir.Z(); - - // Cyclic phases for U and V (period 4) - // Phase 0: cos, Phase 1: -sin, Phase 2: -cos, Phase 3: sin - const int aPhaseU = theNU % 4; - const int aPhaseV = theNV % 4; - - // Pre-compute V-dependent values - NCollection_Array1 aCosV(1, aNbV); - NCollection_Array1 aSinV(1, aNbV); - for (int iV = 1; iV <= aNbV; ++iV) - { - const double v = myVParams.Value(iV); - aCosV.SetValue(iV, std::cos(v)); - aSinV.SetValue(iV, std::sin(v)); - } - for (int iU = 1; iU <= aNbU; ++iU) { - const double u = myUParams.Value(iU); - const double cosU = std::cos(u); - const double sinU = std::sin(u); - - // U-phase coefficients for X and Y directions - double aCoeffUX, aCoeffUY; - switch (aPhaseU) - { - case 0: - aCoeffUX = cosU; - aCoeffUY = sinU; - break; - case 1: - aCoeffUX = -sinU; - aCoeffUY = cosU; - break; - case 2: - aCoeffUX = -cosU; - aCoeffUY = -sinU; - break; - case 3: - aCoeffUX = sinU; - aCoeffUY = -cosU; - break; - default: - aCoeffUX = 0.0; - aCoeffUY = 0.0; - break; - } + const double aU = theUParams.Value(theUParams.Lower() + iU - 1); + const UContext aUCtx = computeUContext(aData, aU); for (int iV = 1; iV <= aNbV; ++iV) { - const double cosV = aCosV.Value(iV); - const double sinV = aSinV.Value(iV); - - // V-phase coefficients: determines contribution of XY-plane vs Z-axis - // d^nv/dv^nv (cosV * XYterm + sinV * Z) - double aCoeffVXY, aCoeffVZ; - switch (aPhaseV) - { - case 0: - aCoeffVXY = cosV; - aCoeffVZ = sinV; - break; - case 1: - aCoeffVXY = -sinV; - aCoeffVZ = cosV; - break; - case 2: - aCoeffVXY = -cosV; - aCoeffVZ = -sinV; - break; - case 3: - aCoeffVXY = sinV; - aCoeffVZ = -cosV; - break; - default: - aCoeffVXY = 0.0; - aCoeffVZ = 0.0; - break; - } - - // Combined coefficient: R * VCoeff_XY * (UCoeffX * X + UCoeffY * Y) + R * VCoeff_Z * Z - // But Z only appears in the V-derivative chain, not U - // For pure U derivatives (NV=0): Z term is sinV (phase 0 for V) - // For mixed derivatives: need both components - - const double aXYTerm = aCoeffVXY * (aCoeffUX * aXX + aCoeffUY * aYX); - const double aXYTermY = aCoeffVXY * (aCoeffUX * aXY + aCoeffUY * aYY); - const double aXYTermZ = aCoeffVXY * (aCoeffUX * aXZ + aCoeffUY * aYZ); - - // Z contribution only if NU == 0 (no U derivative on Z term) - double aZTerm = 0.0, aZTermY = 0.0, aZTermZ = 0.0; - if (theNU == 0) - { - aZTerm = aCoeffVZ * aZX; - aZTermY = aCoeffVZ * aZY; - aZTermZ = aCoeffVZ * aZZ; - } - - aResult.SetValue(iU, - iV, - gp_Vec(aRadius * (aXYTerm + aZTerm), - aRadius * (aXYTermY + aZTermY), - aRadius * (aXYTermZ + aZTermZ))); + const double aV = theVParams.Value(theVParams.Lower() + iV - 1); + aResult.SetValue(iU, iV, computeDN(aData, aUCtx, aV, theNU, theNV)); } } + + return aResult; +} + +//================================================================================================== + +NCollection_Array1 GeomGridEval_Sphere::EvaluatePoints( + const NCollection_Array1& theUVPairs) const +{ + if (myGeom.IsNull() || theUVPairs.IsEmpty()) + { + return NCollection_Array1(); + } + + const Data aData = extractData(); + const int aNb = theUVPairs.Length(); + NCollection_Array1 aResult(1, aNb); + + for (int i = 1; i <= aNb; ++i) + { + const gp_Pnt2d& aUV = theUVPairs.Value(theUVPairs.Lower() + i - 1); + const UContext aUCtx = computeUContext(aData, aUV.X()); + aResult.SetValue(i, computeD0(aData, aUCtx, aUV.Y())); + } + + return aResult; +} + +//================================================================================================== + +NCollection_Array1 GeomGridEval_Sphere::EvaluatePointsD1( + const NCollection_Array1& theUVPairs) const +{ + if (myGeom.IsNull() || theUVPairs.IsEmpty()) + { + return NCollection_Array1(); + } + + const Data aData = extractData(); + const int aNb = theUVPairs.Length(); + NCollection_Array1 aResult(1, aNb); + + for (int i = 1; i <= aNb; ++i) + { + const gp_Pnt2d& aUV = theUVPairs.Value(theUVPairs.Lower() + i - 1); + const UContext aUCtx = computeUContext(aData, aUV.X()); + aResult.SetValue(i, computeD1(aData, aUCtx, aUV.Y())); + } + + return aResult; +} + +//================================================================================================== + +NCollection_Array1 GeomGridEval_Sphere::EvaluatePointsD2( + const NCollection_Array1& theUVPairs) const +{ + if (myGeom.IsNull() || theUVPairs.IsEmpty()) + { + return NCollection_Array1(); + } + + const Data aData = extractData(); + const int aNb = theUVPairs.Length(); + NCollection_Array1 aResult(1, aNb); + + for (int i = 1; i <= aNb; ++i) + { + const gp_Pnt2d& aUV = theUVPairs.Value(theUVPairs.Lower() + i - 1); + const UContext aUCtx = computeUContext(aData, aUV.X()); + aResult.SetValue(i, computeD2(aData, aUCtx, aUV.Y())); + } + + return aResult; +} + +//================================================================================================== + +NCollection_Array1 GeomGridEval_Sphere::EvaluatePointsD3( + const NCollection_Array1& theUVPairs) const +{ + if (myGeom.IsNull() || theUVPairs.IsEmpty()) + { + return NCollection_Array1(); + } + + const Data aData = extractData(); + const int aNb = theUVPairs.Length(); + NCollection_Array1 aResult(1, aNb); + + for (int i = 1; i <= aNb; ++i) + { + const gp_Pnt2d& aUV = theUVPairs.Value(theUVPairs.Lower() + i - 1); + const UContext aUCtx = computeUContext(aData, aUV.X()); + aResult.SetValue(i, computeD3(aData, aUCtx, aUV.Y())); + } + + return aResult; +} + +//================================================================================================== + +NCollection_Array1 GeomGridEval_Sphere::EvaluatePointsDN( + const NCollection_Array1& theUVPairs, + int theNU, + int theNV) const +{ + if (myGeom.IsNull() || theUVPairs.IsEmpty() || theNU < 0 || theNV < 0 || (theNU + theNV) < 1) + { + return NCollection_Array1(); + } + + const Data aData = extractData(); + const int aNb = theUVPairs.Length(); + NCollection_Array1 aResult(1, aNb); + + for (int i = 1; i <= aNb; ++i) + { + const gp_Pnt2d& aUV = theUVPairs.Value(theUVPairs.Lower() + i - 1); + const UContext aUCtx = computeUContext(aData, aUV.X()); + aResult.SetValue(i, computeDN(aData, aUCtx, aUV.Y(), theNU, theNV)); + } + return aResult; } diff --git a/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_Sphere.hxx b/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_Sphere.hxx index d1d13cf7c1..52716e65c1 100644 --- a/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_Sphere.hxx +++ b/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_Sphere.hxx @@ -16,6 +16,7 @@ #include #include +#include #include #include #include @@ -32,8 +33,8 @@ //! Usage: //! @code //! GeomGridEval_Sphere anEvaluator(myGeomSphere); -//! anEvaluator.SetUVParams(myUParams, myVParams); -//! NCollection_Array2 aGrid = anEvaluator.EvaluateGrid(); +//! NCollection_Array2 aGrid = anEvaluator.EvaluateGrid(myUParams, myVParams); +//! NCollection_Array1 aPoints = anEvaluator.EvaluatePoints(myUVPairs); //! @endcode class GeomGridEval_Sphere { @@ -53,53 +54,133 @@ public: GeomGridEval_Sphere(GeomGridEval_Sphere&&) = delete; GeomGridEval_Sphere& operator=(GeomGridEval_Sphere&&) = delete; - //! Set UV parameters from two 1D arrays. - //! @param theUParams array of U parameter values (longitude) - //! @param theVParams array of V parameter values (latitude) - Standard_EXPORT void SetUVParams(const TColStd_Array1OfReal& theUParams, - const TColStd_Array1OfReal& theVParams); - //! Returns the geometry handle. const Handle(Geom_SphericalSurface)& Geometry() const { return myGeom; } - //! Returns number of U parameters. - int NbUParams() const { return myUParams.Size(); } + //! Evaluate grid points at Cartesian product of U and V parameters. + //! @param theUParams array of U parameter values (longitude) + //! @param theVParams array of V parameter values (latitude) + //! @return 2D array of evaluated points (1-based indexing) + Standard_EXPORT NCollection_Array2 EvaluateGrid( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams) const; - //! Returns number of V parameters. - int NbVParams() const { return myVParams.Size(); } + //! Evaluate grid points with first partial derivatives. + //! @param theUParams array of U parameter values (longitude) + //! @param theVParams array of V parameter values (latitude) + //! @return 2D array of SurfD1 (1-based indexing) + Standard_EXPORT NCollection_Array2 EvaluateGridD1( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams) const; - //! Evaluate all grid points. - //! @return 2D array of evaluated points (1-based indexing), - //! or empty array if geometry is null or no parameters set - Standard_EXPORT NCollection_Array2 EvaluateGrid() const; + //! Evaluate grid points with first and second partial derivatives. + //! @param theUParams array of U parameter values (longitude) + //! @param theVParams array of V parameter values (latitude) + //! @return 2D array of SurfD2 (1-based indexing) + Standard_EXPORT NCollection_Array2 EvaluateGridD2( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams) const; - //! Evaluate all grid points with first partial derivatives. - //! @return 2D array of SurfD1 (1-based indexing), - //! or empty array if geometry is null or no parameters set - Standard_EXPORT NCollection_Array2 EvaluateGridD1() const; - - //! Evaluate all grid points with first and second partial derivatives. - //! @return 2D array of SurfD2 (1-based indexing), - //! or empty array if geometry is null or no parameters set - Standard_EXPORT NCollection_Array2 EvaluateGridD2() const; - - //! Evaluate all grid points with derivatives up to third order. - //! @return 2D array of SurfD3 (1-based indexing), - //! or empty array if geometry is null or no parameters set - Standard_EXPORT NCollection_Array2 EvaluateGridD3() const; + //! Evaluate grid points with derivatives up to third order. + //! @param theUParams array of U parameter values (longitude) + //! @param theVParams array of V parameter values (latitude) + //! @return 2D array of SurfD3 (1-based indexing) + Standard_EXPORT NCollection_Array2 EvaluateGridD3( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams) const; //! Evaluate partial derivative d^(NU+NV)S/(dU^NU dV^NV) at all grid points. //! For orders 1-3, reuses EvaluateGridD1/D2/D3. //! For orders > 3, uses geometry DN method. + //! @param theUParams array of U parameter values (longitude) + //! @param theVParams array of V parameter values (latitude) //! @param theNU derivative order in U direction //! @param theNV derivative order in V direction //! @return 2D array of derivative vectors (1-based indexing) - Standard_EXPORT NCollection_Array2 EvaluateGridDN(int theNU, int theNV) const; + Standard_EXPORT NCollection_Array2 EvaluateGridDN(const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams, + int theNU, + int theNV) const; + + //! Evaluate points at arbitrary UV pairs. + //! @param theUVPairs array of UV coordinate pairs + //! @return 1D array of evaluated points (1-based indexing) + Standard_EXPORT NCollection_Array1 EvaluatePoints( + const NCollection_Array1& theUVPairs) const; + + //! Evaluate points with first partial derivatives. + //! @param theUVPairs array of UV coordinate pairs + //! @return 1D array of SurfD1 (1-based indexing) + Standard_EXPORT NCollection_Array1 EvaluatePointsD1( + const NCollection_Array1& theUVPairs) const; + + //! Evaluate points with first and second partial derivatives. + //! @param theUVPairs array of UV coordinate pairs + //! @return 1D array of SurfD2 (1-based indexing) + Standard_EXPORT NCollection_Array1 EvaluatePointsD2( + const NCollection_Array1& theUVPairs) const; + + //! Evaluate points with derivatives up to third order. + //! @param theUVPairs array of UV coordinate pairs + //! @return 1D array of SurfD3 (1-based indexing) + Standard_EXPORT NCollection_Array1 EvaluatePointsD3( + const NCollection_Array1& theUVPairs) const; + + //! Evaluate partial derivative at all UV pairs. + //! @param theUVPairs array of UV coordinate pairs + //! @param theNU derivative order in U direction + //! @param theNV derivative order in V direction + //! @return 1D array of derivative vectors (1-based indexing) + Standard_EXPORT NCollection_Array1 EvaluatePointsDN( + const NCollection_Array1& theUVPairs, + int theNU, + int theNV) const; private: + //! Pre-extracted sphere data for efficient evaluation. + struct Data + { + double CX, CY, CZ; //!< Center coordinates + double XX, XY, XZ; //!< XDir coordinates + double YX, YY, YZ; //!< YDir coordinates + double ZX, ZY, ZZ; //!< ZDir coordinates + double Radius; + }; + + //! Pre-computed U-dependent values for optimized grid evaluation. + struct UContext + { + double cosU, sinU; + double dirUX, dirUY, dirUZ; //!< DirU = cosU*XDir + sinU*YDir + double dDirUX, dDirUY, dDirUZ; //!< DerivDirU = -sinU*XDir + cosU*YDir + }; + + //! Extract sphere data for evaluation. + Data extractData() const; + + //! Pre-compute U-dependent values. + static UContext computeUContext(const Data& theData, double theU); + + //! Compute point with pre-computed U context. + static gp_Pnt computeD0(const Data& theData, const UContext& theUCtx, double theV); + + //! Compute point with D1 with pre-computed U context. + static GeomGridEval::SurfD1 computeD1(const Data& theData, const UContext& theUCtx, double theV); + + //! Compute point with D2 with pre-computed U context. + static GeomGridEval::SurfD2 computeD2(const Data& theData, const UContext& theUCtx, double theV); + + //! Compute point with D3 with pre-computed U context. + static GeomGridEval::SurfD3 computeD3(const Data& theData, const UContext& theUCtx, double theV); + + //! Compute DN with pre-computed U context. + static gp_Vec computeDN(const Data& theData, + const UContext& theUCtx, + double theV, + int theNU, + int theNV); + Handle(Geom_SphericalSurface) myGeom; - NCollection_Array1 myUParams; - NCollection_Array1 myVParams; }; #endif // _GeomGridEval_Sphere_HeaderFile diff --git a/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_Surface.cxx b/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_Surface.cxx index a6cde651e3..14bb294352 100644 --- a/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_Surface.cxx +++ b/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_Surface.cxx @@ -168,7 +168,7 @@ void GeomGridEval_Surface::Initialize(const Adaptor3d_Surface& theSurface) // No geometry available - use adaptor directly as fallback mySurfaceType = theSurface.GetType(); - myEvaluator.emplace(theSurface); + myEvaluator.emplace(&theSurface); return; } @@ -203,7 +203,7 @@ void GeomGridEval_Surface::Initialize(const Adaptor3d_Surface& theSurface) // No geometry available - use adaptor directly as fallback mySurfaceType = theSurface.GetType(); - myEvaluator.emplace(theSurface); + myEvaluator.emplace(&theSurface); return; } @@ -227,7 +227,7 @@ void GeomGridEval_Surface::Initialize(const Adaptor3d_Surface& theSurface) // Surface() is null and not elementary - use adaptor directly mySurfaceType = theSurface.GetType(); - myEvaluator.emplace(theSurface); + myEvaluator.emplace(&theSurface); return; } @@ -241,7 +241,7 @@ void GeomGridEval_Surface::Initialize(const Adaptor3d_Surface& theSurface) // No way to get Geom_Surface - use adaptor directly as fallback mySurfaceType = theSurface.GetType(); - myEvaluator.emplace(theSurface); + myEvaluator.emplace(&theSurface); } //================================================================================================== @@ -310,31 +310,14 @@ void GeomGridEval_Surface::Initialize(const Handle(Geom_Surface)& theSurface) } else { - // Unknown surface type - set uninitialized - // All known Geom_Surface types are handled above - myEvaluator.emplace(); + // Unknown surface type - use OtherSurface fallback mySurfaceType = GeomAbs_OtherSurface; + myEvaluator.emplace(aBasisSurf); } } //================================================================================================== -void GeomGridEval_Surface::SetUVParams(const TColStd_Array1OfReal& theUParams, - const TColStd_Array1OfReal& theVParams) -{ - std::visit( - [&theUParams, &theVParams](auto& theEval) { - using T = std::decay_t; - if constexpr (!std::is_same_v) - { - theEval.SetUVParams(theUParams, theVParams); - } - }, - myEvaluator); -} - -//================================================================================================== - bool GeomGridEval_Surface::IsInitialized() const { return !std::holds_alternative(myEvaluator); @@ -342,48 +325,12 @@ bool GeomGridEval_Surface::IsInitialized() const //================================================================================================== -int GeomGridEval_Surface::NbUParams() const -{ - return std::visit( - [](const auto& theEval) -> int { - using T = std::decay_t; - if constexpr (std::is_same_v) - { - return 0; - } - else - { - return theEval.NbUParams(); - } - }, - myEvaluator); -} - -//================================================================================================== - -int GeomGridEval_Surface::NbVParams() const -{ - return std::visit( - [](const auto& theEval) -> int { - using T = std::decay_t; - if constexpr (std::is_same_v) - { - return 0; - } - else - { - return theEval.NbVParams(); - } - }, - myEvaluator); -} - -//================================================================================================== - -NCollection_Array2 GeomGridEval_Surface::EvaluateGrid() const +NCollection_Array2 GeomGridEval_Surface::EvaluateGrid( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams) const { NCollection_Array2 aResult = std::visit( - [](const auto& theEval) -> NCollection_Array2 { + [&theUParams, &theVParams](const auto& theEval) -> NCollection_Array2 { using T = std::decay_t; if constexpr (std::is_same_v) { @@ -391,7 +338,7 @@ NCollection_Array2 GeomGridEval_Surface::EvaluateGrid() const } else { - return theEval.EvaluateGrid(); + return theEval.EvaluateGrid(theUParams, theVParams); } }, myEvaluator); @@ -406,10 +353,12 @@ NCollection_Array2 GeomGridEval_Surface::EvaluateGrid() const //================================================================================================== -NCollection_Array2 GeomGridEval_Surface::EvaluateGridD1() const +NCollection_Array2 GeomGridEval_Surface::EvaluateGridD1( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams) const { NCollection_Array2 aResult = std::visit( - [](const auto& theEval) -> NCollection_Array2 { + [&theUParams, &theVParams](const auto& theEval) -> NCollection_Array2 { using T = std::decay_t; if constexpr (std::is_same_v) { @@ -417,7 +366,7 @@ NCollection_Array2 GeomGridEval_Surface::EvaluateGridD1() } else { - return theEval.EvaluateGridD1(); + return theEval.EvaluateGridD1(theUParams, theVParams); } }, myEvaluator); @@ -432,10 +381,12 @@ NCollection_Array2 GeomGridEval_Surface::EvaluateGridD1() //================================================================================================== -NCollection_Array2 GeomGridEval_Surface::EvaluateGridD2() const +NCollection_Array2 GeomGridEval_Surface::EvaluateGridD2( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams) const { NCollection_Array2 aResult = std::visit( - [](const auto& theEval) -> NCollection_Array2 { + [&theUParams, &theVParams](const auto& theEval) -> NCollection_Array2 { using T = std::decay_t; if constexpr (std::is_same_v) { @@ -443,7 +394,7 @@ NCollection_Array2 GeomGridEval_Surface::EvaluateGridD2() } else { - return theEval.EvaluateGridD2(); + return theEval.EvaluateGridD2(theUParams, theVParams); } }, myEvaluator); @@ -458,10 +409,12 @@ NCollection_Array2 GeomGridEval_Surface::EvaluateGridD2() //================================================================================================== -NCollection_Array2 GeomGridEval_Surface::EvaluateGridD3() const +NCollection_Array2 GeomGridEval_Surface::EvaluateGridD3( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams) const { NCollection_Array2 aResult = std::visit( - [](const auto& theEval) -> NCollection_Array2 { + [&theUParams, &theVParams](const auto& theEval) -> NCollection_Array2 { using T = std::decay_t; if constexpr (std::is_same_v) { @@ -469,7 +422,7 @@ NCollection_Array2 GeomGridEval_Surface::EvaluateGridD3() } else { - return theEval.EvaluateGridD3(); + return theEval.EvaluateGridD3(theUParams, theVParams); } }, myEvaluator); @@ -484,10 +437,14 @@ NCollection_Array2 GeomGridEval_Surface::EvaluateGridD3() //================================================================================================== -NCollection_Array2 GeomGridEval_Surface::EvaluateGridDN(int theNU, int theNV) const +NCollection_Array2 GeomGridEval_Surface::EvaluateGridDN( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams, + int theNU, + int theNV) const { NCollection_Array2 aResult = std::visit( - [theNU, theNV](const auto& theEval) -> NCollection_Array2 { + [&theUParams, &theVParams, theNU, theNV](const auto& theEval) -> NCollection_Array2 { using T = std::decay_t; if constexpr (std::is_same_v) { @@ -495,7 +452,144 @@ NCollection_Array2 GeomGridEval_Surface::EvaluateGridDN(int theNU, int t } else { - return theEval.EvaluateGridDN(theNU, theNV); + return theEval.EvaluateGridDN(theUParams, theVParams, theNU, theNV); + } + }, + myEvaluator); + + if (myTrsf.has_value()) + { + applyTransformation(aResult); + } + + return aResult; +} + +//================================================================================================== + +NCollection_Array1 GeomGridEval_Surface::EvaluatePoints( + const NCollection_Array1& theUVPairs) const +{ + NCollection_Array1 aResult = std::visit( + [&theUVPairs](const auto& theEval) -> NCollection_Array1 { + using T = std::decay_t; + if constexpr (std::is_same_v) + { + return NCollection_Array1(); + } + else + { + return theEval.EvaluatePoints(theUVPairs); + } + }, + myEvaluator); + + if (myTrsf.has_value()) + { + applyTransformation(aResult); + } + + return aResult; +} + +//================================================================================================== + +NCollection_Array1 GeomGridEval_Surface::EvaluatePointsD1( + const NCollection_Array1& theUVPairs) const +{ + NCollection_Array1 aResult = std::visit( + [&theUVPairs](const auto& theEval) -> NCollection_Array1 { + using T = std::decay_t; + if constexpr (std::is_same_v) + { + return NCollection_Array1(); + } + else + { + return theEval.EvaluatePointsD1(theUVPairs); + } + }, + myEvaluator); + + if (myTrsf.has_value()) + { + applyTransformation(aResult); + } + + return aResult; +} + +//================================================================================================== + +NCollection_Array1 GeomGridEval_Surface::EvaluatePointsD2( + const NCollection_Array1& theUVPairs) const +{ + NCollection_Array1 aResult = std::visit( + [&theUVPairs](const auto& theEval) -> NCollection_Array1 { + using T = std::decay_t; + if constexpr (std::is_same_v) + { + return NCollection_Array1(); + } + else + { + return theEval.EvaluatePointsD2(theUVPairs); + } + }, + myEvaluator); + + if (myTrsf.has_value()) + { + applyTransformation(aResult); + } + + return aResult; +} + +//================================================================================================== + +NCollection_Array1 GeomGridEval_Surface::EvaluatePointsD3( + const NCollection_Array1& theUVPairs) const +{ + NCollection_Array1 aResult = std::visit( + [&theUVPairs](const auto& theEval) -> NCollection_Array1 { + using T = std::decay_t; + if constexpr (std::is_same_v) + { + return NCollection_Array1(); + } + else + { + return theEval.EvaluatePointsD3(theUVPairs); + } + }, + myEvaluator); + + if (myTrsf.has_value()) + { + applyTransformation(aResult); + } + + return aResult; +} + +//================================================================================================== + +NCollection_Array1 GeomGridEval_Surface::EvaluatePointsDN( + const NCollection_Array1& theUVPairs, + int theNU, + int theNV) const +{ + NCollection_Array1 aResult = std::visit( + [&theUVPairs, theNU, theNV](const auto& theEval) -> NCollection_Array1 { + using T = std::decay_t; + if constexpr (std::is_same_v) + { + return NCollection_Array1(); + } + else + { + return theEval.EvaluatePointsDN(theUVPairs, theNU, theNV); } }, myEvaluator); @@ -624,3 +718,105 @@ void GeomGridEval_Surface::applyTransformation(NCollection_Array2& theGr } } } + +//================================================================================================== + +void GeomGridEval_Surface::applyTransformation(NCollection_Array1& thePoints) const +{ + if (!myTrsf.has_value() || thePoints.IsEmpty()) + { + return; + } + + const gp_Trsf& aTrsf = myTrsf.value(); + for (int i = thePoints.Lower(); i <= thePoints.Upper(); ++i) + { + thePoints.ChangeValue(i).Transform(aTrsf); + } +} + +//================================================================================================== + +void GeomGridEval_Surface::applyTransformation( + NCollection_Array1& thePoints) const +{ + if (!myTrsf.has_value() || thePoints.IsEmpty()) + { + return; + } + + const gp_Trsf& aTrsf = myTrsf.value(); + for (int i = thePoints.Lower(); i <= thePoints.Upper(); ++i) + { + GeomGridEval::SurfD1& aVal = thePoints.ChangeValue(i); + aVal.Point.Transform(aTrsf); + aVal.D1U.Transform(aTrsf); + aVal.D1V.Transform(aTrsf); + } +} + +//================================================================================================== + +void GeomGridEval_Surface::applyTransformation( + NCollection_Array1& thePoints) const +{ + if (!myTrsf.has_value() || thePoints.IsEmpty()) + { + return; + } + + const gp_Trsf& aTrsf = myTrsf.value(); + for (int i = thePoints.Lower(); i <= thePoints.Upper(); ++i) + { + GeomGridEval::SurfD2& aVal = thePoints.ChangeValue(i); + aVal.Point.Transform(aTrsf); + aVal.D1U.Transform(aTrsf); + aVal.D1V.Transform(aTrsf); + aVal.D2U.Transform(aTrsf); + aVal.D2V.Transform(aTrsf); + aVal.D2UV.Transform(aTrsf); + } +} + +//================================================================================================== + +void GeomGridEval_Surface::applyTransformation( + NCollection_Array1& thePoints) const +{ + if (!myTrsf.has_value() || thePoints.IsEmpty()) + { + return; + } + + const gp_Trsf& aTrsf = myTrsf.value(); + for (int i = thePoints.Lower(); i <= thePoints.Upper(); ++i) + { + GeomGridEval::SurfD3& aVal = thePoints.ChangeValue(i); + aVal.Point.Transform(aTrsf); + aVal.D1U.Transform(aTrsf); + aVal.D1V.Transform(aTrsf); + aVal.D2U.Transform(aTrsf); + aVal.D2V.Transform(aTrsf); + aVal.D2UV.Transform(aTrsf); + aVal.D3U.Transform(aTrsf); + aVal.D3V.Transform(aTrsf); + aVal.D3UUV.Transform(aTrsf); + aVal.D3UVV.Transform(aTrsf); + } +} + +//================================================================================================== + +void GeomGridEval_Surface::applyTransformation(NCollection_Array1& thePoints) const +{ + if (!myTrsf.has_value() || thePoints.IsEmpty()) + { + return; + } + + const gp_Trsf& aTrsf = myTrsf.value(); + for (int i = thePoints.Lower(); i <= thePoints.Upper(); ++i) + { + thePoints.ChangeValue(i).Transform(aTrsf); + } +} diff --git a/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_Surface.hxx b/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_Surface.hxx index 2514decbcf..2973540bfc 100644 --- a/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_Surface.hxx +++ b/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_Surface.hxx @@ -29,7 +29,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -53,6 +55,8 @@ //! - BezierSurface: Optimized batch evaluation via BSplSLib //! - BSplineSurface: Optimized batch evaluation with span-based caching //! - OffsetSurface: Optimized batch evaluation using basis surface derivatives +//! - SurfaceOfRevolution: Batch evaluation using basis curve +//! - SurfaceOfExtrusion: Batch evaluation using basis curve //! - Other: Fallback using Adaptor3d_Surface::D0 //! //! Usage: @@ -61,8 +65,10 @@ //! anEval.Initialize(myAdaptorSurface); //! // OR //! anEval.Initialize(myGeomSurface); -//! anEval.SetUVParams(myUParams, myVParams); -//! NCollection_Array2 aGrid = anEval.EvaluateGrid(); +//! // Grid evaluation +//! NCollection_Array2 aGrid = anEval.EvaluateGrid(myUParams, myVParams); +//! // Or point evaluation +//! NCollection_Array1 aPoints = anEval.EvaluatePoints(myUVPairs); //! @endcode class GeomGridEval_Surface { @@ -108,42 +114,86 @@ public: //! @param theSurface geometry to evaluate Standard_EXPORT void Initialize(const Handle(Geom_Surface)& theSurface); - //! Set UV parameters from two 1D arrays. - //! @param theUParams array of U parameter values - //! @param theVParams array of V parameter values - Standard_EXPORT void SetUVParams(const TColStd_Array1OfReal& theUParams, - const TColStd_Array1OfReal& theVParams); - //! Returns true if properly initialized. Standard_EXPORT bool IsInitialized() const; - //! Returns number of U parameters set. - Standard_EXPORT int NbUParams() const; - - //! Returns number of V parameters set. - Standard_EXPORT int NbVParams() const; - - //! Evaluate grid points at all set parameters. + //! Evaluate grid points at all specified parameters. + //! @param[in] theUParams array of U parameter values + //! @param[in] theVParams array of V parameter values //! @return 2D array of 3D points (1-based indexing) - Standard_EXPORT NCollection_Array2 EvaluateGrid() const; + Standard_EXPORT NCollection_Array2 EvaluateGrid( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams) const; //! Evaluate grid points with first partial derivatives. + //! @param[in] theUParams array of U parameter values + //! @param[in] theVParams array of V parameter values //! @return 2D array of SurfD1 (1-based indexing) - Standard_EXPORT NCollection_Array2 EvaluateGridD1() const; + Standard_EXPORT NCollection_Array2 EvaluateGridD1( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams) const; //! Evaluate grid points with first and second partial derivatives. + //! @param[in] theUParams array of U parameter values + //! @param[in] theVParams array of V parameter values //! @return 2D array of SurfD2 (1-based indexing) - Standard_EXPORT NCollection_Array2 EvaluateGridD2() const; + Standard_EXPORT NCollection_Array2 EvaluateGridD2( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams) const; //! Evaluate grid points with derivatives up to third order. + //! @param[in] theUParams array of U parameter values + //! @param[in] theVParams array of V parameter values //! @return 2D array of SurfD3 (1-based indexing) - Standard_EXPORT NCollection_Array2 EvaluateGridD3() const; + Standard_EXPORT NCollection_Array2 EvaluateGridD3( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams) const; //! Evaluate partial derivative d^(NU+NV)S/(dU^NU dV^NV) at all grid points. - //! @param theNU derivative order in U direction - //! @param theNV derivative order in V direction + //! @param[in] theUParams array of U parameter values + //! @param[in] theVParams array of V parameter values + //! @param[in] theNU derivative order in U direction + //! @param[in] theNV derivative order in V direction //! @return 2D array of derivative vectors (1-based indexing) - Standard_EXPORT NCollection_Array2 EvaluateGridDN(int theNU, int theNV) const; + Standard_EXPORT NCollection_Array2 EvaluateGridDN(const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams, + int theNU, + int theNV) const; + + //! Evaluate all UV pairs (points mode). + //! Dispatches to appropriate specialized evaluator. + //! @param[in] theUVPairs array of UV coordinate pairs (U=X(), V=Y()) + //! @return 1D array of evaluated points (1-based indexing) + Standard_EXPORT NCollection_Array1 EvaluatePoints( + const NCollection_Array1& theUVPairs) const; + + //! Evaluate all UV pairs with first partial derivatives. + //! @param[in] theUVPairs array of UV coordinate pairs (U=X(), V=Y()) + //! @return 1D array of SurfD1 (1-based indexing) + Standard_EXPORT NCollection_Array1 EvaluatePointsD1( + const NCollection_Array1& theUVPairs) const; + + //! Evaluate all UV pairs with first and second partial derivatives. + //! @param[in] theUVPairs array of UV coordinate pairs (U=X(), V=Y()) + //! @return 1D array of SurfD2 (1-based indexing) + Standard_EXPORT NCollection_Array1 EvaluatePointsD2( + const NCollection_Array1& theUVPairs) const; + + //! Evaluate all UV pairs with derivatives up to third order. + //! @param[in] theUVPairs array of UV coordinate pairs (U=X(), V=Y()) + //! @return 1D array of SurfD3 (1-based indexing) + Standard_EXPORT NCollection_Array1 EvaluatePointsD3( + const NCollection_Array1& theUVPairs) const; + + //! Evaluate partial derivative at all UV pairs. + //! @param[in] theUVPairs array of UV coordinate pairs (U=X(), V=Y()) + //! @param[in] theNU derivative order in U direction + //! @param[in] theNV derivative order in V direction + //! @return 1D array of derivative vectors (1-based indexing) + Standard_EXPORT NCollection_Array1 EvaluatePointsDN( + const NCollection_Array1& theUVPairs, + int theNU, + int theNV) const; //! Returns the detected surface type. GeomAbs_SurfaceType GetType() const { return mySurfaceType; } @@ -170,6 +220,21 @@ private: //! Apply transformation to grid of vectors. void applyTransformation(NCollection_Array2& theGrid) const; + //! Apply transformation to array of points. + void applyTransformation(NCollection_Array1& thePoints) const; + + //! Apply transformation to array of D1 results. + void applyTransformation(NCollection_Array1& thePoints) const; + + //! Apply transformation to array of D2 results. + void applyTransformation(NCollection_Array1& thePoints) const; + + //! Apply transformation to array of D3 results. + void applyTransformation(NCollection_Array1& thePoints) const; + + //! Apply transformation to array of vectors. + void applyTransformation(NCollection_Array1& thePoints) const; + EvaluatorVariant myEvaluator; GeomAbs_SurfaceType mySurfaceType; std::optional myTrsf; //!< Optional transformation for BRepAdaptor surfaces diff --git a/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_SurfaceOfExtrusion.cxx b/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_SurfaceOfExtrusion.cxx index 4ac4e7604a..57d037a34a 100644 --- a/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_SurfaceOfExtrusion.cxx +++ b/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_SurfaceOfExtrusion.cxx @@ -30,43 +30,23 @@ GeomGridEval_SurfaceOfExtrusion::GeomGridEval_SurfaceOfExtrusion( //================================================================================================== -void GeomGridEval_SurfaceOfExtrusion::SetUVParams(const TColStd_Array1OfReal& theUParams, - const TColStd_Array1OfReal& theVParams) +NCollection_Array2 GeomGridEval_SurfaceOfExtrusion::EvaluateGrid( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams) const { - const int aNbU = theUParams.Size(); - const int aNbV = theVParams.Size(); - - myUParams.Resize(1, aNbU, false); - for (int i = 1; i <= aNbU; ++i) - { - myUParams.SetValue(i, theUParams.Value(theUParams.Lower() + i - 1)); - } - - myVParams.Resize(1, aNbV, false); - for (int j = 1; j <= aNbV; ++j) - { - myVParams.SetValue(j, theVParams.Value(theVParams.Lower() + j - 1)); - } -} - -//================================================================================================== - -NCollection_Array2 GeomGridEval_SurfaceOfExtrusion::EvaluateGrid() const -{ - if (myBasisCurve.IsNull() || myUParams.IsEmpty() || myVParams.IsEmpty()) + if (myBasisCurve.IsNull() || theUParams.IsEmpty() || theVParams.IsEmpty()) { return NCollection_Array2(); } - const int aNbU = myUParams.Size(); - const int aNbV = myVParams.Size(); + const int aNbU = theUParams.Size(); + const int aNbV = theVParams.Size(); // Batch evaluate curve points using optimized curve evaluator GeomGridEval_Curve aCurveEval; aCurveEval.Initialize(myBasisCurve); - aCurveEval.SetParams(myUParams); - NCollection_Array1 aCurvePoints = aCurveEval.EvaluateGrid(); + NCollection_Array1 aCurvePoints = aCurveEval.EvaluateGrid(theUParams); if (aCurvePoints.IsEmpty()) { return NCollection_Array2(); @@ -82,7 +62,7 @@ NCollection_Array2 GeomGridEval_SurfaceOfExtrusion::EvaluateGrid() const const gp_Pnt& aCurvePt = aCurvePoints.Value(i); for (int j = 1; j <= aNbV; ++j) { - const double aV = myVParams.Value(j); + const double aV = theVParams.Value(theVParams.Lower() + j - 1); gp_Pnt aP; Geom_ExtrusionUtils::CalculateD0(aCurvePt, aV, aDirXYZ, aP); aResult.SetValue(i, j, aP); @@ -94,22 +74,23 @@ NCollection_Array2 GeomGridEval_SurfaceOfExtrusion::EvaluateGrid() const //================================================================================================== -NCollection_Array2 GeomGridEval_SurfaceOfExtrusion::EvaluateGridD1() const +NCollection_Array2 GeomGridEval_SurfaceOfExtrusion::EvaluateGridD1( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams) const { - if (myBasisCurve.IsNull() || myUParams.IsEmpty() || myVParams.IsEmpty()) + if (myBasisCurve.IsNull() || theUParams.IsEmpty() || theVParams.IsEmpty()) { return NCollection_Array2(); } - const int aNbU = myUParams.Size(); - const int aNbV = myVParams.Size(); + const int aNbU = theUParams.Size(); + const int aNbV = theVParams.Size(); // Batch evaluate curve D1 using optimized curve evaluator GeomGridEval_Curve aCurveEval; aCurveEval.Initialize(myBasisCurve); - aCurveEval.SetParams(myUParams); - NCollection_Array1 aCurveD1 = aCurveEval.EvaluateGridD1(); + NCollection_Array1 aCurveD1 = aCurveEval.EvaluateGridD1(theUParams); if (aCurveD1.IsEmpty()) { return NCollection_Array2(); @@ -125,7 +106,7 @@ NCollection_Array2 GeomGridEval_SurfaceOfExtrusion::Evalua for (int j = 1; j <= aNbV; ++j) { - const double aV = myVParams.Value(j); + const double aV = theVParams.Value(theVParams.Lower() + j - 1); gp_Pnt aP; gp_Vec aD1U, aD1V; Geom_ExtrusionUtils::CalculateD1(aCurveData.Point, @@ -144,22 +125,23 @@ NCollection_Array2 GeomGridEval_SurfaceOfExtrusion::Evalua //================================================================================================== -NCollection_Array2 GeomGridEval_SurfaceOfExtrusion::EvaluateGridD2() const +NCollection_Array2 GeomGridEval_SurfaceOfExtrusion::EvaluateGridD2( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams) const { - if (myBasisCurve.IsNull() || myUParams.IsEmpty() || myVParams.IsEmpty()) + if (myBasisCurve.IsNull() || theUParams.IsEmpty() || theVParams.IsEmpty()) { return NCollection_Array2(); } - const int aNbU = myUParams.Size(); - const int aNbV = myVParams.Size(); + const int aNbU = theUParams.Size(); + const int aNbV = theVParams.Size(); // Batch evaluate curve D2 using optimized curve evaluator GeomGridEval_Curve aCurveEval; aCurveEval.Initialize(myBasisCurve); - aCurveEval.SetParams(myUParams); - NCollection_Array1 aCurveD2 = aCurveEval.EvaluateGridD2(); + NCollection_Array1 aCurveD2 = aCurveEval.EvaluateGridD2(theUParams); if (aCurveD2.IsEmpty()) { return NCollection_Array2(); @@ -176,7 +158,7 @@ NCollection_Array2 GeomGridEval_SurfaceOfExtrusion::Evalua for (int j = 1; j <= aNbV; ++j) { - const double aV = myVParams.Value(j); + const double aV = theVParams.Value(theVParams.Lower() + j - 1); gp_Pnt aP; gp_Vec aD1U, aD1V, aD2U, aD2V, aD2UV; Geom_ExtrusionUtils::CalculateD2(aCurveData.Point, @@ -199,22 +181,23 @@ NCollection_Array2 GeomGridEval_SurfaceOfExtrusion::Evalua //================================================================================================== -NCollection_Array2 GeomGridEval_SurfaceOfExtrusion::EvaluateGridD3() const +NCollection_Array2 GeomGridEval_SurfaceOfExtrusion::EvaluateGridD3( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams) const { - if (myBasisCurve.IsNull() || myUParams.IsEmpty() || myVParams.IsEmpty()) + if (myBasisCurve.IsNull() || theUParams.IsEmpty() || theVParams.IsEmpty()) { return NCollection_Array2(); } - const int aNbU = myUParams.Size(); - const int aNbV = myVParams.Size(); + const int aNbU = theUParams.Size(); + const int aNbV = theVParams.Size(); // Batch evaluate curve D3 using optimized curve evaluator GeomGridEval_Curve aCurveEval; aCurveEval.Initialize(myBasisCurve); - aCurveEval.SetParams(myUParams); - NCollection_Array1 aCurveD3 = aCurveEval.EvaluateGridD3(); + NCollection_Array1 aCurveD3 = aCurveEval.EvaluateGridD3(theUParams); if (aCurveD3.IsEmpty()) { return NCollection_Array2(); @@ -232,7 +215,7 @@ NCollection_Array2 GeomGridEval_SurfaceOfExtrusion::Evalua for (int j = 1; j <= aNbV; ++j) { - const double aV = myVParams.Value(j); + const double aV = theVParams.Value(theVParams.Lower() + j - 1); gp_Pnt aP; gp_Vec aD1U, aD1V, aD2U, aD2V, aD2UV, aD3U, aD3V, aD3UUV, aD3UVV; Geom_ExtrusionUtils::CalculateD3(aCurveData.Point, @@ -260,17 +243,20 @@ NCollection_Array2 GeomGridEval_SurfaceOfExtrusion::Evalua //================================================================================================== -NCollection_Array2 GeomGridEval_SurfaceOfExtrusion::EvaluateGridDN(int theNU, - int theNV) const +NCollection_Array2 GeomGridEval_SurfaceOfExtrusion::EvaluateGridDN( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams, + int theNU, + int theNV) const { - if (myBasisCurve.IsNull() || myUParams.IsEmpty() || myVParams.IsEmpty() || theNU < 0 || theNV < 0 - || (theNU + theNV) < 1) + if (myBasisCurve.IsNull() || theUParams.IsEmpty() || theVParams.IsEmpty() || theNU < 0 + || theNV < 0 || (theNU + theNV) < 1) { return NCollection_Array2(); } - const int aNbU = myUParams.Size(); - const int aNbV = myVParams.Size(); + const int aNbU = theUParams.Size(); + const int aNbV = theVParams.Size(); NCollection_Array2 aResult(1, aNbU, 1, aNbV); @@ -282,9 +268,8 @@ NCollection_Array2 GeomGridEval_SurfaceOfExtrusion::EvaluateGridDN(int t // Pure U derivative = curve derivative GeomGridEval_Curve aCurveEval; aCurveEval.Initialize(myBasisCurve); - aCurveEval.SetParams(myUParams); - NCollection_Array1 aCurveDN = aCurveEval.EvaluateGridDN(theNU); + NCollection_Array1 aCurveDN = aCurveEval.EvaluateGridDN(theUParams, theNU); for (int i = 1; i <= aNbU; ++i) { @@ -310,3 +295,96 @@ NCollection_Array2 GeomGridEval_SurfaceOfExtrusion::EvaluateGridDN(int t return aResult; } + +//================================================================================================== + +NCollection_Array1 GeomGridEval_SurfaceOfExtrusion::EvaluatePoints( + const NCollection_Array1& theUVPairs) const +{ + if (myGeom.IsNull() || theUVPairs.IsEmpty()) + { + return NCollection_Array1(); + } + + return GeomGridEval::EvaluatePointsHelper(theUVPairs, [this](double theU, double theV) -> gp_Pnt { + return myGeom->Value(theU, theV); + }); +} + +//================================================================================================== + +NCollection_Array1 GeomGridEval_SurfaceOfExtrusion::EvaluatePointsD1( + const NCollection_Array1& theUVPairs) const +{ + if (myGeom.IsNull() || theUVPairs.IsEmpty()) + { + return NCollection_Array1(); + } + + return GeomGridEval::EvaluatePointsD1Helper( + theUVPairs, + [this](double theU, double theV) -> GeomGridEval::SurfD1 { + gp_Pnt aP; + gp_Vec aD1U, aD1V; + myGeom->D1(theU, theV, aP, aD1U, aD1V); + return {aP, aD1U, aD1V}; + }); +} + +//================================================================================================== + +NCollection_Array1 GeomGridEval_SurfaceOfExtrusion::EvaluatePointsD2( + const NCollection_Array1& theUVPairs) const +{ + if (myGeom.IsNull() || theUVPairs.IsEmpty()) + { + return NCollection_Array1(); + } + + return GeomGridEval::EvaluatePointsD2Helper( + theUVPairs, + [this](double theU, double theV) -> GeomGridEval::SurfD2 { + gp_Pnt aP; + gp_Vec aD1U, aD1V, aD2U, aD2V, aD2UV; + myGeom->D2(theU, theV, aP, aD1U, aD1V, aD2U, aD2V, aD2UV); + return {aP, aD1U, aD1V, aD2U, aD2V, aD2UV}; + }); +} + +//================================================================================================== + +NCollection_Array1 GeomGridEval_SurfaceOfExtrusion::EvaluatePointsD3( + const NCollection_Array1& theUVPairs) const +{ + if (myGeom.IsNull() || theUVPairs.IsEmpty()) + { + return NCollection_Array1(); + } + + return GeomGridEval::EvaluatePointsD3Helper( + theUVPairs, + [this](double theU, double theV) -> GeomGridEval::SurfD3 { + gp_Pnt aP; + gp_Vec aD1U, aD1V, aD2U, aD2V, aD2UV, aD3U, aD3V, aD3UUV, aD3UVV; + myGeom->D3(theU, theV, aP, aD1U, aD1V, aD2U, aD2V, aD2UV, aD3U, aD3V, aD3UUV, aD3UVV); + return {aP, aD1U, aD1V, aD2U, aD2V, aD2UV, aD3U, aD3V, aD3UUV, aD3UVV}; + }); +} + +//================================================================================================== + +NCollection_Array1 GeomGridEval_SurfaceOfExtrusion::EvaluatePointsDN( + const NCollection_Array1& theUVPairs, + int theNU, + int theNV) const +{ + if (myGeom.IsNull() || theUVPairs.IsEmpty() || theNU < 0 || theNV < 0 || (theNU + theNV) < 1) + { + return NCollection_Array1(); + } + + return GeomGridEval::EvaluatePointsDNHelper(theUVPairs, + [this, theNU, theNV](double theU, double theV) { + return myGeom->DN(theU, theV, theNU, theNV); + }); +} diff --git a/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_SurfaceOfExtrusion.hxx b/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_SurfaceOfExtrusion.hxx index 46f78076d1..d6e7e53725 100644 --- a/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_SurfaceOfExtrusion.hxx +++ b/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_SurfaceOfExtrusion.hxx @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -42,8 +43,7 @@ //! Usage: //! @code //! GeomGridEval_SurfaceOfExtrusion anEvaluator(myExtrusionSurface); -//! anEvaluator.SetUVParams(myUParams, myVParams); -//! NCollection_Array2 aGrid = anEvaluator.EvaluateGrid(); +//! NCollection_Array2 aGrid = anEvaluator.EvaluateGrid(myUParams, myVParams); //! @endcode class GeomGridEval_SurfaceOfExtrusion { @@ -61,53 +61,98 @@ public: GeomGridEval_SurfaceOfExtrusion(GeomGridEval_SurfaceOfExtrusion&&) = delete; GeomGridEval_SurfaceOfExtrusion& operator=(GeomGridEval_SurfaceOfExtrusion&&) = delete; - //! Set UV parameters from two 1D arrays. - //! @param theUParams array of U parameter values (curve parameter) - //! @param theVParams array of V parameter values (extrusion distance) - Standard_EXPORT void SetUVParams(const TColStd_Array1OfReal& theUParams, - const TColStd_Array1OfReal& theVParams); - //! Returns the geometry handle. const Handle(Geom_SurfaceOfLinearExtrusion)& Geometry() const { return myGeom; } - //! Returns number of U parameters. - int NbUParams() const { return myUParams.Size(); } - - //! Returns number of V parameters. - int NbVParams() const { return myVParams.Size(); } - //! Evaluate all grid points. + //! @param[in] theUParams array of U parameter values (curve parameter) + //! @param[in] theVParams array of V parameter values (extrusion distance) //! @return 2D array of evaluated points (1-based indexing), //! or empty array if geometry is null or no parameters set - Standard_EXPORT NCollection_Array2 EvaluateGrid() const; + Standard_EXPORT NCollection_Array2 EvaluateGrid( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams) const; //! Evaluate all grid points with first partial derivatives. + //! @param[in] theUParams array of U parameter values (curve parameter) + //! @param[in] theVParams array of V parameter values (extrusion distance) //! @return 2D array of SurfD1 (1-based indexing), //! or empty array if geometry is null or no parameters set - Standard_EXPORT NCollection_Array2 EvaluateGridD1() const; + Standard_EXPORT NCollection_Array2 EvaluateGridD1( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams) const; //! Evaluate all grid points with first and second partial derivatives. + //! @param[in] theUParams array of U parameter values (curve parameter) + //! @param[in] theVParams array of V parameter values (extrusion distance) //! @return 2D array of SurfD2 (1-based indexing), //! or empty array if geometry is null or no parameters set - Standard_EXPORT NCollection_Array2 EvaluateGridD2() const; + Standard_EXPORT NCollection_Array2 EvaluateGridD2( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams) const; //! Evaluate all grid points with derivatives up to third order. + //! @param[in] theUParams array of U parameter values (curve parameter) + //! @param[in] theVParams array of V parameter values (extrusion distance) //! @return 2D array of SurfD3 (1-based indexing), //! or empty array if geometry is null or no parameters set - Standard_EXPORT NCollection_Array2 EvaluateGridD3() const; + Standard_EXPORT NCollection_Array2 EvaluateGridD3( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams) const; //! Evaluate partial derivative d^(NU+NV)S/(dU^NU dV^NV) at all grid points. - //! @param theNU derivative order in U direction - //! @param theNV derivative order in V direction + //! @param[in] theUParams array of U parameter values (curve parameter) + //! @param[in] theVParams array of V parameter values (extrusion distance) + //! @param[in] theNU derivative order in U direction + //! @param[in] theNV derivative order in V direction //! @return 2D array of derivative vectors (1-based indexing) - Standard_EXPORT NCollection_Array2 EvaluateGridDN(int theNU, int theNV) const; + Standard_EXPORT NCollection_Array2 EvaluateGridDN(const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams, + int theNU, + int theNV) const; + + //! Evaluate points at arbitrary UV pairs. + //! @param[in] theUVPairs array of UV coordinate pairs (U=X(), V=Y()) + //! @return array of evaluated points (1-based indexing), + //! or empty array if geometry is null or no parameters set + Standard_EXPORT NCollection_Array1 EvaluatePoints( + const NCollection_Array1& theUVPairs) const; + + //! Evaluate points with first partial derivatives at arbitrary UV pairs. + //! @param[in] theUVPairs array of UV coordinate pairs (U=X(), V=Y()) + //! @return array of SurfD1 (1-based indexing), + //! or empty array if geometry is null or no parameters set + Standard_EXPORT NCollection_Array1 EvaluatePointsD1( + const NCollection_Array1& theUVPairs) const; + + //! Evaluate points with first and second partial derivatives at arbitrary UV pairs. + //! @param[in] theUVPairs array of UV coordinate pairs (U=X(), V=Y()) + //! @return array of SurfD2 (1-based indexing), + //! or empty array if geometry is null or no parameters set + Standard_EXPORT NCollection_Array1 EvaluatePointsD2( + const NCollection_Array1& theUVPairs) const; + + //! Evaluate points with derivatives up to third order at arbitrary UV pairs. + //! @param[in] theUVPairs array of UV coordinate pairs (U=X(), V=Y()) + //! @return array of SurfD3 (1-based indexing), + //! or empty array if geometry is null or no parameters set + Standard_EXPORT NCollection_Array1 EvaluatePointsD3( + const NCollection_Array1& theUVPairs) const; + + //! Evaluate partial derivative at arbitrary UV pairs. + //! @param[in] theUVPairs array of UV coordinate pairs (U=X(), V=Y()) + //! @param[in] theNU derivative order in U direction + //! @param[in] theNV derivative order in V direction + //! @return array of derivative vectors (1-based indexing) + Standard_EXPORT NCollection_Array1 EvaluatePointsDN( + const NCollection_Array1& theUVPairs, + int theNU, + int theNV) const; private: Handle(Geom_SurfaceOfLinearExtrusion) myGeom; Handle(Geom_Curve) myBasisCurve; gp_Dir myDirection; - NCollection_Array1 myUParams; - NCollection_Array1 myVParams; }; #endif // _GeomGridEval_SurfaceOfExtrusion_HeaderFile diff --git a/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_SurfaceOfRevolution.cxx b/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_SurfaceOfRevolution.cxx index f939471703..8c0517ae86 100644 --- a/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_SurfaceOfRevolution.cxx +++ b/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_SurfaceOfRevolution.cxx @@ -32,43 +32,23 @@ GeomGridEval_SurfaceOfRevolution::GeomGridEval_SurfaceOfRevolution( //================================================================================================== -void GeomGridEval_SurfaceOfRevolution::SetUVParams(const TColStd_Array1OfReal& theUParams, - const TColStd_Array1OfReal& theVParams) +NCollection_Array2 GeomGridEval_SurfaceOfRevolution::EvaluateGrid( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams) const { - const int aNbU = theUParams.Size(); - const int aNbV = theVParams.Size(); - - myUParams.Resize(1, aNbU, false); - for (int i = 1; i <= aNbU; ++i) - { - myUParams.SetValue(i, theUParams.Value(theUParams.Lower() + i - 1)); - } - - myVParams.Resize(1, aNbV, false); - for (int j = 1; j <= aNbV; ++j) - { - myVParams.SetValue(j, theVParams.Value(theVParams.Lower() + j - 1)); - } -} - -//================================================================================================== - -NCollection_Array2 GeomGridEval_SurfaceOfRevolution::EvaluateGrid() const -{ - if (myBasisCurve.IsNull() || myUParams.IsEmpty() || myVParams.IsEmpty()) + if (myBasisCurve.IsNull() || theUParams.IsEmpty() || theVParams.IsEmpty()) { return NCollection_Array2(); } - const int aNbU = myUParams.Size(); - const int aNbV = myVParams.Size(); + const int aNbU = theUParams.Size(); + const int aNbV = theVParams.Size(); // Batch evaluate curve points using optimized curve evaluator GeomGridEval_Curve aCurveEval; aCurveEval.Initialize(myBasisCurve); - aCurveEval.SetParams(myVParams); - NCollection_Array1 aCurvePoints = aCurveEval.EvaluateGrid(); + NCollection_Array1 aCurvePoints = aCurveEval.EvaluateGrid(theVParams); if (aCurvePoints.IsEmpty()) { return NCollection_Array2(); @@ -78,7 +58,7 @@ NCollection_Array2 GeomGridEval_SurfaceOfRevolution::EvaluateGrid() cons for (int i = 1; i <= aNbU; ++i) { - const double aU = myUParams.Value(i); + const double aU = theUParams.Value(theUParams.Lower() + i - 1); for (int j = 1; j <= aNbV; ++j) { @@ -93,22 +73,23 @@ NCollection_Array2 GeomGridEval_SurfaceOfRevolution::EvaluateGrid() cons //================================================================================================== -NCollection_Array2 GeomGridEval_SurfaceOfRevolution::EvaluateGridD1() const +NCollection_Array2 GeomGridEval_SurfaceOfRevolution::EvaluateGridD1( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams) const { - if (myBasisCurve.IsNull() || myUParams.IsEmpty() || myVParams.IsEmpty()) + if (myBasisCurve.IsNull() || theUParams.IsEmpty() || theVParams.IsEmpty()) { return NCollection_Array2(); } - const int aNbU = myUParams.Size(); - const int aNbV = myVParams.Size(); + const int aNbU = theUParams.Size(); + const int aNbV = theVParams.Size(); // Batch evaluate curve D1 GeomGridEval_Curve aCurveEval; aCurveEval.Initialize(myBasisCurve); - aCurveEval.SetParams(myVParams); - NCollection_Array1 aCurveD1 = aCurveEval.EvaluateGridD1(); + NCollection_Array1 aCurveD1 = aCurveEval.EvaluateGridD1(theVParams); if (aCurveD1.IsEmpty()) { return NCollection_Array2(); @@ -118,7 +99,7 @@ NCollection_Array2 GeomGridEval_SurfaceOfRevolution::Evalu for (int i = 1; i <= aNbU; ++i) { - const double aU = myUParams.Value(i); + const double aU = theUParams.Value(theUParams.Lower() + i - 1); for (int j = 1; j <= aNbV; ++j) { @@ -142,22 +123,23 @@ NCollection_Array2 GeomGridEval_SurfaceOfRevolution::Evalu //================================================================================================== -NCollection_Array2 GeomGridEval_SurfaceOfRevolution::EvaluateGridD2() const +NCollection_Array2 GeomGridEval_SurfaceOfRevolution::EvaluateGridD2( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams) const { - if (myBasisCurve.IsNull() || myUParams.IsEmpty() || myVParams.IsEmpty()) + if (myBasisCurve.IsNull() || theUParams.IsEmpty() || theVParams.IsEmpty()) { return NCollection_Array2(); } - const int aNbU = myUParams.Size(); - const int aNbV = myVParams.Size(); + const int aNbU = theUParams.Size(); + const int aNbV = theVParams.Size(); // Batch evaluate curve D2 GeomGridEval_Curve aCurveEval; aCurveEval.Initialize(myBasisCurve); - aCurveEval.SetParams(myVParams); - NCollection_Array1 aCurveD2 = aCurveEval.EvaluateGridD2(); + NCollection_Array1 aCurveD2 = aCurveEval.EvaluateGridD2(theVParams); if (aCurveD2.IsEmpty()) { return NCollection_Array2(); @@ -167,7 +149,7 @@ NCollection_Array2 GeomGridEval_SurfaceOfRevolution::Evalu for (int i = 1; i <= aNbU; ++i) { - const double aU = myUParams.Value(i); + const double aU = theUParams.Value(theUParams.Lower() + i - 1); for (int j = 1; j <= aNbV; ++j) { @@ -195,22 +177,23 @@ NCollection_Array2 GeomGridEval_SurfaceOfRevolution::Evalu //================================================================================================== -NCollection_Array2 GeomGridEval_SurfaceOfRevolution::EvaluateGridD3() const +NCollection_Array2 GeomGridEval_SurfaceOfRevolution::EvaluateGridD3( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams) const { - if (myBasisCurve.IsNull() || myUParams.IsEmpty() || myVParams.IsEmpty()) + if (myBasisCurve.IsNull() || theUParams.IsEmpty() || theVParams.IsEmpty()) { return NCollection_Array2(); } - const int aNbU = myUParams.Size(); - const int aNbV = myVParams.Size(); + const int aNbU = theUParams.Size(); + const int aNbV = theVParams.Size(); // Batch evaluate curve D3 GeomGridEval_Curve aCurveEval; aCurveEval.Initialize(myBasisCurve); - aCurveEval.SetParams(myVParams); - NCollection_Array1 aCurveD3 = aCurveEval.EvaluateGridD3(); + NCollection_Array1 aCurveD3 = aCurveEval.EvaluateGridD3(theVParams); if (aCurveD3.IsEmpty()) { return NCollection_Array2(); @@ -220,7 +203,7 @@ NCollection_Array2 GeomGridEval_SurfaceOfRevolution::Evalu for (int i = 1; i <= aNbU; ++i) { - const double aU = myUParams.Value(i); + const double aU = theUParams.Value(theUParams.Lower() + i - 1); for (int j = 1; j <= aNbV; ++j) { @@ -253,33 +236,35 @@ NCollection_Array2 GeomGridEval_SurfaceOfRevolution::Evalu //================================================================================================== -NCollection_Array2 GeomGridEval_SurfaceOfRevolution::EvaluateGridDN(int theNU, - int theNV) const +NCollection_Array2 GeomGridEval_SurfaceOfRevolution::EvaluateGridDN( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams, + int theNU, + int theNV) const { - if (myBasisCurve.IsNull() || myUParams.IsEmpty() || myVParams.IsEmpty() || theNU < 0 || theNV < 0 - || (theNU + theNV) < 1) + if (myBasisCurve.IsNull() || theUParams.IsEmpty() || theVParams.IsEmpty() || theNU < 0 + || theNV < 0 || (theNU + theNV) < 1) { return NCollection_Array2(); } - const int aNbU = myUParams.Size(); - const int aNbV = myVParams.Size(); + const int aNbU = theUParams.Size(); + const int aNbV = theVParams.Size(); NCollection_Array2 aResult(1, aNbU, 1, aNbV); // Get curve data GeomGridEval_Curve aCurveEval; aCurveEval.Initialize(myBasisCurve); - aCurveEval.SetParams(myVParams); if (theNU == 0) { // Pure V derivative = curve derivative, rotated - NCollection_Array1 aCurveDN = aCurveEval.EvaluateGridDN(theNV); + NCollection_Array1 aCurveDN = aCurveEval.EvaluateGridDN(theVParams, theNV); for (int i = 1; i <= aNbU; ++i) { - const double aU = myUParams.Value(i); + const double aU = theUParams.Value(theUParams.Lower() + i - 1); for (int j = 1; j <= aNbV; ++j) { @@ -297,16 +282,16 @@ NCollection_Array2 GeomGridEval_SurfaceOfRevolution::EvaluateGridDN(int if (theNV == 0) { - aCurvePts = aCurveEval.EvaluateGrid(); + aCurvePts = aCurveEval.EvaluateGrid(theVParams); } else { - aCurveDV = aCurveEval.EvaluateGridDN(theNV); + aCurveDV = aCurveEval.EvaluateGridDN(theVParams, theNV); } for (int i = 1; i <= aNbU; ++i) { - const double aU = myUParams.Value(i); + const double aU = theUParams.Value(theUParams.Lower() + i - 1); for (int j = 1; j <= aNbV; ++j) { @@ -329,3 +314,91 @@ NCollection_Array2 GeomGridEval_SurfaceOfRevolution::EvaluateGridDN(int return aResult; } + +//================================================================================================== + +NCollection_Array1 GeomGridEval_SurfaceOfRevolution::EvaluatePoints( + const NCollection_Array1& theUVPairs) const +{ + if (myGeom.IsNull() || theUVPairs.IsEmpty()) + { + return NCollection_Array1(); + } + + return GeomGridEval::EvaluatePointsHelper(theUVPairs, [this](double theU, double theV) -> gp_Pnt { + return myGeom->Value(theU, theV); + }); +} + +//================================================================================================== + +NCollection_Array1 GeomGridEval_SurfaceOfRevolution::EvaluatePointsD1( + const NCollection_Array1& theUVPairs) const +{ + if (myGeom.IsNull() || theUVPairs.IsEmpty()) + { + return NCollection_Array1(); + } + + return GeomGridEval::EvaluatePointsD1Helper(theUVPairs, [this](double theU, double theV) { + gp_Pnt aP; + gp_Vec aD1U, aD1V; + myGeom->D1(theU, theV, aP, aD1U, aD1V); + return GeomGridEval::SurfD1{aP, aD1U, aD1V}; + }); +} + +//================================================================================================== + +NCollection_Array1 GeomGridEval_SurfaceOfRevolution::EvaluatePointsD2( + const NCollection_Array1& theUVPairs) const +{ + if (myGeom.IsNull() || theUVPairs.IsEmpty()) + { + return NCollection_Array1(); + } + + return GeomGridEval::EvaluatePointsD2Helper(theUVPairs, [this](double theU, double theV) { + gp_Pnt aP; + gp_Vec aD1U, aD1V, aD2U, aD2V, aD2UV; + myGeom->D2(theU, theV, aP, aD1U, aD1V, aD2U, aD2V, aD2UV); + return GeomGridEval::SurfD2{aP, aD1U, aD1V, aD2U, aD2V, aD2UV}; + }); +} + +//================================================================================================== + +NCollection_Array1 GeomGridEval_SurfaceOfRevolution::EvaluatePointsD3( + const NCollection_Array1& theUVPairs) const +{ + if (myGeom.IsNull() || theUVPairs.IsEmpty()) + { + return NCollection_Array1(); + } + + return GeomGridEval::EvaluatePointsD3Helper(theUVPairs, [this](double theU, double theV) { + gp_Pnt aP; + gp_Vec aD1U, aD1V, aD2U, aD2V, aD2UV, aD3U, aD3V, aD3UUV, aD3UVV; + myGeom->D3(theU, theV, aP, aD1U, aD1V, aD2U, aD2V, aD2UV, aD3U, aD3V, aD3UUV, aD3UVV); + return GeomGridEval::SurfD3{aP, aD1U, aD1V, aD2U, aD2V, aD2UV, aD3U, aD3V, aD3UUV, aD3UVV}; + }); +} + +//================================================================================================== + +NCollection_Array1 GeomGridEval_SurfaceOfRevolution::EvaluatePointsDN( + const NCollection_Array1& theUVPairs, + int theNU, + int theNV) const +{ + if (myGeom.IsNull() || theUVPairs.IsEmpty() || theNU < 0 || theNV < 0 || (theNU + theNV) < 1) + { + return NCollection_Array1(); + } + + return GeomGridEval::EvaluatePointsDNHelper( + theUVPairs, + [this, theNU, theNV](double theU, double theV) -> gp_Vec { + return myGeom->DN(theU, theV, theNU, theNV); + }); +} diff --git a/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_SurfaceOfRevolution.hxx b/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_SurfaceOfRevolution.hxx index 278473ed9c..1db5a8d18b 100644 --- a/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_SurfaceOfRevolution.hxx +++ b/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_SurfaceOfRevolution.hxx @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -50,8 +51,7 @@ //! Usage: //! @code //! GeomGridEval_SurfaceOfRevolution anEvaluator(myRevolutionSurface); -//! anEvaluator.SetUVParams(myUParams, myVParams); -//! NCollection_Array2 aGrid = anEvaluator.EvaluateGrid(); +//! NCollection_Array2 aGrid = anEvaluator.EvaluateGrid(myUParams, myVParams); //! @endcode class GeomGridEval_SurfaceOfRevolution { @@ -69,46 +69,93 @@ public: GeomGridEval_SurfaceOfRevolution(GeomGridEval_SurfaceOfRevolution&&) = delete; GeomGridEval_SurfaceOfRevolution& operator=(GeomGridEval_SurfaceOfRevolution&&) = delete; - //! Set UV parameters from two 1D arrays. - //! @param theUParams array of U parameter values (rotation angle) - //! @param theVParams array of V parameter values (curve parameter) - Standard_EXPORT void SetUVParams(const TColStd_Array1OfReal& theUParams, - const TColStd_Array1OfReal& theVParams); - //! Returns the geometry handle. const Handle(Geom_SurfaceOfRevolution)& Geometry() const { return myGeom; } - //! Returns number of U parameters. - int NbUParams() const { return myUParams.Size(); } - - //! Returns number of V parameters. - int NbVParams() const { return myVParams.Size(); } - //! Evaluate all grid points. + //! @param[in] theUParams array of U parameter values (rotation angle) + //! @param[in] theVParams array of V parameter values (curve parameter) //! @return 2D array of evaluated points (1-based indexing), //! or empty array if geometry is null or no parameters set - Standard_EXPORT NCollection_Array2 EvaluateGrid() const; + Standard_EXPORT NCollection_Array2 EvaluateGrid( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams) const; //! Evaluate all grid points with first partial derivatives. + //! @param[in] theUParams array of U parameter values (rotation angle) + //! @param[in] theVParams array of V parameter values (curve parameter) //! @return 2D array of SurfD1 (1-based indexing), //! or empty array if geometry is null or no parameters set - Standard_EXPORT NCollection_Array2 EvaluateGridD1() const; + Standard_EXPORT NCollection_Array2 EvaluateGridD1( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams) const; //! Evaluate all grid points with first and second partial derivatives. + //! @param[in] theUParams array of U parameter values (rotation angle) + //! @param[in] theVParams array of V parameter values (curve parameter) //! @return 2D array of SurfD2 (1-based indexing), //! or empty array if geometry is null or no parameters set - Standard_EXPORT NCollection_Array2 EvaluateGridD2() const; + Standard_EXPORT NCollection_Array2 EvaluateGridD2( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams) const; //! Evaluate all grid points with derivatives up to third order. + //! @param[in] theUParams array of U parameter values (rotation angle) + //! @param[in] theVParams array of V parameter values (curve parameter) //! @return 2D array of SurfD3 (1-based indexing), //! or empty array if geometry is null or no parameters set - Standard_EXPORT NCollection_Array2 EvaluateGridD3() const; + Standard_EXPORT NCollection_Array2 EvaluateGridD3( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams) const; //! Evaluate partial derivative d^(NU+NV)S/(dU^NU dV^NV) at all grid points. - //! @param theNU derivative order in U direction - //! @param theNV derivative order in V direction + //! @param[in] theUParams array of U parameter values (rotation angle) + //! @param[in] theVParams array of V parameter values (curve parameter) + //! @param[in] theNU derivative order in U direction + //! @param[in] theNV derivative order in V direction //! @return 2D array of derivative vectors (1-based indexing) - Standard_EXPORT NCollection_Array2 EvaluateGridDN(int theNU, int theNV) const; + Standard_EXPORT NCollection_Array2 EvaluateGridDN(const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams, + int theNU, + int theNV) const; + + //! Evaluate points at arbitrary UV pairs. + //! @param[in] theUVPairs array of UV coordinate pairs (U=X(), V=Y()) + //! @return array of evaluated points (1-based indexing), + //! or empty array if geometry is null or no parameters set + Standard_EXPORT NCollection_Array1 EvaluatePoints( + const NCollection_Array1& theUVPairs) const; + + //! Evaluate points with first partial derivatives at arbitrary UV pairs. + //! @param[in] theUVPairs array of UV coordinate pairs (U=X(), V=Y()) + //! @return array of SurfD1 (1-based indexing), + //! or empty array if geometry is null or no parameters set + Standard_EXPORT NCollection_Array1 EvaluatePointsD1( + const NCollection_Array1& theUVPairs) const; + + //! Evaluate points with first and second partial derivatives at arbitrary UV pairs. + //! @param[in] theUVPairs array of UV coordinate pairs (U=X(), V=Y()) + //! @return array of SurfD2 (1-based indexing), + //! or empty array if geometry is null or no parameters set + Standard_EXPORT NCollection_Array1 EvaluatePointsD2( + const NCollection_Array1& theUVPairs) const; + + //! Evaluate points with derivatives up to third order at arbitrary UV pairs. + //! @param[in] theUVPairs array of UV coordinate pairs (U=X(), V=Y()) + //! @return array of SurfD3 (1-based indexing), + //! or empty array if geometry is null or no parameters set + Standard_EXPORT NCollection_Array1 EvaluatePointsD3( + const NCollection_Array1& theUVPairs) const; + + //! Evaluate partial derivative at arbitrary UV pairs. + //! @param[in] theUVPairs array of UV coordinate pairs (U=X(), V=Y()) + //! @param[in] theNU derivative order in U direction + //! @param[in] theNV derivative order in V direction + //! @return array of derivative vectors (1-based indexing) + Standard_EXPORT NCollection_Array1 EvaluatePointsDN( + const NCollection_Array1& theUVPairs, + int theNU, + int theNV) const; private: Handle(Geom_SurfaceOfRevolution) myGeom; @@ -116,8 +163,6 @@ private: gp_Ax1 myAxis; gp_Pnt myAxisLocation; gp_Dir myAxisDirection; - NCollection_Array1 myUParams; - NCollection_Array1 myVParams; }; #endif // _GeomGridEval_SurfaceOfRevolution_HeaderFile diff --git a/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_Torus.cxx b/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_Torus.cxx index 6277b1cafe..f0509ef7a8 100644 --- a/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_Torus.cxx +++ b/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_Torus.cxx @@ -19,473 +19,246 @@ //================================================================================================== -void GeomGridEval_Torus::SetUVParams(const TColStd_Array1OfReal& theUParams, - const TColStd_Array1OfReal& theVParams) +GeomGridEval_Torus::Data GeomGridEval_Torus::extractData() const { - const int aNbU = theUParams.Size(); - const int aNbV = theVParams.Size(); + const gp_Torus& aTorus = myGeom->Torus(); + const gp_Pnt& aCenter = aTorus.Location(); + const gp_Dir& aXDir = aTorus.Position().XDirection(); + const gp_Dir& aYDir = aTorus.Position().YDirection(); + const gp_Dir& aZDir = aTorus.Position().Direction(); - myUParams.Resize(1, aNbU, false); - for (int i = 1; i <= aNbU; ++i) - { - myUParams.SetValue(i, theUParams.Value(theUParams.Lower() + i - 1)); - } - - myVParams.Resize(1, aNbV, false); - for (int j = 1; j <= aNbV; ++j) - { - myVParams.SetValue(j, theVParams.Value(theVParams.Lower() + j - 1)); - } + return {aCenter.X(), + aCenter.Y(), + aCenter.Z(), + aXDir.X(), + aXDir.Y(), + aXDir.Z(), + aYDir.X(), + aYDir.Y(), + aYDir.Z(), + aZDir.X(), + aZDir.Y(), + aZDir.Z(), + aTorus.MajorRadius(), + aTorus.MinorRadius()}; } //================================================================================================== -NCollection_Array2 GeomGridEval_Torus::EvaluateGrid() const +GeomGridEval_Torus::UContext GeomGridEval_Torus::computeUContext(const Data& theData, double theU) { - if (myGeom.IsNull() || myUParams.IsEmpty() || myVParams.IsEmpty()) - { - return NCollection_Array2(); - } + const double cosU = std::cos(theU); + const double sinU = std::sin(theU); - const int aNbU = myUParams.Size(); - const int aNbV = myVParams.Size(); - - NCollection_Array2 aResult(1, aNbU, 1, aNbV); - - // Extract torus data - const gp_Torus& aTorus = myGeom->Torus(); - const gp_Pnt& aCenter = aTorus.Location(); - const gp_Dir& aXDir = aTorus.Position().XDirection(); - const gp_Dir& aYDir = aTorus.Position().YDirection(); - const gp_Dir& aZDir = aTorus.Position().Direction(); - const double aMajorRadius = aTorus.MajorRadius(); - const double aMinorRadius = aTorus.MinorRadius(); - - const double aCX = aCenter.X(); - const double aCY = aCenter.Y(); - const double aCZ = aCenter.Z(); - const double aXX = aXDir.X(); - const double aXY = aXDir.Y(); - const double aXZ = aXDir.Z(); - const double aYX = aYDir.X(); - const double aYY = aYDir.Y(); - const double aYZ = aYDir.Z(); - const double aZX = aZDir.X(); - const double aZY = aZDir.Y(); - const double aZZ = aZDir.Z(); - - // Pre-compute V-dependent values (sin/cos of minor angle) - NCollection_Array1 aCosV(1, aNbV); - NCollection_Array1 aSinV(1, aNbV); - for (int iV = 1; iV <= aNbV; ++iV) - { - const double v = myVParams.Value(iV); - aCosV.SetValue(iV, std::cos(v)); - aSinV.SetValue(iV, std::sin(v)); - } - - for (int iU = 1; iU <= aNbU; ++iU) - { - const double u = myUParams.Value(iU); - const double cosU = std::cos(u); - const double sinU = std::sin(u); - - // Common term for X and Y components based on U - const double aDirUX = cosU * aXX + sinU * aYX; - const double aDirUY = cosU * aXY + sinU * aYY; - const double aDirUZ = cosU * aXZ + sinU * aYZ; - - for (int iV = 1; iV <= aNbV; ++iV) - { - const double cosV = aCosV.Value(iV); - const double sinV = aSinV.Value(iV); - - // K = MajorRadius + MinorRadius * cos(v) - const double K = aMajorRadius + aMinorRadius * cosV; - - // P = Center + K * (cosU*XDir + sinU*YDir) + MinorRadius * sinV * ZDir - aResult.SetValue(iU, - iV, - gp_Pnt(aCX + K * aDirUX + aMinorRadius * sinV * aZX, - aCY + K * aDirUY + aMinorRadius * sinV * aZY, - aCZ + K * aDirUZ + aMinorRadius * sinV * aZZ)); - } - } - return aResult; + return {cosU, + sinU, + cosU * theData.XX + sinU * theData.YX, // dirUX + cosU * theData.XY + sinU * theData.YY, // dirUY + cosU * theData.XZ + sinU * theData.YZ, // dirUZ + -sinU * theData.XX + cosU * theData.YX, // dDirUX + -sinU * theData.XY + cosU * theData.YY, // dDirUY + -sinU * theData.XZ + cosU * theData.YZ}; // dDirUZ } //================================================================================================== -NCollection_Array2 GeomGridEval_Torus::EvaluateGridD1() const +gp_Pnt GeomGridEval_Torus::computeD0(const Data& theData, const UContext& theUCtx, double theV) { - if (myGeom.IsNull() || myUParams.IsEmpty() || myVParams.IsEmpty()) - { - return NCollection_Array2(); - } + const double cosV = std::cos(theV); + const double sinV = std::sin(theV); - const int aNbU = myUParams.Size(); - const int aNbV = myVParams.Size(); + // K = MajorRadius + MinorRadius * cos(v) + const double K = theData.MajorRadius + theData.MinorRadius * cosV; - NCollection_Array2 aResult(1, aNbU, 1, aNbV); - - const gp_Torus& aTorus = myGeom->Torus(); - const gp_Pnt& aCenter = aTorus.Location(); - const gp_Dir& aXDir = aTorus.Position().XDirection(); - const gp_Dir& aYDir = aTorus.Position().YDirection(); - const gp_Dir& aZDir = aTorus.Position().Direction(); - const double aMajorRadius = aTorus.MajorRadius(); - const double aMinorRadius = aTorus.MinorRadius(); - - const double aCX = aCenter.X(); - const double aCY = aCenter.Y(); - const double aCZ = aCenter.Z(); - const double aXX = aXDir.X(); - const double aXY = aXDir.Y(); - const double aXZ = aXDir.Z(); - const double aYX = aYDir.X(); - const double aYY = aYDir.Y(); - const double aYZ = aYDir.Z(); - const double aZX = aZDir.X(); - const double aZY = aZDir.Y(); - const double aZZ = aZDir.Z(); - - NCollection_Array1 aCosV(1, aNbV); - NCollection_Array1 aSinV(1, aNbV); - for (int iV = 1; iV <= aNbV; ++iV) - { - const double v = myVParams.Value(iV); - aCosV.SetValue(iV, std::cos(v)); - aSinV.SetValue(iV, std::sin(v)); - } - - for (int iU = 1; iU <= aNbU; ++iU) - { - const double u = myUParams.Value(iU); - const double cosU = std::cos(u); - const double sinU = std::sin(u); - - // Direction vectors for U - // DirU = cosU*XDir + sinU*YDir - const double dirUX = cosU * aXX + sinU * aYX; - const double dirUY = cosU * aXY + sinU * aYY; - const double dirUZ = cosU * aXZ + sinU * aYZ; - - // DerivDirU = -sinU*XDir + cosU*YDir - const double dDirUX = -sinU * aXX + cosU * aYX; - const double dDirUY = -sinU * aXY + cosU * aYY; - const double dDirUZ = -sinU * aXZ + cosU * aYZ; - - for (int iV = 1; iV <= aNbV; ++iV) - { - const double cosV = aCosV.Value(iV); - const double sinV = aSinV.Value(iV); - - const double K = aMajorRadius + aMinorRadius * cosV; - - // P = Center + K * DirU + r * sinV * ZDir - const double pX = aCX + K * dirUX + aMinorRadius * sinV * aZX; - const double pY = aCY + K * dirUY + aMinorRadius * sinV * aZY; - const double pZ = aCZ + K * dirUZ + aMinorRadius * sinV * aZZ; - - // D1U = K * DerivDirU - const double dU1 = K * dDirUX; - const double dU2 = K * dDirUY; - const double dU3 = K * dDirUZ; - - // D1V = -r * sinV * DirU + r * cosV * ZDir - const double dV1 = -aMinorRadius * sinV * dirUX + aMinorRadius * cosV * aZX; - const double dV2 = -aMinorRadius * sinV * dirUY + aMinorRadius * cosV * aZY; - const double dV3 = -aMinorRadius * sinV * dirUZ + aMinorRadius * cosV * aZZ; - - aResult.ChangeValue(iU, - iV) = {gp_Pnt(pX, pY, pZ), gp_Vec(dU1, dU2, dU3), gp_Vec(dV1, dV2, dV3)}; - } - } - return aResult; + // P = Center + K * DirU + MinorRadius * sinV * ZDir + return gp_Pnt(theData.CX + K * theUCtx.dirUX + theData.MinorRadius * sinV * theData.ZX, + theData.CY + K * theUCtx.dirUY + theData.MinorRadius * sinV * theData.ZY, + theData.CZ + K * theUCtx.dirUZ + theData.MinorRadius * sinV * theData.ZZ); } //================================================================================================== -NCollection_Array2 GeomGridEval_Torus::EvaluateGridD2() const +GeomGridEval::SurfD1 GeomGridEval_Torus::computeD1(const Data& theData, + const UContext& theUCtx, + double theV) { - if (myGeom.IsNull() || myUParams.IsEmpty() || myVParams.IsEmpty()) - { - return NCollection_Array2(); - } + const double cosV = std::cos(theV); + const double sinV = std::sin(theV); - const int aNbU = myUParams.Size(); - const int aNbV = myVParams.Size(); + const double K = theData.MajorRadius + theData.MinorRadius * cosV; - NCollection_Array2 aResult(1, aNbU, 1, aNbV); + // D1U = K * DerivDirU + const double dU1 = K * theUCtx.dDirUX; + const double dU2 = K * theUCtx.dDirUY; + const double dU3 = K * theUCtx.dDirUZ; - const gp_Torus& aTorus = myGeom->Torus(); - const gp_Pnt& aCenter = aTorus.Location(); - const gp_Dir& aXDir = aTorus.Position().XDirection(); - const gp_Dir& aYDir = aTorus.Position().YDirection(); - const gp_Dir& aZDir = aTorus.Position().Direction(); - const double aMajorRadius = aTorus.MajorRadius(); - const double aMinorRadius = aTorus.MinorRadius(); + // D1V = -r * sinV * DirU + r * cosV * ZDir + const double dV1 = + -theData.MinorRadius * sinV * theUCtx.dirUX + theData.MinorRadius * cosV * theData.ZX; + const double dV2 = + -theData.MinorRadius * sinV * theUCtx.dirUY + theData.MinorRadius * cosV * theData.ZY; + const double dV3 = + -theData.MinorRadius * sinV * theUCtx.dirUZ + theData.MinorRadius * cosV * theData.ZZ; - const double aCX = aCenter.X(); - const double aCY = aCenter.Y(); - const double aCZ = aCenter.Z(); - const double aXX = aXDir.X(); - const double aXY = aXDir.Y(); - const double aXZ = aXDir.Z(); - const double aYX = aYDir.X(); - const double aYY = aYDir.Y(); - const double aYZ = aYDir.Z(); - const double aZX = aZDir.X(); - const double aZY = aZDir.Y(); - const double aZZ = aZDir.Z(); - - NCollection_Array1 aCosV(1, aNbV); - NCollection_Array1 aSinV(1, aNbV); - for (int iV = 1; iV <= aNbV; ++iV) - { - const double v = myVParams.Value(iV); - aCosV.SetValue(iV, std::cos(v)); - aSinV.SetValue(iV, std::sin(v)); - } - - for (int iU = 1; iU <= aNbU; ++iU) - { - const double u = myUParams.Value(iU); - const double cosU = std::cos(u); - const double sinU = std::sin(u); - - // DirU = cosU*XDir + sinU*YDir - const double dirUX = cosU * aXX + sinU * aYX; - const double dirUY = cosU * aXY + sinU * aYY; - const double dirUZ = cosU * aXZ + sinU * aYZ; - - // DerivDirU = -sinU*XDir + cosU*YDir - const double dDirUX = -sinU * aXX + cosU * aYX; - const double dDirUY = -sinU * aXY + cosU * aYY; - const double dDirUZ = -sinU * aXZ + cosU * aYZ; - - // Deriv2DirU = -cosU*XDir - sinU*YDir = -DirU - const double d2DirUX = -dirUX; - const double d2DirUY = -dirUY; - const double d2DirUZ = -dirUZ; - - for (int iV = 1; iV <= aNbV; ++iV) - { - const double cosV = aCosV.Value(iV); - const double sinV = aSinV.Value(iV); - - const double K = aMajorRadius + aMinorRadius * cosV; - - // P - const double pX = aCX + K * dirUX + aMinorRadius * sinV * aZX; - const double pY = aCY + K * dirUY + aMinorRadius * sinV * aZY; - const double pZ = aCZ + K * dirUZ + aMinorRadius * sinV * aZZ; - - // D1U = K * DerivDirU - const double dU1 = K * dDirUX; - const double dU2 = K * dDirUY; - const double dU3 = K * dDirUZ; - - // D1V = -r * sinV * DirU + r * cosV * ZDir - const double dV1 = -aMinorRadius * sinV * dirUX + aMinorRadius * cosV * aZX; - const double dV2 = -aMinorRadius * sinV * dirUY + aMinorRadius * cosV * aZY; - const double dV3 = -aMinorRadius * sinV * dirUZ + aMinorRadius * cosV * aZZ; - - // D2U = K * Deriv2DirU = -K * DirU - const double d2U1 = K * d2DirUX; - const double d2U2 = K * d2DirUY; - const double d2U3 = K * d2DirUZ; - - // D2V = -r * cosV * DirU - r * sinV * ZDir - const double d2V1 = -aMinorRadius * cosV * dirUX - aMinorRadius * sinV * aZX; - const double d2V2 = -aMinorRadius * cosV * dirUY - aMinorRadius * sinV * aZY; - const double d2V3 = -aMinorRadius * cosV * dirUZ - aMinorRadius * sinV * aZZ; - - // D2UV = -r * sinV * DerivDirU - const double d2UV1 = -aMinorRadius * sinV * dDirUX; - const double d2UV2 = -aMinorRadius * sinV * dDirUY; - const double d2UV3 = -aMinorRadius * sinV * dDirUZ; - - aResult.ChangeValue(iU, iV) = {gp_Pnt(pX, pY, pZ), - gp_Vec(dU1, dU2, dU3), - gp_Vec(dV1, dV2, dV3), - gp_Vec(d2U1, d2U2, d2U3), - gp_Vec(d2V1, d2V2, d2V3), - gp_Vec(d2UV1, d2UV2, d2UV3)}; - } - } - return aResult; + return {gp_Pnt(theData.CX + K * theUCtx.dirUX + theData.MinorRadius * sinV * theData.ZX, + theData.CY + K * theUCtx.dirUY + theData.MinorRadius * sinV * theData.ZY, + theData.CZ + K * theUCtx.dirUZ + theData.MinorRadius * sinV * theData.ZZ), + gp_Vec(dU1, dU2, dU3), + gp_Vec(dV1, dV2, dV3)}; } //================================================================================================== -NCollection_Array2 GeomGridEval_Torus::EvaluateGridD3() const +GeomGridEval::SurfD2 GeomGridEval_Torus::computeD2(const Data& theData, + const UContext& theUCtx, + double theV) { - if (myGeom.IsNull() || myUParams.IsEmpty() || myVParams.IsEmpty()) - { - return NCollection_Array2(); - } + const double cosV = std::cos(theV); + const double sinV = std::sin(theV); - const int aNbU = myUParams.Size(); - const int aNbV = myVParams.Size(); + const double K = theData.MajorRadius + theData.MinorRadius * cosV; - NCollection_Array2 aResult(1, aNbU, 1, aNbV); + // D1U = K * DerivDirU + const double dU1 = K * theUCtx.dDirUX; + const double dU2 = K * theUCtx.dDirUY; + const double dU3 = K * theUCtx.dDirUZ; - const gp_Torus& aTorus = myGeom->Torus(); - const gp_Pnt& aCenter = aTorus.Location(); - const gp_Dir& aXDir = aTorus.Position().XDirection(); - const gp_Dir& aYDir = aTorus.Position().YDirection(); - const gp_Dir& aZDir = aTorus.Position().Direction(); - const double aMajorRadius = aTorus.MajorRadius(); - const double aMinorRadius = aTorus.MinorRadius(); + // D1V = -r * sinV * DirU + r * cosV * ZDir + const double dV1 = + -theData.MinorRadius * sinV * theUCtx.dirUX + theData.MinorRadius * cosV * theData.ZX; + const double dV2 = + -theData.MinorRadius * sinV * theUCtx.dirUY + theData.MinorRadius * cosV * theData.ZY; + const double dV3 = + -theData.MinorRadius * sinV * theUCtx.dirUZ + theData.MinorRadius * cosV * theData.ZZ; - const double aCX = aCenter.X(); - const double aCY = aCenter.Y(); - const double aCZ = aCenter.Z(); - const double aXX = aXDir.X(); - const double aXY = aXDir.Y(); - const double aXZ = aXDir.Z(); - const double aYX = aYDir.X(); - const double aYY = aYDir.Y(); - const double aYZ = aYDir.Z(); - const double aZX = aZDir.X(); - const double aZY = aZDir.Y(); - const double aZZ = aZDir.Z(); + // D2U = K * Deriv2DirU = -K * DirU + const double d2U1 = -K * theUCtx.dirUX; + const double d2U2 = -K * theUCtx.dirUY; + const double d2U3 = -K * theUCtx.dirUZ; - NCollection_Array1 aCosV(1, aNbV); - NCollection_Array1 aSinV(1, aNbV); - for (int iV = 1; iV <= aNbV; ++iV) - { - const double v = myVParams.Value(iV); - aCosV.SetValue(iV, std::cos(v)); - aSinV.SetValue(iV, std::sin(v)); - } + // D2V = -r * cosV * DirU - r * sinV * ZDir + const double d2V1 = + -theData.MinorRadius * cosV * theUCtx.dirUX - theData.MinorRadius * sinV * theData.ZX; + const double d2V2 = + -theData.MinorRadius * cosV * theUCtx.dirUY - theData.MinorRadius * sinV * theData.ZY; + const double d2V3 = + -theData.MinorRadius * cosV * theUCtx.dirUZ - theData.MinorRadius * sinV * theData.ZZ; - for (int iU = 1; iU <= aNbU; ++iU) - { - const double u = myUParams.Value(iU); - const double cosU = std::cos(u); - const double sinU = std::sin(u); + // D2UV = -r * sinV * DerivDirU + const double d2UV1 = -theData.MinorRadius * sinV * theUCtx.dDirUX; + const double d2UV2 = -theData.MinorRadius * sinV * theUCtx.dDirUY; + const double d2UV3 = -theData.MinorRadius * sinV * theUCtx.dDirUZ; - // DirU = cosU*XDir + sinU*YDir - const double dirUX = cosU * aXX + sinU * aYX; - const double dirUY = cosU * aXY + sinU * aYY; - const double dirUZ = cosU * aXZ + sinU * aYZ; - - // DerivDirU = -sinU*XDir + cosU*YDir - const double dDirUX = -sinU * aXX + cosU * aYX; - const double dDirUY = -sinU * aXY + cosU * aYY; - const double dDirUZ = -sinU * aXZ + cosU * aYZ; - - for (int iV = 1; iV <= aNbV; ++iV) - { - const double cosV = aCosV.Value(iV); - const double sinV = aSinV.Value(iV); - - // R1 = r * cosV, R2 = r * sinV - const double R1 = aMinorRadius * cosV; - const double R2 = aMinorRadius * sinV; - - // K = R + r * cosV - const double K = aMajorRadius + R1; - - // A3 = R2 * cosU, A4 = R2 * sinU (for Som3) - const double A3 = R2 * cosU; - const double A4 = R2 * sinU; - // A5 = R1 * cosU, A6 = R1 * sinU (for Vvv, Vuvv) - const double A5 = R1 * cosU; - const double A6 = R1 * sinU; - - // Som1 = K * DirU (for P and D2U) - const double Som1X = K * dirUX; - const double Som1Y = K * dirUY; - const double Som1Z = K * dirUZ; - - // Som3 = R2 * (cosU*X + sinU*Y) = A3*X + A4*Y - const double Som3X = A3 * aXX + A4 * aYX; - const double Som3Y = A3 * aXY + A4 * aYY; - const double Som3Z = A3 * aXZ + A4 * aYZ; - - // P = Center + Som1 + R2*Z - const double pX = aCX + Som1X + R2 * aZX; - const double pY = aCY + Som1Y + R2 * aZY; - const double pZ = aCZ + Som1Z + R2 * aZZ; - - // D1U = K * DerivDirU - const double dU1 = K * dDirUX; - const double dU2 = K * dDirUY; - const double dU3 = K * dDirUZ; - - // D1V = -Som3 + R1*Z = -r*sinV*DirU + r*cosV*Z - const double dV1 = -Som3X + R1 * aZX; - const double dV2 = -Som3Y + R1 * aZY; - const double dV3 = -Som3Z + R1 * aZZ; - - // D2U = -Som1 = -K * DirU - const double d2U1 = -Som1X; - const double d2U2 = -Som1Y; - const double d2U3 = -Som1Z; - - // D2V = -R1*DirU - R2*Z = -(A5*X + A6*Y) - R2*Z - const double d2V1 = -A5 * aXX - A6 * aYX - R2 * aZX; - const double d2V2 = -A5 * aXY - A6 * aYY - R2 * aZY; - const double d2V3 = -A5 * aXZ - A6 * aYZ - R2 * aZZ; - - // D2UV = r*sinV*(sinU*X - cosU*Y) = A4*X - A3*Y - const double d2UV1 = A4 * aXX - A3 * aYX; - const double d2UV2 = A4 * aXY - A3 * aYY; - const double d2UV3 = A4 * aXZ - A3 * aYZ; - - // D3U = -D1U (Vuuu = Dif1 = -DerivDirU*K) - const double d3U1 = -dU1; - const double d3U2 = -dU2; - const double d3U3 = -dU3; - - // D3V = -D1V (Vvvv = Som3 - R1*Z) - const double d3V1 = Som3X - R1 * aZX; - const double d3V2 = Som3Y - R1 * aZY; - const double d3V3 = Som3Z - R1 * aZZ; - - // D3UUV = Som3 = r*sinV*(cosU*X + sinU*Y) - const double d3UUV1 = Som3X; - const double d3UUV2 = Som3Y; - const double d3UUV3 = Som3Z; - - // D3UVV = r*cosV*(sinU*X - cosU*Y) = A6*X - A5*Y - const double d3UVV1 = A6 * aXX - A5 * aYX; - const double d3UVV2 = A6 * aXY - A5 * aYY; - const double d3UVV3 = A6 * aXZ - A5 * aYZ; - - aResult.ChangeValue(iU, iV) = {gp_Pnt(pX, pY, pZ), - gp_Vec(dU1, dU2, dU3), - gp_Vec(dV1, dV2, dV3), - gp_Vec(d2U1, d2U2, d2U3), - gp_Vec(d2V1, d2V2, d2V3), - gp_Vec(d2UV1, d2UV2, d2UV3), - gp_Vec(d3U1, d3U2, d3U3), - gp_Vec(d3V1, d3V2, d3V3), - gp_Vec(d3UUV1, d3UUV2, d3UUV3), - gp_Vec(d3UVV1, d3UVV2, d3UVV3)}; - } - } - return aResult; + return {gp_Pnt(theData.CX + K * theUCtx.dirUX + theData.MinorRadius * sinV * theData.ZX, + theData.CY + K * theUCtx.dirUY + theData.MinorRadius * sinV * theData.ZY, + theData.CZ + K * theUCtx.dirUZ + theData.MinorRadius * sinV * theData.ZZ), + gp_Vec(dU1, dU2, dU3), + gp_Vec(dV1, dV2, dV3), + gp_Vec(d2U1, d2U2, d2U3), + gp_Vec(d2V1, d2V2, d2V3), + gp_Vec(d2UV1, d2UV2, d2UV3)}; } //================================================================================================== -NCollection_Array2 GeomGridEval_Torus::EvaluateGridDN(int theNU, int theNV) const +GeomGridEval::SurfD3 GeomGridEval_Torus::computeD3(const Data& theData, + const UContext& theUCtx, + double theV) { - if (myGeom.IsNull() || myUParams.IsEmpty() || myVParams.IsEmpty() || theNU < 0 || theNV < 0 - || (theNU + theNV) < 1) - { - return NCollection_Array2(); - } + const double cosV = std::cos(theV); + const double sinV = std::sin(theV); - const int aNbU = myUParams.Size(); - const int aNbV = myVParams.Size(); + // R1 = r * cosV, R2 = r * sinV + const double R1 = theData.MinorRadius * cosV; + const double R2 = theData.MinorRadius * sinV; - NCollection_Array2 aResult(1, aNbU, 1, aNbV); + // K = R + r * cosV + const double K = theData.MajorRadius + R1; + // A3 = R2 * cosU, A4 = R2 * sinU (for Som3) + const double A3 = R2 * theUCtx.cosU; + const double A4 = R2 * theUCtx.sinU; + // A5 = R1 * cosU, A6 = R1 * sinU (for Vvv, Vuvv) + const double A5 = R1 * theUCtx.cosU; + const double A6 = R1 * theUCtx.sinU; + + // Som1 = K * DirU (for P and D2U) + const double Som1X = K * theUCtx.dirUX; + const double Som1Y = K * theUCtx.dirUY; + const double Som1Z = K * theUCtx.dirUZ; + + // Som3 = R2 * (cosU*X + sinU*Y) = A3*X + A4*Y + const double Som3X = A3 * theData.XX + A4 * theData.YX; + const double Som3Y = A3 * theData.XY + A4 * theData.YY; + const double Som3Z = A3 * theData.XZ + A4 * theData.YZ; + + // D1U = K * DerivDirU + const double dU1 = K * theUCtx.dDirUX; + const double dU2 = K * theUCtx.dDirUY; + const double dU3 = K * theUCtx.dDirUZ; + + // D1V = -Som3 + R1*Z = -r*sinV*DirU + r*cosV*Z + const double dV1 = -Som3X + R1 * theData.ZX; + const double dV2 = -Som3Y + R1 * theData.ZY; + const double dV3 = -Som3Z + R1 * theData.ZZ; + + // D2U = -Som1 = -K * DirU + const double d2U1 = -Som1X; + const double d2U2 = -Som1Y; + const double d2U3 = -Som1Z; + + // D2V = -R1*DirU - R2*Z = -(A5*X + A6*Y) - R2*Z + const double d2V1 = -A5 * theData.XX - A6 * theData.YX - R2 * theData.ZX; + const double d2V2 = -A5 * theData.XY - A6 * theData.YY - R2 * theData.ZY; + const double d2V3 = -A5 * theData.XZ - A6 * theData.YZ - R2 * theData.ZZ; + + // D2UV = r*sinV*(sinU*X - cosU*Y) = A4*X - A3*Y + const double d2UV1 = A4 * theData.XX - A3 * theData.YX; + const double d2UV2 = A4 * theData.XY - A3 * theData.YY; + const double d2UV3 = A4 * theData.XZ - A3 * theData.YZ; + + // D3U = -D1U (Vuuu = Dif1 = -DerivDirU*K) + const double d3U1 = -dU1; + const double d3U2 = -dU2; + const double d3U3 = -dU3; + + // D3V = -D1V (Vvvv = Som3 - R1*Z) + const double d3V1 = Som3X - R1 * theData.ZX; + const double d3V2 = Som3Y - R1 * theData.ZY; + const double d3V3 = Som3Z - R1 * theData.ZZ; + + // D3UUV = Som3 = r*sinV*(cosU*X + sinU*Y) + const double d3UUV1 = Som3X; + const double d3UUV2 = Som3Y; + const double d3UUV3 = Som3Z; + + // D3UVV = r*cosV*(sinU*X - cosU*Y) = A6*X - A5*Y + const double d3UVV1 = A6 * theData.XX - A5 * theData.YX; + const double d3UVV2 = A6 * theData.XY - A5 * theData.YY; + const double d3UVV3 = A6 * theData.XZ - A5 * theData.YZ; + + return {gp_Pnt(theData.CX + Som1X + R2 * theData.ZX, + theData.CY + Som1Y + R2 * theData.ZY, + theData.CZ + Som1Z + R2 * theData.ZZ), + gp_Vec(dU1, dU2, dU3), + gp_Vec(dV1, dV2, dV3), + gp_Vec(d2U1, d2U2, d2U3), + gp_Vec(d2V1, d2V2, d2V3), + gp_Vec(d2UV1, d2UV2, d2UV3), + gp_Vec(d3U1, d3U2, d3U3), + gp_Vec(d3V1, d3V2, d3V3), + gp_Vec(d3UUV1, d3UUV2, d3UUV3), + gp_Vec(d3UVV1, d3UVV2, d3UVV3)}; +} + +//================================================================================================== + +gp_Vec GeomGridEval_Torus::computeDN(const Data& theData, + const UContext& theUCtx, + double theV, + int theNU, + int theNV) +{ // For torus P(u,v) = C + K(v)*DirU(u) + r*sin(v)*Z // where K(v) = R + r*cos(v), DirU(u) = cos(u)*X + sin(u)*Y // @@ -500,156 +273,387 @@ NCollection_Array2 GeomGridEval_Torus::EvaluateGridDN(int theNU, int the // - d^nu(DirU)/du^nu // - d^nv(r*sin(v))/dv^nv = r * d^nv(sin(v))/dv^nv (only contributes when nu == 0) - // Extract torus data - const gp_Torus& aTorus = myGeom->Torus(); - const gp_Dir& aXDir = aTorus.Position().XDirection(); - const gp_Dir& aYDir = aTorus.Position().YDirection(); - const gp_Dir& aZDir = aTorus.Position().Direction(); - const double aMajorRadius = aTorus.MajorRadius(); - const double aMinorRadius = aTorus.MinorRadius(); - - const double aXX = aXDir.X(); - const double aXY = aXDir.Y(); - const double aXZ = aXDir.Z(); - const double aYX = aYDir.X(); - const double aYY = aYDir.Y(); - const double aYZ = aYDir.Z(); - const double aZX = aZDir.X(); - const double aZY = aZDir.Y(); - const double aZZ = aZDir.Z(); + const double cosV = std::cos(theV); + const double sinV = std::sin(theV); // Phase for U derivatives (period 4) const int aPhaseU = theNU % 4; // Phase for V derivatives (period 4) const int aPhaseV = theNV % 4; - // Pre-compute V-dependent values - NCollection_Array1 aCosV(1, aNbV); - NCollection_Array1 aSinV(1, aNbV); - for (int iV = 1; iV <= aNbV; ++iV) + // Compute d^nu(DirU)/du^nu based on phase (using pre-computed cosU, sinU from UContext) + double dirDnX, dirDnY, dirDnZ; + switch (aPhaseU) { - const double v = myVParams.Value(iV); - aCosV.SetValue(iV, std::cos(v)); - aSinV.SetValue(iV, std::sin(v)); + case 0: // cos(u)*X + sin(u)*Y = DirU + dirDnX = theUCtx.dirUX; + dirDnY = theUCtx.dirUY; + dirDnZ = theUCtx.dirUZ; + break; + case 1: // -sin(u)*X + cos(u)*Y = DerivDirU + dirDnX = theUCtx.dDirUX; + dirDnY = theUCtx.dDirUY; + dirDnZ = theUCtx.dDirUZ; + break; + case 2: // -cos(u)*X - sin(u)*Y = -DirU + dirDnX = -theUCtx.dirUX; + dirDnY = -theUCtx.dirUY; + dirDnZ = -theUCtx.dirUZ; + break; + case 3: // sin(u)*X - cos(u)*Y = -DerivDirU + default: + dirDnX = -theUCtx.dDirUX; + dirDnY = -theUCtx.dDirUY; + dirDnZ = -theUCtx.dDirUZ; + break; } + // Compute d^nv(cos(v))/dv^nv based on phase + double dCosV; + switch (aPhaseV) + { + case 0: + dCosV = cosV; + break; + case 1: + dCosV = -sinV; + break; + case 2: + dCosV = -cosV; + break; + case 3: + default: + dCosV = sinV; + break; + } + + // Compute d^nv(sin(v))/dv^nv based on phase + double dSinV; + switch (aPhaseV) + { + case 0: + dSinV = sinV; + break; + case 1: + dSinV = cosV; + break; + case 2: + dSinV = -sinV; + break; + case 3: + default: + dSinV = -cosV; + break; + } + + // For the general derivative D_{nu,nv}: + // - If nv == 0: D = K(v) * d^nu(DirU) where K = R + r*cos(v) + // - If nv >= 1 and nu == 0: D = d^nv(K)/dv^nv * DirU + r * d^nv(sin(v))/dv^nv * Z + // - If nv >= 1 and nu >= 1: D = r * d^nv(cos(v))/dv^nv * d^nu(DirU)/du^nu + + double resX, resY, resZ; + + if (theNV == 0) + { + // Pure U derivative: K(v) * d^nu(DirU)/du^nu + const double K = theData.MajorRadius + theData.MinorRadius * cosV; + resX = K * dirDnX; + resY = K * dirDnY; + resZ = K * dirDnZ; + } + else if (theNU == 0) + { + // Pure V derivative with nu=0: d^nv(K)/dv^nv * DirU + r * d^nv(sin(v))/dv^nv * Z + // where d^nv(K)/dv^nv = r * d^nv(cos(v))/dv^nv + const double dK = theData.MinorRadius * dCosV; + resX = dK * dirDnX + theData.MinorRadius * dSinV * theData.ZX; + resY = dK * dirDnY + theData.MinorRadius * dSinV * theData.ZY; + resZ = dK * dirDnZ + theData.MinorRadius * dSinV * theData.ZZ; + } + else + { + // Mixed derivative with both nu >= 1 and nv >= 1: + // D = r * d^nv(cos(v))/dv^nv * d^nu(DirU)/du^nu + const double coeff = theData.MinorRadius * dCosV; + resX = coeff * dirDnX; + resY = coeff * dirDnY; + resZ = coeff * dirDnZ; + } + + return gp_Vec(resX, resY, resZ); +} + +//================================================================================================== + +NCollection_Array2 GeomGridEval_Torus::EvaluateGrid( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams) const +{ + if (myGeom.IsNull() || theUParams.IsEmpty() || theVParams.IsEmpty()) + { + return NCollection_Array2(); + } + + const int aNbU = theUParams.Size(); + const int aNbV = theVParams.Size(); + + NCollection_Array2 aResult(1, aNbU, 1, aNbV); + const Data aData = extractData(); + for (int iU = 1; iU <= aNbU; ++iU) { - const double u = myUParams.Value(iU); - const double cosU = std::cos(u); - const double sinU = std::sin(u); - - // Compute d^nu(DirU)/du^nu based on phase - double dirDnX, dirDnY, dirDnZ; - switch (aPhaseU) - { - case 0: // cos(u)*X + sin(u)*Y - dirDnX = cosU * aXX + sinU * aYX; - dirDnY = cosU * aXY + sinU * aYY; - dirDnZ = cosU * aXZ + sinU * aYZ; - break; - case 1: // -sin(u)*X + cos(u)*Y - dirDnX = -sinU * aXX + cosU * aYX; - dirDnY = -sinU * aXY + cosU * aYY; - dirDnZ = -sinU * aXZ + cosU * aYZ; - break; - case 2: // -cos(u)*X - sin(u)*Y - dirDnX = -cosU * aXX - sinU * aYX; - dirDnY = -cosU * aXY - sinU * aYY; - dirDnZ = -cosU * aXZ - sinU * aYZ; - break; - case 3: // sin(u)*X - cos(u)*Y - default: - dirDnX = sinU * aXX - cosU * aYX; - dirDnY = sinU * aXY - cosU * aYY; - dirDnZ = sinU * aXZ - cosU * aYZ; - break; - } + const double u = theUParams.Value(theUParams.Lower() + iU - 1); + const UContext aUCtx = computeUContext(aData, u); for (int iV = 1; iV <= aNbV; ++iV) { - const double cosV = aCosV.Value(iV); - const double sinV = aSinV.Value(iV); - - // Compute d^nv(cos(v))/dv^nv based on phase - double dCosV; - switch (aPhaseV) - { - case 0: - dCosV = cosV; - break; - case 1: - dCosV = -sinV; - break; - case 2: - dCosV = -cosV; - break; - case 3: - default: - dCosV = sinV; - break; - } - - // Compute d^nv(sin(v))/dv^nv based on phase - double dSinV; - switch (aPhaseV) - { - case 0: - dSinV = sinV; - break; - case 1: - dSinV = cosV; - break; - case 2: - dSinV = -sinV; - break; - case 3: - default: - dSinV = -cosV; - break; - } - - // For the general derivative D_{nu,nv}: - // - If nv == 0: D = K(v) * d^nu(DirU) where K = R + r*cos(v) - // But NU >= 1, so K is just multiplied - // - If nv >= 1 and nu == 0: D = d^nv(K)/dv^nv * DirU + r * d^nv(sin(v))/dv^nv * Z - // where d^nv(K)/dv^nv = r * d^nv(cos(v))/dv^nv - // - If nv >= 1 and nu >= 1: D = r * d^nv(cos(v))/dv^nv * d^nu(DirU)/du^nu - // (The Z term vanishes because it doesn't depend on U) - - double resX, resY, resZ; - - if (theNV == 0) - { - // Pure U derivative: K(v) * d^nu(DirU)/du^nu - const double K = aMajorRadius + aMinorRadius * cosV; - resX = K * dirDnX; - resY = K * dirDnY; - resZ = K * dirDnZ; - } - else if (theNU == 0) - { - // Pure V derivative with nu=0: d^nv(K)/dv^nv * DirU + r * d^nv(sin(v))/dv^nv * Z - // where d^nv(K)/dv^nv = r * d^nv(cos(v))/dv^nv - // and DirU = dirDnX, dirDnY, dirDnZ when aPhaseU = 0 - const double dK = aMinorRadius * dCosV; - resX = dK * dirDnX + aMinorRadius * dSinV * aZX; - resY = dK * dirDnY + aMinorRadius * dSinV * aZY; - resZ = dK * dirDnZ + aMinorRadius * dSinV * aZZ; - } - else - { - // Mixed derivative with both nu >= 1 and nv >= 1: - // D = r * d^nv(cos(v))/dv^nv * d^nu(DirU)/du^nu - const double coeff = aMinorRadius * dCosV; - resX = coeff * dirDnX; - resY = coeff * dirDnY; - resZ = coeff * dirDnZ; - } - - aResult.SetValue(iU, iV, gp_Vec(resX, resY, resZ)); + const double v = theVParams.Value(theVParams.Lower() + iV - 1); + aResult.SetValue(iU, iV, computeD0(aData, aUCtx, v)); } } + return aResult; +} +//================================================================================================== + +NCollection_Array2 GeomGridEval_Torus::EvaluateGridD1( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams) const +{ + if (myGeom.IsNull() || theUParams.IsEmpty() || theVParams.IsEmpty()) + { + return NCollection_Array2(); + } + + const int aNbU = theUParams.Size(); + const int aNbV = theVParams.Size(); + + NCollection_Array2 aResult(1, aNbU, 1, aNbV); + const Data aData = extractData(); + + for (int iU = 1; iU <= aNbU; ++iU) + { + const double u = theUParams.Value(theUParams.Lower() + iU - 1); + const UContext aUCtx = computeUContext(aData, u); + + for (int iV = 1; iV <= aNbV; ++iV) + { + const double v = theVParams.Value(theVParams.Lower() + iV - 1); + aResult.SetValue(iU, iV, computeD1(aData, aUCtx, v)); + } + } + return aResult; +} + +//================================================================================================== + +NCollection_Array2 GeomGridEval_Torus::EvaluateGridD2( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams) const +{ + if (myGeom.IsNull() || theUParams.IsEmpty() || theVParams.IsEmpty()) + { + return NCollection_Array2(); + } + + const int aNbU = theUParams.Size(); + const int aNbV = theVParams.Size(); + + NCollection_Array2 aResult(1, aNbU, 1, aNbV); + const Data aData = extractData(); + + for (int iU = 1; iU <= aNbU; ++iU) + { + const double u = theUParams.Value(theUParams.Lower() + iU - 1); + const UContext aUCtx = computeUContext(aData, u); + + for (int iV = 1; iV <= aNbV; ++iV) + { + const double v = theVParams.Value(theVParams.Lower() + iV - 1); + aResult.SetValue(iU, iV, computeD2(aData, aUCtx, v)); + } + } + return aResult; +} + +//================================================================================================== + +NCollection_Array2 GeomGridEval_Torus::EvaluateGridD3( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams) const +{ + if (myGeom.IsNull() || theUParams.IsEmpty() || theVParams.IsEmpty()) + { + return NCollection_Array2(); + } + + const int aNbU = theUParams.Size(); + const int aNbV = theVParams.Size(); + + NCollection_Array2 aResult(1, aNbU, 1, aNbV); + const Data aData = extractData(); + + for (int iU = 1; iU <= aNbU; ++iU) + { + const double u = theUParams.Value(theUParams.Lower() + iU - 1); + const UContext aUCtx = computeUContext(aData, u); + + for (int iV = 1; iV <= aNbV; ++iV) + { + const double v = theVParams.Value(theVParams.Lower() + iV - 1); + aResult.SetValue(iU, iV, computeD3(aData, aUCtx, v)); + } + } + return aResult; +} + +//================================================================================================== + +NCollection_Array2 GeomGridEval_Torus::EvaluateGridDN( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams, + int theNU, + int theNV) const +{ + if (myGeom.IsNull() || theUParams.IsEmpty() || theVParams.IsEmpty() || theNU < 0 || theNV < 0 + || (theNU + theNV) < 1) + { + return NCollection_Array2(); + } + + const int aNbU = theUParams.Size(); + const int aNbV = theVParams.Size(); + + NCollection_Array2 aResult(1, aNbU, 1, aNbV); + const Data aData = extractData(); + + for (int iU = 1; iU <= aNbU; ++iU) + { + const double u = theUParams.Value(theUParams.Lower() + iU - 1); + const UContext aUCtx = computeUContext(aData, u); + + for (int iV = 1; iV <= aNbV; ++iV) + { + const double v = theVParams.Value(theVParams.Lower() + iV - 1); + aResult.SetValue(iU, iV, computeDN(aData, aUCtx, v, theNU, theNV)); + } + } + return aResult; +} + +//================================================================================================== + +NCollection_Array1 GeomGridEval_Torus::EvaluatePoints( + const NCollection_Array1& theUVPairs) const +{ + if (myGeom.IsNull() || theUVPairs.IsEmpty()) + { + return NCollection_Array1(); + } + + const int aNbPts = theUVPairs.Size(); + NCollection_Array1 aResult(1, aNbPts); + const Data aData = extractData(); + + for (int iPt = 1; iPt <= aNbPts; ++iPt) + { + const gp_Pnt2d& aUV = theUVPairs.Value(theUVPairs.Lower() + iPt - 1); + const UContext aUCtx = computeUContext(aData, aUV.X()); + aResult.SetValue(iPt, computeD0(aData, aUCtx, aUV.Y())); + } + return aResult; +} + +//================================================================================================== + +NCollection_Array1 GeomGridEval_Torus::EvaluatePointsD1( + const NCollection_Array1& theUVPairs) const +{ + if (myGeom.IsNull() || theUVPairs.IsEmpty()) + { + return NCollection_Array1(); + } + + const int aNbPts = theUVPairs.Size(); + NCollection_Array1 aResult(1, aNbPts); + const Data aData = extractData(); + + for (int iPt = 1; iPt <= aNbPts; ++iPt) + { + const gp_Pnt2d& aUV = theUVPairs.Value(theUVPairs.Lower() + iPt - 1); + const UContext aUCtx = computeUContext(aData, aUV.X()); + aResult.SetValue(iPt, computeD1(aData, aUCtx, aUV.Y())); + } + return aResult; +} + +//================================================================================================== + +NCollection_Array1 GeomGridEval_Torus::EvaluatePointsD2( + const NCollection_Array1& theUVPairs) const +{ + if (myGeom.IsNull() || theUVPairs.IsEmpty()) + { + return NCollection_Array1(); + } + + const int aNbPts = theUVPairs.Size(); + NCollection_Array1 aResult(1, aNbPts); + const Data aData = extractData(); + + for (int iPt = 1; iPt <= aNbPts; ++iPt) + { + const gp_Pnt2d& aUV = theUVPairs.Value(theUVPairs.Lower() + iPt - 1); + const UContext aUCtx = computeUContext(aData, aUV.X()); + aResult.SetValue(iPt, computeD2(aData, aUCtx, aUV.Y())); + } + return aResult; +} + +//================================================================================================== + +NCollection_Array1 GeomGridEval_Torus::EvaluatePointsD3( + const NCollection_Array1& theUVPairs) const +{ + if (myGeom.IsNull() || theUVPairs.IsEmpty()) + { + return NCollection_Array1(); + } + + const int aNbPts = theUVPairs.Size(); + NCollection_Array1 aResult(1, aNbPts); + const Data aData = extractData(); + + for (int iPt = 1; iPt <= aNbPts; ++iPt) + { + const gp_Pnt2d& aUV = theUVPairs.Value(theUVPairs.Lower() + iPt - 1); + const UContext aUCtx = computeUContext(aData, aUV.X()); + aResult.SetValue(iPt, computeD3(aData, aUCtx, aUV.Y())); + } + return aResult; +} + +//================================================================================================== + +NCollection_Array1 GeomGridEval_Torus::EvaluatePointsDN( + const NCollection_Array1& theUVPairs, + int theNU, + int theNV) const +{ + if (myGeom.IsNull() || theUVPairs.IsEmpty() || theNU < 0 || theNV < 0 || (theNU + theNV) < 1) + { + return NCollection_Array1(); + } + + const int aNbPts = theUVPairs.Size(); + NCollection_Array1 aResult(1, aNbPts); + const Data aData = extractData(); + + for (int iPt = 1; iPt <= aNbPts; ++iPt) + { + const gp_Pnt2d& aUV = theUVPairs.Value(theUVPairs.Lower() + iPt - 1); + const UContext aUCtx = computeUContext(aData, aUV.X()); + aResult.SetValue(iPt, computeDN(aData, aUCtx, aUV.Y(), theNU, theNV)); + } return aResult; } diff --git a/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_Torus.hxx b/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_Torus.hxx index f2b2825eb4..df97e89b51 100644 --- a/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_Torus.hxx +++ b/src/ModelingData/TKG3d/GeomGridEval/GeomGridEval_Torus.hxx @@ -16,6 +16,7 @@ #include #include +#include #include #include #include @@ -33,8 +34,8 @@ //! Usage: //! @code //! GeomGridEval_Torus anEvaluator(myGeomTorus); -//! anEvaluator.SetUVParams(myUParams, myVParams); -//! NCollection_Array2 aGrid = anEvaluator.EvaluateGrid(); +//! NCollection_Array2 aGrid = anEvaluator.EvaluateGrid(myUParams, myVParams); +//! NCollection_Array1 aPoints = anEvaluator.EvaluatePoints(myUVPairs); //! @endcode class GeomGridEval_Torus { @@ -54,53 +55,134 @@ public: GeomGridEval_Torus(GeomGridEval_Torus&&) = delete; GeomGridEval_Torus& operator=(GeomGridEval_Torus&&) = delete; - //! Set UV parameters from two 1D arrays. - //! @param theUParams array of U parameter values (major angle) - //! @param theVParams array of V parameter values (minor angle) - Standard_EXPORT void SetUVParams(const TColStd_Array1OfReal& theUParams, - const TColStd_Array1OfReal& theVParams); - //! Returns the geometry handle. const Handle(Geom_ToroidalSurface)& Geometry() const { return myGeom; } - //! Returns number of U parameters. - int NbUParams() const { return myUParams.Size(); } + //! Evaluate grid points at Cartesian product of U and V parameters. + //! @param theUParams array of U parameter values (major angle) + //! @param theVParams array of V parameter values (minor angle) + //! @return 2D array of evaluated points (1-based indexing) + Standard_EXPORT NCollection_Array2 EvaluateGrid( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams) const; - //! Returns number of V parameters. - int NbVParams() const { return myVParams.Size(); } + //! Evaluate grid points with first partial derivatives. + //! @param theUParams array of U parameter values (major angle) + //! @param theVParams array of V parameter values (minor angle) + //! @return 2D array of SurfD1 (1-based indexing) + Standard_EXPORT NCollection_Array2 EvaluateGridD1( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams) const; - //! Evaluate all grid points. - //! @return 2D array of evaluated points (1-based indexing), - //! or empty array if geometry is null or no parameters set - Standard_EXPORT NCollection_Array2 EvaluateGrid() const; + //! Evaluate grid points with first and second partial derivatives. + //! @param theUParams array of U parameter values (major angle) + //! @param theVParams array of V parameter values (minor angle) + //! @return 2D array of SurfD2 (1-based indexing) + Standard_EXPORT NCollection_Array2 EvaluateGridD2( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams) const; - //! Evaluate all grid points with first partial derivatives. - //! @return 2D array of SurfD1 (1-based indexing), - //! or empty array if geometry is null or no parameters set - Standard_EXPORT NCollection_Array2 EvaluateGridD1() const; - - //! Evaluate all grid points with first and second partial derivatives. - //! @return 2D array of SurfD2 (1-based indexing), - //! or empty array if geometry is null or no parameters set - Standard_EXPORT NCollection_Array2 EvaluateGridD2() const; - - //! Evaluate all grid points with derivatives up to third order. - //! @return 2D array of SurfD3 (1-based indexing), - //! or empty array if geometry is null or no parameters set - Standard_EXPORT NCollection_Array2 EvaluateGridD3() const; + //! Evaluate grid points with derivatives up to third order. + //! @param theUParams array of U parameter values (major angle) + //! @param theVParams array of V parameter values (minor angle) + //! @return 2D array of SurfD3 (1-based indexing) + Standard_EXPORT NCollection_Array2 EvaluateGridD3( + const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams) const; //! Evaluate partial derivative d^(NU+NV)S/(dU^NU dV^NV) at all grid points. //! For orders 1-3, reuses EvaluateGridD1/D2/D3. //! For orders > 3, uses geometry DN method. + //! @param theUParams array of U parameter values (major angle) + //! @param theVParams array of V parameter values (minor angle) //! @param theNU derivative order in U direction //! @param theNV derivative order in V direction //! @return 2D array of derivative vectors (1-based indexing) - Standard_EXPORT NCollection_Array2 EvaluateGridDN(int theNU, int theNV) const; + Standard_EXPORT NCollection_Array2 EvaluateGridDN(const TColStd_Array1OfReal& theUParams, + const TColStd_Array1OfReal& theVParams, + int theNU, + int theNV) const; + + //! Evaluate points at arbitrary UV pairs. + //! @param theUVPairs array of UV coordinate pairs + //! @return 1D array of evaluated points (1-based indexing) + Standard_EXPORT NCollection_Array1 EvaluatePoints( + const NCollection_Array1& theUVPairs) const; + + //! Evaluate points with first partial derivatives. + //! @param theUVPairs array of UV coordinate pairs + //! @return 1D array of SurfD1 (1-based indexing) + Standard_EXPORT NCollection_Array1 EvaluatePointsD1( + const NCollection_Array1& theUVPairs) const; + + //! Evaluate points with first and second partial derivatives. + //! @param theUVPairs array of UV coordinate pairs + //! @return 1D array of SurfD2 (1-based indexing) + Standard_EXPORT NCollection_Array1 EvaluatePointsD2( + const NCollection_Array1& theUVPairs) const; + + //! Evaluate points with derivatives up to third order. + //! @param theUVPairs array of UV coordinate pairs + //! @return 1D array of SurfD3 (1-based indexing) + Standard_EXPORT NCollection_Array1 EvaluatePointsD3( + const NCollection_Array1& theUVPairs) const; + + //! Evaluate partial derivative at all UV pairs. + //! @param theUVPairs array of UV coordinate pairs + //! @param theNU derivative order in U direction + //! @param theNV derivative order in V direction + //! @return 1D array of derivative vectors (1-based indexing) + Standard_EXPORT NCollection_Array1 EvaluatePointsDN( + const NCollection_Array1& theUVPairs, + int theNU, + int theNV) const; private: + //! Pre-extracted torus data for efficient evaluation. + struct Data + { + double CX, CY, CZ; //!< Center coordinates + double XX, XY, XZ; //!< XDir coordinates + double YX, YY, YZ; //!< YDir coordinates + double ZX, ZY, ZZ; //!< ZDir coordinates + double MajorRadius; //!< Major radius + double MinorRadius; //!< Minor radius + }; + + //! Pre-computed U-dependent values for optimized grid evaluation. + struct UContext + { + double cosU, sinU; + double dirUX, dirUY, dirUZ; //!< DirU = cosU*XDir + sinU*YDir + double dDirUX, dDirUY, dDirUZ; //!< DerivDirU = -sinU*XDir + cosU*YDir + }; + + //! Extract torus data for evaluation. + Data extractData() const; + + //! Pre-compute U-dependent values. + static UContext computeUContext(const Data& theData, double theU); + + //! Compute point with pre-computed U context. + static gp_Pnt computeD0(const Data& theData, const UContext& theUCtx, double theV); + + //! Compute point with D1 with pre-computed U context. + static GeomGridEval::SurfD1 computeD1(const Data& theData, const UContext& theUCtx, double theV); + + //! Compute point with D2 with pre-computed U context. + static GeomGridEval::SurfD2 computeD2(const Data& theData, const UContext& theUCtx, double theV); + + //! Compute point with D3 with pre-computed U context. + static GeomGridEval::SurfD3 computeD3(const Data& theData, const UContext& theUCtx, double theV); + + //! Compute DN with pre-computed U context. + static gp_Vec computeDN(const Data& theData, + const UContext& theUCtx, + double theV, + int theNU, + int theNV); + Handle(Geom_ToroidalSurface) myGeom; - NCollection_Array1 myUParams; - NCollection_Array1 myVParams; }; #endif // _GeomGridEval_Torus_HeaderFile diff --git a/src/ModelingData/TKGeomBase/BndLib/BndLib_AddSurface.cxx b/src/ModelingData/TKGeomBase/BndLib/BndLib_AddSurface.cxx index e979334212..6706532b1c 100644 --- a/src/ModelingData/TKGeomBase/BndLib/BndLib_AddSurface.cxx +++ b/src/ModelingData/TKGeomBase/BndLib/BndLib_AddSurface.cxx @@ -461,9 +461,8 @@ void BndLib_AddSurface::Add(const Adaptor3d_Surface& S, GeomGridEval_Surface anEvaluator; anEvaluator.Initialize(S); - anEvaluator.SetUVParams(aUParams, aVParams); - const NCollection_Array2 aGrid = anEvaluator.EvaluateGrid(); + const NCollection_Array2 aGrid = anEvaluator.EvaluateGrid(aUParams, aVParams); for (Standard_Integer i = aGrid.LowerRow(); i <= aGrid.UpperRow(); i++) { for (Standard_Integer j = aGrid.LowerCol(); j <= aGrid.UpperCol(); j++) @@ -588,9 +587,8 @@ void BndLib_AddSurface::AddGenSurf(const Adaptor3d_Surface& S, GeomGridEval_Surface anEvaluator; anEvaluator.Initialize(S); - anEvaluator.SetUVParams(aUParams, aVParams); - const NCollection_Array2 aFineGrid = anEvaluator.EvaluateGrid(); + const NCollection_Array2 aFineGrid = anEvaluator.EvaluateGrid(aUParams, aVParams); // Extract main grid points (at even indices in fine grid: 1, 3, 5, ...) // Main grid indices in fine grid: iFine = 2*i - 1, jFine = 2*j - 1 diff --git a/src/ModelingData/TKGeomBase/Extrema/Extrema_GenExtCS.cxx b/src/ModelingData/TKGeomBase/Extrema/Extrema_GenExtCS.cxx index 1c20705b76..1dc707e348 100644 --- a/src/ModelingData/TKGeomBase/Extrema/Extrema_GenExtCS.cxx +++ b/src/ModelingData/TKGeomBase/Extrema/Extrema_GenExtCS.cxx @@ -256,9 +256,8 @@ void Extrema_GenExtCS::Initialize(const Adaptor3d_Surface& S, // Use batch grid evaluation for optimized surface point computation GeomGridEval_Surface anEvaluator; anEvaluator.Initialize(*myS); - anEvaluator.SetUVParams(aUParams, aVParams); - const NCollection_Array2 aGrid = anEvaluator.EvaluateGrid(); + const NCollection_Array2 aGrid = anEvaluator.EvaluateGrid(aUParams, aVParams); // aGrid is 1-based, mySurfPnts is 0-based - adjust indexing for (Standard_Integer aSUI = 0; aSUI <= myusample; aSUI++) diff --git a/src/ModelingData/TKGeomBase/Extrema/Extrema_GenExtPS.cxx b/src/ModelingData/TKGeomBase/Extrema/Extrema_GenExtPS.cxx index f1909247ac..96cc8b9993 100644 --- a/src/ModelingData/TKGeomBase/Extrema/Extrema_GenExtPS.cxx +++ b/src/ModelingData/TKGeomBase/Extrema/Extrema_GenExtPS.cxx @@ -541,9 +541,9 @@ void Extrema_GenExtPS::BuildGrid(const gp_Pnt& thePoint) GeomGridEval_Surface aGridEval; aGridEval.Initialize(*myS); - aGridEval.SetUVParams(myUParams->Array1(), myVParams->Array1()); - NCollection_Array2 aGridPoints = aGridEval.EvaluateGrid(); + NCollection_Array2 aGridPoints = + aGridEval.EvaluateGrid(myUParams->Array1(), myVParams->Array1()); if (aGridPoints.IsEmpty()) { @@ -873,9 +873,9 @@ void Extrema_GenExtPS::BuildTree() // Use unified grid evaluator for all surface types (optimized for BSpline, Bezier, etc.) GeomGridEval_Surface aGridEval; aGridEval.Initialize(*myS); - aGridEval.SetUVParams(myUParams->Array1(), myVParams->Array1()); - const NCollection_Array2 aGridPoints = aGridEval.EvaluateGrid(); + const NCollection_Array2 aGridPoints = + aGridEval.EvaluateGrid(myUParams->Array1(), myVParams->Array1()); for (NoU = 1; NoU <= myusample; NoU++) { diff --git a/src/ModelingData/TKGeomBase/Extrema/Extrema_GenExtSS.cxx b/src/ModelingData/TKGeomBase/Extrema/Extrema_GenExtSS.cxx index 0741068e06..a07a6cd17e 100644 --- a/src/ModelingData/TKGeomBase/Extrema/Extrema_GenExtSS.cxx +++ b/src/ModelingData/TKGeomBase/Extrema/Extrema_GenExtSS.cxx @@ -221,9 +221,8 @@ void Extrema_GenExtSS::Initialize(const Adaptor3d_Surface& S2, // Use batch grid evaluation for optimized surface point computation GeomGridEval_Surface anEvaluator; anEvaluator.Initialize(*myS2); - anEvaluator.SetUVParams(aUParams, aVParams); - const NCollection_Array2 aGrid = anEvaluator.EvaluateGrid(); + const NCollection_Array2 aGrid = anEvaluator.EvaluateGrid(aUParams, aVParams); for (Standard_Integer NoU = 1; NoU <= myusample; NoU++) { @@ -303,9 +302,8 @@ void Extrema_GenExtSS::Perform(const Adaptor3d_Surface& S1, // Use batch grid evaluation for optimized surface point computation GeomGridEval_Surface anEvaluator; anEvaluator.Initialize(S1); - anEvaluator.SetUVParams(aU1Params, aV1Params); - const NCollection_Array2 aGrid = anEvaluator.EvaluateGrid(); + const NCollection_Array2 aGrid = anEvaluator.EvaluateGrid(aU1Params, aV1Params); for (NoU1 = 1; NoU1 <= myusample; NoU1++) {