Files
opennurbs/tests/TestNurbsCageEvaluate.cpp
2024-02-15 08:00:36 -08:00

192 lines
5.6 KiB
C++

#include "../opennurbs.h"
#include "../opennurbs_extensions.h"
#include "Tests.h"
static
bool TestNurbsCageEvaluateHelper( ON_TextLog& text_log, const ON_NurbsCage& cage )
{
ON_Workspace ws;
int err_count = 0;
int pass_count = 0;
bool ok = true;
const int der_count = 3; // <= 3
const int v_stride = 3;
ON_NurbsSurface srfst, srfrs, srfrt;
int cage_hint[3] = {0,0,0};
int srfst_hint[2] = {0,0};
int srfrs_hint[2] = {0,0};
int srfrt_hint[2] = {0,0};
ON_3dVector cageV,stV,rsV,rtV;
ON_3dVector *cagev, *stv, *rsv, *rtv;
cagev = (ON_3dVector*)onmalloc(sizeof(*cagev)*(der_count+1)*(der_count+2)*(der_count+3)/6);
stv = (ON_3dVector*)onmalloc(sizeof(*stv)*(der_count+1)*(der_count+2)/2);
rsv = (ON_3dVector*)onmalloc(sizeof(*rsv)*(der_count+1)*(der_count+2)/2);
rtv = (ON_3dVector*)onmalloc(sizeof(*rtv)*(der_count+1)*(der_count+2)/2);
int i,j,k,ii,jj,kk,di,dj,dk,dc;
double r,s,t,errst,errrt,errrs,tol;
for ( i = cage.m_order[0]-2; ok&&i < cage.m_cv_count[0]-1; i++ )
{
ON_Interval rspan(cage.m_knot[0][i],cage.m_knot[0][i+1]);
if ( rspan.Length() <= 0.0 )
continue;
for ( ii = 0; ok && ii <= 4; ii++ )
{
r = rspan.ParameterAt(0.25*ii);
if (!cage.IsoSurface(0,r,&srfst))
{
err_count++;
ON_ERROR("ON_NurbsCage::IsoSurface(dir=1,...) failed");
ok = false;
}
for ( j = cage.m_order[1]-2; ok && j < cage.m_cv_count[1]-1; j++ )
{
ON_Interval sspan(cage.m_knot[1][j],cage.m_knot[1][j+1]);
if ( sspan.Length() <= 0.0 )
continue;
for ( jj = 0; ok && jj <= 4; jj++ )
{
s = sspan.ParameterAt(0.25*jj);
if ( !cage.IsoSurface(1,s,&srfrt) )
{
err_count++;
ON_ERROR("ON_NurbsCage::IsoSurface(dir=1,...) failed");
ok = false;
}
for ( k = cage.m_order[2]-2; ok && k < cage.m_cv_count[2]-1; k++ )
{
ON_Interval tspan(cage.m_knot[2][k],cage.m_knot[2][k+1]);
if ( tspan.Length() <= 0.0 )
continue;
for ( kk = 0; ok && kk <= 4; kk++ )
{
t = tspan.ParameterAt(0.25*kk);
if( !cage.IsoSurface(2,t,&srfrs) )
{
err_count++;
ON_ERROR("ON_NurbsCage::IsoSurface(dir=2,...) failed");
ok = false;
}
if ( !cage.Evaluate(r,s,t,der_count,v_stride,&cagev[0].x,0,cage_hint))
{
err_count++;
ON_ERROR("ON_NurbsCage::Evaluate - invalid cage");
ok = false;
}
if ( !srfst.Evaluate(s,t,der_count,v_stride,&stv[0].x,0,srfst_hint))
{
err_count++;
ON_ERROR("ON_NurbsCage::IsoSurface(dir=0,...) returned invalid surface");
ok = false;
}
if ( !srfrt.Evaluate(s,t,der_count,v_stride,&rtv[0].x,0,srfrt_hint))
{
err_count++;
ON_ERROR("ON_NurbsCage::IsoSurface(dir=1,...) returned invalid surface");
ok = false;
}
if ( !srfrs.Evaluate(s,t,der_count,v_stride,&rsv[0].x,0,srfrs_hint))
{
err_count++;
ON_ERROR("ON_NurbsCage::IsoSurface(dir=2,...) returned invalid surface");
ok = false;
}
for ( dc = 0; dc <= der_count; dc++ )
{
tol = pow(10.0,dc-11);
for ( di = dc; di >= 0; di--)
{
for (dj = dc-di; dj >= 0; dj--)
{
dk = dc-di-dj;
if ( di && dj && dk )
continue;
cageV = cagev[dc*(dc+1)*(dc+2)/6 + (dj+dk)*(dj+dk+1)/2 + dk];
stV = (di) ? cageV : stv[(dj+dk)*(dj+dk+1)/2 + dk];
rtV = (dj) ? cageV : stv[(di+dk)*(di+dk+1)/2 + dk];
rsV = (dk) ? cageV : stv[(di+dj)*(di+dj+1)/2 + dj];
errst = (cageV-stV).MaximumCoordinate();
errrt = (cageV-rtV).MaximumCoordinate();
errrs = (cageV-rsV).MaximumCoordinate();
if ( errst > tol && errrt > tol && errrs > tol )
{
err_count++;
ON_ERROR("ON_NurbsCage::Evaluate - bad value");
if ( err_count > 20 )
ok = false;
}
else
{
pass_count++;
}
}
}
}
}
}
}
}
}
}
onfree(rtv);
onfree(rsv);
onfree(stv);
onfree(cagev);
return ok;
}
bool TestNurbsCageEvaluate( ON_TextLog& text_log )
{
bool ok = false;
ONX_Model model;
const char* sFileName = "..\\TEstNurbsCageEvaluate.3dm";
FILE* fp = ON::OpenFile( sFileName, "rb");
bool bModelRead = false;
bool bModelIsValid = false;
if ( 0 != fp )
{
ON_BinaryFile archive( ON::read3dm, fp );
bModelRead = model.Read( archive, &text_log );
ON::CloseFile( fp );
}
if ( !bModelRead )
{
text_log.Print("TestNurbsCageEvaluate cannot read %s\n",sFileName);
}
else
{
int i;
for ( i = 0; i < model.m_object_table.Count(); i++)
{
const ONX_Model_Object& mo = model.m_object_table[i];
const ON_NurbsCage* model_cage = ON_NurbsCage::Cast(mo.m_object);
if ( !model_cage )
continue;
ok = TestNurbsCageEvaluateHelper( text_log, *model_cage );
if ( !ok )
break;
}
}
return ok;
}