测试了 NurbsCurve 的 基础API :
D0点
D1一阶导
D2二阶导
高级API可以看成是 基础 API的组合。
最近距离/反求参数 : 用到了 D0 D1
长度/表面积/体积计算: 用到了 D0 D1
曲率计算: 用到了 D1 D2
求交计算: 用到了 D0 D1,有的求交方法会用到曲率
离散算法: D0
基础API效率测试代码
int main()
{
Geom_BSplineCurve* nurbs = ;
int N = 10000000;
double time = 0;
LARGE_INTEGER nFreq;
LARGE_INTEGER nBeginTime;
LARGE_INTEGER nEndTime;
QueryPerformanceFrequency(&nFreq);
QueryPerformanceCounter(&nBeginTime);//开始计时
for (int i = 0; i < N; i++)
{
gp_Pnt pt;
gp_Vec v1;
gp_Vec v2;
nurbs.D0(i*M_PI * 2 / N, pt);
nurbs.D1(i*M_PI * 2 / N, pt,v1);
nurbs.D2(i*M_PI * 2 / N, pt, v1, v2);
}
QueryPerformanceCounter(&nEndTime);//停止计时
time = (double)(nEndTime.QuadPart - nBeginTime.QuadPart) / (double)nFreq.QuadPart;//计算程序执行时间单位为s
cout << "opencascade 程序执行时间 :" << time * 1000 << "ms" << endl;
ON_NurbsCurve* opennurbs = ToOpenNurbsCurve(nurbs);
double time2 = 0;
LARGE_INTEGER nFreq2;
LARGE_INTEGER nBeginTime2;
LARGE_INTEGER nEndTime2;
QueryPerformanceFrequency(&nFreq2);
QueryPerformanceCounter(&nBeginTime2);//开始计时
for (int i = 0; i < N; i++)
{
ON_3dPoint point;
ON_3dVector first_derivative;
ON_3dVector second_derivative;
auto pt = opennurbs->PointAt(i*M_PI * 2 / N);
auto b1 = opennurbs->Ev1Der(i*M_PI * 2 / N, point, first_derivative);
auto b2 = opennurbs->Ev2Der(i*M_PI * 2 / N, point, first_derivative, second_derivative);
}
QueryPerformanceCounter(&nEndTime2);//停止计时
time2 = (double)(nEndTime2.QuadPart - nBeginTime2.QuadPart) / (double)nFreq2.QuadPart;//计算程序执行时间单位为s
cout << "opennurbs 程序执行时间 :" << time2 * 1000 << "ms" << endl;
}
曲线转化代码:
static ON_NurbsCurve* ToOpenNurbsCurve(const Handle(Geom_BSplineCurve) curve) {
bool isPeriodic = curve->IsPeriodic();
int isRat = curve->IsRational() ? 1 : 0;
int order = curve->Degree() + 1;
int nBcv = curve->NbPoles() + (isPeriodic ? 1 : 0);
int nBKs = nBcv + order;
auto OCCknots = curve->Knots();
int index = 0;
int nbK = curve->NbKnots();
auto nurbs = ON_NurbsCurve::New(3, isRat, order, nBcv);
// fill
for (int i = 1; i <= nbK; i++)
{
int multi = curve->Multiplicity(i);
if (!isPeriodic && (i == 1 || i == nbK)) {
multi--;
}
while (multi > 0) {
nurbs->m_knot[index++] = OCCknots.Value(i);
multi--;
}
}
auto occCv = curve->Poles();
auto occW = curve->Weights();
index = 0;
for (int i = 1; i <= nBcv; i++)
{
int ii = i;
if (isPeriodic && i == nBcv) {
ii = 1;
}
double w = (occW == NULL)? 1 : occW->Value(ii);
int base = (i-1) * nurbs->m_cv_stride;
auto pt = occCv.Value(ii);
nurbs->m_cv[base + 0] = pt.X() * w;
nurbs->m_cv[base + 1] = pt.Y() * w;
nurbs->m_cv[base + 2] = pt.Z() * w;
if (isRat) {
nurbs->m_cv[base + 3] = w;
}
}
return nurbs;
}
测试了一个圆和半圆转Nurbs:
opencascade 程序执行时间 :3463.91ms
opennurbs 程序执行时间 :2008.1ms
opennurbs的耗时为opencascade耗时的 58%
读者也可以在自己机器上测试下对比效果~