mirror of
https://github.com/Open-Cascade-SAS/OCCT.git
synced 2026-05-10 09:30:48 +08:00
Modeling Data - Update hardcoded AppCont_ContMatrices (#1117)
- Replaced old AppCont_ContMatrices.hxx/.cxx public interface with internal namespace-based .pxx header structure - Split legacy matrix data into separate internal headers (BB, InvM, IBP, IBT, VB) for better organization - Fixed out-of-bounds read in IBPMatrix for classe=26 by adding 3 missing data entries - Added comprehensive GTest suite with 9 tests covering all matrix functions and their mathematical properties
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -1,34 +0,0 @@
|
||||
// Copyright (c) 1995-1999 Matra Datavision
|
||||
// Copyright (c) 1999-2014 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#ifndef AppCont_ContMatrices_HeaderFile
|
||||
#define AppCont_ContMatrices_HeaderFile
|
||||
#include <math_Vector.hxx>
|
||||
|
||||
// Stockage des matrices de resolution d approxiamtion continue.
|
||||
// La classe est limitee a 26 pour MMatrix et InvMMatrix, (pas de contraintes)
|
||||
// pour IBPMatrix (contraintes de passage aux extremites)
|
||||
// et IBTMatrix (contraintes de tangence aux extremites).
|
||||
|
||||
void InvMMatrix(const int classe, math_Matrix& M);
|
||||
|
||||
void MMatrix(const int classe, math_Matrix& M);
|
||||
|
||||
void IBPMatrix(const int classe, math_Matrix& M);
|
||||
|
||||
void IBTMatrix(const int classe, math_Matrix& M);
|
||||
|
||||
void VBernstein(const int classe, const int nbpoints, math_Matrix& M);
|
||||
|
||||
#endif
|
||||
181
src/ModelingData/TKGeomBase/AppCont/AppCont_ContMatrices.pxx
Normal file
181
src/ModelingData/TKGeomBase/AppCont/AppCont_ContMatrices.pxx
Normal file
@@ -0,0 +1,181 @@
|
||||
// Copyright (c) 2025 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#ifndef AppCont_ContMatrices_HeaderFile
|
||||
#define AppCont_ContMatrices_HeaderFile
|
||||
|
||||
#include <math_Matrix.hxx>
|
||||
#include <Standard_DimensionError.hxx>
|
||||
|
||||
#include <AppCont_ContMatrices_BB.pxx>
|
||||
#include <AppCont_ContMatrices_InvM.pxx>
|
||||
#include <AppCont_ContMatrices_IBP.pxx>
|
||||
#include <AppCont_ContMatrices_IBT.pxx>
|
||||
#include <AppCont_ContMatrices_VB.pxx>
|
||||
|
||||
namespace AppCont_ContMatrices
|
||||
{
|
||||
|
||||
constexpr int THE_MAX_CLASSE = 26;
|
||||
constexpr int THE_MAX_MMATRIX_CLASSE = 24;
|
||||
constexpr int THE_MAX_NBPOINTS = 24;
|
||||
|
||||
//! Compute offset into the flat MMatrix/InvMMatrix array for a given classe.
|
||||
//! Data for classe values 2..24 are packed sequentially,
|
||||
//! each block having classe*classe entries.
|
||||
constexpr int MMatrixOffset(const int theClasse)
|
||||
{
|
||||
int anOffset = 0;
|
||||
for (int i = 2; i < theClasse; ++i)
|
||||
{
|
||||
anOffset += i * i;
|
||||
}
|
||||
return anOffset;
|
||||
}
|
||||
|
||||
//! Compute offset into the flat IBPMatrix array for a given classe.
|
||||
//! IBP result has size (classe-2)^2, starting from classe=3.
|
||||
constexpr int IBPMatrixOffset(const int theClasse)
|
||||
{
|
||||
int anOffset = 0;
|
||||
for (int i = 1; i < theClasse - 2; ++i)
|
||||
{
|
||||
anOffset += i * i;
|
||||
}
|
||||
return anOffset;
|
||||
}
|
||||
|
||||
//! Compute offset into the flat IBTMatrix array for a given classe.
|
||||
//! IBT result has size (classe-4)^2, starting from classe=5.
|
||||
constexpr int IBTMatrixOffset(const int theClasse)
|
||||
{
|
||||
int anOffset = 0;
|
||||
for (int i = 1; i < theClasse - 4; ++i)
|
||||
{
|
||||
anOffset += i * i;
|
||||
}
|
||||
return anOffset;
|
||||
}
|
||||
|
||||
//! Compute Bernstein basis mass matrix of size classe x classe.
|
||||
inline void MMatrix(const int classe, math_Matrix& M)
|
||||
{
|
||||
if (classe > THE_MAX_MMATRIX_CLASSE)
|
||||
{
|
||||
throw Standard_DimensionError("MMatrix: classe > 24");
|
||||
}
|
||||
|
||||
const double* aData = THE_BBMATRIX_DATA + MMatrixOffset(classe);
|
||||
int k = 0;
|
||||
for (int i = 1; i <= classe; ++i)
|
||||
{
|
||||
for (int j = 1; j <= classe; ++j)
|
||||
{
|
||||
M(i + M.LowerRow() - 1, j + M.LowerCol() - 1) = aData[k++];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//! Compute inverse of the Bernstein basis mass matrix.
|
||||
inline void InvMMatrix(const int classe, math_Matrix& InvM)
|
||||
{
|
||||
if (classe > THE_MAX_MMATRIX_CLASSE)
|
||||
{
|
||||
throw Standard_DimensionError("InvMMatrix: classe > 24");
|
||||
}
|
||||
|
||||
const double* aData = THE_INV_MMATRIX_DATA + MMatrixOffset(classe);
|
||||
int k = 0;
|
||||
for (int i = 1; i <= classe; ++i)
|
||||
{
|
||||
for (int j = 1; j <= classe; ++j)
|
||||
{
|
||||
InvM(i + InvM.LowerRow() - 1, j + InvM.LowerCol() - 1) = aData[k++];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//! Compute inverse of (MP^T * MP) for pass-point constraints,
|
||||
//! where MP is the submatrix of M with columns 2..classe-1.
|
||||
//! Result size: (classe-2) x (classe-2).
|
||||
inline void IBPMatrix(const int classe, math_Matrix& IBPMa)
|
||||
{
|
||||
if (classe > THE_MAX_CLASSE)
|
||||
{
|
||||
throw Standard_DimensionError("IBPMatrix: classe > 26");
|
||||
}
|
||||
|
||||
const int aDim = classe - 2;
|
||||
const double* aData = THE_IBPMATRIX_DATA + IBPMatrixOffset(classe);
|
||||
int k = 0;
|
||||
for (int i = 1; i <= aDim; ++i)
|
||||
{
|
||||
for (int j = 1; j <= aDim; ++j)
|
||||
{
|
||||
IBPMa(i + IBPMa.LowerRow() - 1, j + IBPMa.LowerCol() - 1) = aData[k++];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//! Compute inverse of (MT^T * MT) for tangency constraints,
|
||||
//! where MT is the submatrix of M with columns 3..classe-2.
|
||||
//! Result size: (classe-4) x (classe-4).
|
||||
inline void IBTMatrix(const int classe, math_Matrix& IBTMa)
|
||||
{
|
||||
if (classe > THE_MAX_CLASSE)
|
||||
{
|
||||
throw Standard_DimensionError("IBTMatrix: classe > 26");
|
||||
}
|
||||
|
||||
const int aDim = classe - 4;
|
||||
const double* aData = THE_IBTMATRIX_DATA + IBTMatrixOffset(classe);
|
||||
int k = 0;
|
||||
for (int i = 1; i <= aDim; ++i)
|
||||
{
|
||||
for (int j = 1; j <= aDim; ++j)
|
||||
{
|
||||
IBTMa(i + IBTMa.LowerRow() - 1, j + IBTMa.LowerCol() - 1) = aData[k++];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//! Evaluate Bernstein basis polynomials at Gauss-Legendre points.
|
||||
//! Result size: classe x nbpoints.
|
||||
inline void VBernstein(const int classe, const int nbpoints, math_Matrix& M)
|
||||
{
|
||||
if (classe > THE_MAX_CLASSE)
|
||||
{
|
||||
throw Standard_DimensionError("VBernstein: classe > 26");
|
||||
}
|
||||
if (nbpoints > THE_MAX_NBPOINTS)
|
||||
{
|
||||
throw Standard_DimensionError("VBernstein: nbpoints > 24");
|
||||
}
|
||||
|
||||
const int Som = static_cast<int>(300.0 * ((classe - 1) * classe / 2.0 - 1.0)
|
||||
+ classe * (nbpoints - 1) * nbpoints / 2.0);
|
||||
|
||||
const double* aData = THE_VBMATRIX_DATA + Som;
|
||||
for (int i = 1; i <= classe; ++i)
|
||||
{
|
||||
for (int j = 1; j <= nbpoints; ++j)
|
||||
{
|
||||
M(i, j) = *aData;
|
||||
++aData;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace AppCont_ContMatrices
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,4 @@
|
||||
// Created on: 1995-03-14
|
||||
// Created by: Modelistation
|
||||
// Copyright (c) 1995-1999 Matra Datavision
|
||||
// Copyright (c) 1999-2014 OPEN CASCADE SAS
|
||||
// Copyright (c) 2025 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
@@ -14,16 +11,14 @@
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#ifndef OCCT_DEBUG
|
||||
#define No_Standard_OutOfRange
|
||||
#define No_Standard_RangeError
|
||||
#endif
|
||||
#ifndef AppCont_ContMatrices_BB_HeaderFile
|
||||
#define AppCont_ContMatrices_BB_HeaderFile
|
||||
|
||||
#include <AppCont_ContMatrices.hxx>
|
||||
#include <math_Matrix.hxx>
|
||||
#include <Standard_DimensionError.hxx>
|
||||
namespace AppCont_ContMatrices
|
||||
{
|
||||
|
||||
static const double BBMatrix[] = {
|
||||
//! Legacy pre-computed Bernstein mass matrix data for classe 2..24.
|
||||
static const double THE_BBMATRIX_DATA[] = {
|
||||
|
||||
0.3333333333333333333333333,
|
||||
0.1666666666666666666666667,
|
||||
@@ -6252,21 +6247,6 @@ static const double BBMatrix[] = {
|
||||
|
||||
};
|
||||
|
||||
void MMatrix(const int classe, math_Matrix& M)
|
||||
{
|
||||
if (classe > 24)
|
||||
throw Standard_DimensionError("MMatrix: classe > 24");
|
||||
int i, j, k = 0, Som = 0;
|
||||
for (i = 2; i < classe; i++)
|
||||
{
|
||||
Som += (i) * (i);
|
||||
}
|
||||
for (i = 1; i <= classe; i++)
|
||||
{
|
||||
for (j = 1; j <= classe; j++)
|
||||
{
|
||||
M(i + M.LowerRow() - 1, j + M.LowerCol() - 1) = BBMatrix[Som + k];
|
||||
k++;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace AppCont_ContMatrices
|
||||
|
||||
#endif
|
||||
@@ -1,7 +1,4 @@
|
||||
// Created on: 1995-03-14
|
||||
// Created by: Modelistation
|
||||
// Copyright (c) 1995-1999 Matra Datavision
|
||||
// Copyright (c) 1999-2014 OPEN CASCADE SAS
|
||||
// Copyright (c) 2025 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
@@ -14,16 +11,14 @@
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#ifndef OCCT_DEBUG
|
||||
#define No_Standard_OutOfRange
|
||||
#define No_Standard_RangeError
|
||||
#endif
|
||||
#ifndef AppCont_ContMatrices_IBP_HeaderFile
|
||||
#define AppCont_ContMatrices_IBP_HeaderFile
|
||||
|
||||
#include <AppCont_ContMatrices.hxx>
|
||||
#include <math_Matrix.hxx>
|
||||
#include <Standard_DimensionError.hxx>
|
||||
namespace AppCont_ContMatrices
|
||||
{
|
||||
|
||||
static const double IBP[] = {
|
||||
//! Legacy pre-computed IBPMatrix data for classe 3..26.
|
||||
static const double THE_IBPMATRIX_DATA[] = {
|
||||
|
||||
26.47058823529411764705882,
|
||||
|
||||
@@ -4944,26 +4939,13 @@ static const double IBP[] = {
|
||||
-6.81419514385368135790775e18,
|
||||
9.7907165718702577801836e17,
|
||||
-8.95315514158120708669274e16,
|
||||
3.91616137389441893377958e15
|
||||
3.91616137389441893377958e15,
|
||||
1.06556449533824003906e13,
|
||||
-1.69077258069171362305e12,
|
||||
1.19821760754084976196e11
|
||||
|
||||
};
|
||||
|
||||
void IBPMatrix(const int classe, math_Matrix& IBPMa)
|
||||
{
|
||||
if (classe > 26)
|
||||
throw Standard_DimensionError("IBPMatrix: classe > 26");
|
||||
// math_Matrix IBPMa(1, classe-2, 1, classe-2);
|
||||
int i, j, k = 0, Som = 0;
|
||||
for (i = 1; i < classe - 2; i++)
|
||||
{
|
||||
Som += (i) * (i);
|
||||
}
|
||||
for (i = 1; i <= classe - 2; i++)
|
||||
{
|
||||
for (j = 1; j <= classe - 2; j++)
|
||||
{
|
||||
IBPMa(i + IBPMa.LowerRow() - 1, j + IBPMa.LowerCol() - 1) = IBP[Som + k];
|
||||
k++;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace AppCont_ContMatrices
|
||||
|
||||
#endif
|
||||
@@ -1,7 +1,4 @@
|
||||
// Created on: 1995-03-14
|
||||
// Created by: Modelistation
|
||||
// Copyright (c) 1995-1999 Matra Datavision
|
||||
// Copyright (c) 1999-2014 OPEN CASCADE SAS
|
||||
// Copyright (c) 2025 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
@@ -14,17 +11,14 @@
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#ifndef OCCT_DEBUG
|
||||
#define No_Standard_OutOfRange
|
||||
#define No_Standard_RangeError
|
||||
#endif
|
||||
#ifndef AppCont_ContMatrices_IBT_HeaderFile
|
||||
#define AppCont_ContMatrices_IBT_HeaderFile
|
||||
|
||||
#include <AppCont_ContMatrices.hxx>
|
||||
#include <math_Matrix.hxx>
|
||||
#include <Standard_DimensionError.hxx>
|
||||
|
||||
static const double IBT[] = {
|
||||
namespace AppCont_ContMatrices
|
||||
{
|
||||
|
||||
//! Legacy pre-computed IBTMatrix data for classe 5..26.
|
||||
static const double THE_IBTMATRIX_DATA[] = {
|
||||
111.9289340101522842639594,
|
||||
|
||||
1099.710340230071948294785, -1005.490755660339010609325, -1005.490755660339010609325,
|
||||
@@ -1324,22 +1318,6 @@ static const double IBT[] = {
|
||||
|
||||
};
|
||||
|
||||
void IBTMatrix(const int classe, math_Matrix& IBTMa)
|
||||
{
|
||||
if (classe > 26)
|
||||
throw Standard_DimensionError("IBTMatrix: classe > 26");
|
||||
// math_Matrix IBTMa(1, classe-4, 1, classe-4);
|
||||
int i, j, k = 0, Som = 0;
|
||||
for (i = 1; i < classe - 4; i++)
|
||||
{
|
||||
Som += (i) * (i);
|
||||
}
|
||||
for (i = 1; i <= classe - 4; i++)
|
||||
{
|
||||
for (j = 1; j <= classe - 4; j++)
|
||||
{
|
||||
IBTMa(i + IBTMa.LowerRow() - 1, j + IBTMa.LowerCol() - 1) = IBT[Som + k];
|
||||
k++;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace AppCont_ContMatrices
|
||||
|
||||
#endif
|
||||
6252
src/ModelingData/TKGeomBase/AppCont/AppCont_ContMatrices_InvM.pxx
Normal file
6252
src/ModelingData/TKGeomBase/AppCont/AppCont_ContMatrices_InvM.pxx
Normal file
File diff suppressed because it is too large
Load Diff
105627
src/ModelingData/TKGeomBase/AppCont/AppCont_ContMatrices_VB.pxx
Normal file
105627
src/ModelingData/TKGeomBase/AppCont/AppCont_ContMatrices_VB.pxx
Normal file
File diff suppressed because it is too large
Load Diff
@@ -22,7 +22,7 @@
|
||||
|
||||
#include <math.hxx>
|
||||
#include <AppParCurves_MultiPoint.hxx>
|
||||
#include <AppCont_ContMatrices.hxx>
|
||||
#include <AppCont_ContMatrices.pxx>
|
||||
#include <PLib.hxx>
|
||||
|
||||
//=================================================================================================
|
||||
@@ -212,7 +212,7 @@ AppCont_LeastSquare::AppCont_LeastSquare(const AppCont_Function& SSP,
|
||||
}
|
||||
}
|
||||
|
||||
VBernstein(classe, myNbPoints, myVB);
|
||||
AppCont_ContMatrices::VBernstein(classe, myNbPoints, myVB);
|
||||
|
||||
// Traitement du second membre:
|
||||
NCollection_Array1<double> tmppoints(1, nbcol);
|
||||
@@ -238,7 +238,7 @@ AppCont_LeastSquare::AppCont_LeastSquare(const AppCont_Function& SSP,
|
||||
{
|
||||
|
||||
math_Matrix InvM(1, classe, 1, classe);
|
||||
InvMMatrix(classe, InvM);
|
||||
AppCont_ContMatrices::InvMMatrix(classe, InvM);
|
||||
// Calcul direct des poles:
|
||||
|
||||
for (i = 1; i <= classe; i++)
|
||||
@@ -257,7 +257,7 @@ AppCont_LeastSquare::AppCont_LeastSquare(const AppCont_Function& SSP,
|
||||
else
|
||||
{
|
||||
math_Matrix M(1, classe, 1, classe);
|
||||
MMatrix(classe, M);
|
||||
AppCont_ContMatrices::MMatrix(classe, M);
|
||||
NCollection_Array1<gp_Pnt2d> aFixP2d(1, std::max(myNbP2d, 1));
|
||||
NCollection_Array1<gp_Pnt> aFixP(1, std::max(myNbP, 1));
|
||||
|
||||
@@ -453,11 +453,11 @@ AppCont_LeastSquare::AppCont_LeastSquare(const AppCont_Function& SSP,
|
||||
|
||||
if (bdeb == 2 && bfin == classe - 1 && classe <= 26)
|
||||
{
|
||||
IBPMatrix(classe, IBP);
|
||||
AppCont_ContMatrices::IBPMatrix(classe, IBP);
|
||||
}
|
||||
else if (bdeb == 3 && bfin == classe - 2 && classe <= 26)
|
||||
{
|
||||
IBTMatrix(classe, IBP);
|
||||
AppCont_ContMatrices::IBTMatrix(classe, IBP);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -2,12 +2,12 @@
|
||||
set(OCCT_AppCont_FILES_LOCATION "${CMAKE_CURRENT_LIST_DIR}")
|
||||
|
||||
set(OCCT_AppCont_FILES
|
||||
AppCont_ContMatrices.cxx
|
||||
AppCont_ContMatrices.hxx
|
||||
AppCont_ContMatrices_1.cxx
|
||||
AppCont_ContMatrices_2.cxx
|
||||
AppCont_ContMatrices_3.cxx
|
||||
AppCont_ContMatrices_4.cxx
|
||||
AppCont_ContMatrices_BB.pxx
|
||||
AppCont_ContMatrices.pxx
|
||||
AppCont_ContMatrices_IBP.pxx
|
||||
AppCont_ContMatrices_IBT.pxx
|
||||
AppCont_ContMatrices_InvM.pxx
|
||||
AppCont_ContMatrices_VB.pxx
|
||||
AppCont_Function.hxx
|
||||
AppCont_LeastSquare.cxx
|
||||
AppCont_LeastSquare.hxx
|
||||
|
||||
279
src/ModelingData/TKGeomBase/GTests/AppCont_ContMatrices_Test.cxx
Normal file
279
src/ModelingData/TKGeomBase/GTests/AppCont_ContMatrices_Test.cxx
Normal file
@@ -0,0 +1,279 @@
|
||||
// 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 <AppCont_ContMatrices.pxx>
|
||||
#include <math.hxx>
|
||||
#include <math_Matrix.hxx>
|
||||
#include <math_Vector.hxx>
|
||||
#include <Standard_DimensionError.hxx>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
static constexpr double THE_FORMULA_TOL = 1e-14;
|
||||
static constexpr double THE_SYMMETRY_TOL = 1e-15;
|
||||
|
||||
// Helper: compute binomial coefficient C(n,k).
|
||||
static double testBinomCoeff(int theN, int theK)
|
||||
{
|
||||
if (theK < 0 || theK > theN)
|
||||
{
|
||||
return 0.0;
|
||||
}
|
||||
if (theK > theN - theK)
|
||||
{
|
||||
theK = theN - theK;
|
||||
}
|
||||
double aResult = 1.0;
|
||||
for (int i = 0; i < theK; ++i)
|
||||
{
|
||||
aResult = aResult * (theN - i) / (i + 1);
|
||||
}
|
||||
return aResult;
|
||||
}
|
||||
|
||||
// Helper: compute Bernstein mass matrix entry M(i,j) for degree n (0-based).
|
||||
static double testBernsteinMassEntry(int theN, int theI, int theJ)
|
||||
{
|
||||
return testBinomCoeff(theN, theI) * testBinomCoeff(theN, theJ)
|
||||
/ ((2 * theN + 1) * testBinomCoeff(2 * theN, theI + theJ));
|
||||
}
|
||||
|
||||
// Verify MMatrix entries match the closed-form Bernstein mass matrix formula.
|
||||
TEST(AppCont_ContMatricesTest, MMatrix_MatchesFormula)
|
||||
{
|
||||
for (int aClasse = 2; aClasse <= 20; aClasse++)
|
||||
{
|
||||
math_Matrix aMat(1, aClasse, 1, aClasse);
|
||||
AppCont_ContMatrices::MMatrix(aClasse, aMat);
|
||||
|
||||
const int n = aClasse - 1;
|
||||
for (int i = 1; i <= aClasse; i++)
|
||||
{
|
||||
for (int j = 1; j <= aClasse; j++)
|
||||
{
|
||||
const double anExpected = testBernsteinMassEntry(n, i - 1, j - 1);
|
||||
EXPECT_NEAR(aMat(i, j), anExpected, THE_FORMULA_TOL)
|
||||
<< "classe=" << aClasse << " i=" << i << " j=" << j;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Verify MMatrix is symmetric.
|
||||
TEST(AppCont_ContMatricesTest, MMatrix_Symmetric)
|
||||
{
|
||||
for (int aClasse = 2; aClasse <= 20; aClasse++)
|
||||
{
|
||||
math_Matrix aMat(1, aClasse, 1, aClasse);
|
||||
AppCont_ContMatrices::MMatrix(aClasse, aMat);
|
||||
|
||||
for (int i = 1; i <= aClasse; i++)
|
||||
{
|
||||
for (int j = i + 1; j <= aClasse; j++)
|
||||
{
|
||||
EXPECT_NEAR(aMat(i, j), aMat(j, i), THE_SYMMETRY_TOL)
|
||||
<< "classe=" << aClasse << " i=" << i << " j=" << j;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Verify InvMMatrix * MMatrix = Identity for low-to-moderate degrees.
|
||||
TEST(AppCont_ContMatricesTest, InvMMatrix_IsInverse)
|
||||
{
|
||||
for (int aClasse = 2; aClasse <= 12; aClasse++)
|
||||
{
|
||||
math_Matrix aMat(1, aClasse, 1, aClasse);
|
||||
math_Matrix anInvMat(1, aClasse, 1, aClasse);
|
||||
AppCont_ContMatrices::MMatrix(aClasse, aMat);
|
||||
AppCont_ContMatrices::InvMMatrix(aClasse, anInvMat);
|
||||
|
||||
math_Matrix aProduct = anInvMat * aMat;
|
||||
for (int i = 1; i <= aClasse; i++)
|
||||
{
|
||||
for (int j = 1; j <= aClasse; j++)
|
||||
{
|
||||
const double anExpected = (i == j) ? 1.0 : 0.0;
|
||||
EXPECT_NEAR(aProduct(i, j), anExpected, 1e-8)
|
||||
<< "classe=" << aClasse << " i=" << i << " j=" << j;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Verify InvMMatrix is symmetric (inverse of symmetric matrix is symmetric).
|
||||
TEST(AppCont_ContMatricesTest, InvMMatrix_Symmetric)
|
||||
{
|
||||
for (int aClasse = 2; aClasse <= 24; aClasse++)
|
||||
{
|
||||
math_Matrix anInvMat(1, aClasse, 1, aClasse);
|
||||
AppCont_ContMatrices::InvMMatrix(aClasse, anInvMat);
|
||||
|
||||
for (int i = 1; i <= aClasse; i++)
|
||||
{
|
||||
for (int j = i + 1; j <= aClasse; j++)
|
||||
{
|
||||
EXPECT_DOUBLE_EQ(anInvMat(i, j), anInvMat(j, i))
|
||||
<< "classe=" << aClasse << " i=" << i << " j=" << j;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Verify strict legacy class limits for matrix providers.
|
||||
TEST(AppCont_ContMatricesTest, LegacyRangeLimits)
|
||||
{
|
||||
{
|
||||
math_Matrix aMat24(1, 24, 1, 24);
|
||||
math_Matrix aMat25(1, 25, 1, 25);
|
||||
EXPECT_NO_THROW(AppCont_ContMatrices::MMatrix(24, aMat24));
|
||||
EXPECT_THROW(AppCont_ContMatrices::MMatrix(25, aMat25), Standard_DimensionError);
|
||||
}
|
||||
|
||||
{
|
||||
math_Matrix anInv24(1, 24, 1, 24);
|
||||
math_Matrix anInv25(1, 25, 1, 25);
|
||||
EXPECT_NO_THROW(AppCont_ContMatrices::InvMMatrix(24, anInv24));
|
||||
EXPECT_THROW(AppCont_ContMatrices::InvMMatrix(25, anInv25), Standard_DimensionError);
|
||||
}
|
||||
|
||||
{
|
||||
math_Matrix anIBP26(1, 24, 1, 24);
|
||||
math_Matrix anIBP27(1, 25, 1, 25);
|
||||
EXPECT_NO_THROW(AppCont_ContMatrices::IBPMatrix(26, anIBP26));
|
||||
EXPECT_THROW(AppCont_ContMatrices::IBPMatrix(27, anIBP27), Standard_DimensionError);
|
||||
}
|
||||
|
||||
{
|
||||
math_Matrix anIBT26(1, 22, 1, 22);
|
||||
math_Matrix anIBT27(1, 23, 1, 23);
|
||||
EXPECT_NO_THROW(AppCont_ContMatrices::IBTMatrix(26, anIBT26));
|
||||
EXPECT_THROW(AppCont_ContMatrices::IBTMatrix(27, anIBT27), Standard_DimensionError);
|
||||
}
|
||||
|
||||
{
|
||||
math_Matrix aVB26x24(1, 26, 1, 24);
|
||||
math_Matrix aVB27x24(1, 27, 1, 24);
|
||||
math_Matrix aVB26x25(1, 26, 1, 25);
|
||||
EXPECT_NO_THROW(AppCont_ContMatrices::VBernstein(26, 24, aVB26x24));
|
||||
EXPECT_THROW(AppCont_ContMatrices::VBernstein(27, 24, aVB27x24), Standard_DimensionError);
|
||||
EXPECT_THROW(AppCont_ContMatrices::VBernstein(26, 25, aVB26x25), Standard_DimensionError);
|
||||
}
|
||||
}
|
||||
|
||||
// Verify IBPMatrix is symmetric for degrees where legacy data retains symmetry.
|
||||
TEST(AppCont_ContMatricesTest, IBPMatrix_Symmetric)
|
||||
{
|
||||
for (int aClasse = 3; aClasse <= 22; aClasse++)
|
||||
{
|
||||
const int aDim = aClasse - 2;
|
||||
math_Matrix anIBP(1, aDim, 1, aDim);
|
||||
AppCont_ContMatrices::IBPMatrix(aClasse, anIBP);
|
||||
|
||||
for (int i = 1; i <= aDim; i++)
|
||||
{
|
||||
for (int j = i + 1; j <= aDim; j++)
|
||||
{
|
||||
EXPECT_DOUBLE_EQ(anIBP(i, j), anIBP(j, i))
|
||||
<< "classe=" << aClasse << " i=" << i << " j=" << j;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Verify IBTMatrix is symmetric and has correct dimensions for all cached classes.
|
||||
TEST(AppCont_ContMatricesTest, IBTMatrix_Symmetric)
|
||||
{
|
||||
for (int aClasse = 5; aClasse <= 26; aClasse++)
|
||||
{
|
||||
const int aDim = aClasse - 4;
|
||||
math_Matrix anIBT(1, aDim, 1, aDim);
|
||||
AppCont_ContMatrices::IBTMatrix(aClasse, anIBT);
|
||||
|
||||
for (int i = 1; i <= aDim; i++)
|
||||
{
|
||||
for (int j = i + 1; j <= aDim; j++)
|
||||
{
|
||||
EXPECT_DOUBLE_EQ(anIBT(i, j), anIBT(j, i))
|
||||
<< "classe=" << aClasse << " i=" << i << " j=" << j;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Verify VBernstein values match direct Bernstein evaluation at Gauss points.
|
||||
TEST(AppCont_ContMatricesTest, VBernstein_MatchesBernsteinEval)
|
||||
{
|
||||
for (int aClasse = 2; aClasse <= 20; aClasse++)
|
||||
{
|
||||
for (int aNbPts : {4, 8, 12, 20, 24})
|
||||
{
|
||||
math_Matrix aVB(1, aClasse, 1, aNbPts);
|
||||
AppCont_ContMatrices::VBernstein(aClasse, aNbPts, aVB);
|
||||
|
||||
// Get Gauss-Legendre points on [-1, 1] and remap to [0, 1].
|
||||
math_Vector aGaussP(1, aNbPts);
|
||||
math::GaussPoints(aNbPts, aGaussP);
|
||||
|
||||
math_Vector aParams(1, aNbPts);
|
||||
const int aHalf = (aNbPts + 1) / 2;
|
||||
for (int k = 1; k <= aNbPts; k++)
|
||||
{
|
||||
const double aT = 0.5 * (1.0 + aGaussP(k));
|
||||
if (k <= aHalf)
|
||||
{
|
||||
aParams(aNbPts - k + 1) = aT;
|
||||
}
|
||||
else
|
||||
{
|
||||
aParams(k - aHalf) = aT;
|
||||
}
|
||||
}
|
||||
|
||||
const int n = aClasse - 1;
|
||||
for (int i = 1; i <= aClasse; i++)
|
||||
{
|
||||
const int aI = i - 1;
|
||||
const double aBinom = testBinomCoeff(n, aI);
|
||||
for (int j = 1; j <= aNbPts; j++)
|
||||
{
|
||||
const double aT = aParams(j);
|
||||
const double anExpected = aBinom * std::pow(aT, aI) * std::pow(1.0 - aT, n - aI);
|
||||
EXPECT_NEAR(aVB(i, j), anExpected, THE_FORMULA_TOL)
|
||||
<< "classe=" << aClasse << " nbpoints=" << aNbPts << " i=" << i << " j=" << j;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Verify partition of unity: sum of Bernstein basis values at each point should be 1.
|
||||
TEST(AppCont_ContMatricesTest, VBernstein_PartitionOfUnity)
|
||||
{
|
||||
for (int aClasse : {3, 5, 10, 20})
|
||||
{
|
||||
const int aNbPts = 12;
|
||||
math_Matrix aVB(1, aClasse, 1, aNbPts);
|
||||
AppCont_ContMatrices::VBernstein(aClasse, aNbPts, aVB);
|
||||
|
||||
for (int j = 1; j <= aNbPts; j++)
|
||||
{
|
||||
double aSum = 0.0;
|
||||
for (int i = 1; i <= aClasse; i++)
|
||||
{
|
||||
aSum += aVB(i, j);
|
||||
}
|
||||
EXPECT_NEAR(aSum, 1.0, 1e-13) << "classe=" << aClasse << " point=" << j;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
set(OCCT_TKGeomBase_GTests_FILES_LOCATION "${CMAKE_CURRENT_LIST_DIR}")
|
||||
|
||||
set(OCCT_TKGeomBase_GTests_FILES
|
||||
AppCont_ContMatrices_Test.cxx
|
||||
BndLib_Test.cxx
|
||||
Extrema_ExtPC_Test.cxx
|
||||
GCPnts_AbscissaPoint_Test.cxx
|
||||
|
||||
Reference in New Issue
Block a user