OPEN CASCADE BSpline Curve Interpolation

eryar@163.com

Abstract. Global curve interpolation to point data is a way to construct curves. The paper focus on the interpolate algorithm in OPEN CASCADE, and give a simple example to demonstrate the usage of the GeomAPI_Interpolate class.

Key Words. Interpolate, NURBS, BSpline, OPEN CASCADE

1.Introduction

曲线曲面拟合Curve and Surface Fitting的方式可以分为两类:插值interpolation和逼近approximation。采用插值的方式时,所创建的曲线或曲面必须精确地满足所给的数据条件,例如曲线通过所给的插值点。采用逼近的方式时,创建的曲线或曲面不必精确地满足所给的数据条件,只要在一定的误差范围内接近即可,如下图所示:

Figure 1.1 A curve interpolating five points and end derivatives(The NURBS Book)

Figure 1.2 A curve approximating points(The NURBS Book)

本文先简要介绍B样条插值的原理,再结合OPEN CASCADE源码说明如何对给定点插值B样条曲线及OPEN CASCADE中插值曲线的一些注意事项。

2.Global Interpolation

假设给定一组数据点{Qk},k=0,1,…n,我们想要用一条p次非有理B样条曲线插值于这些点。如果我们为每个点Qk指定了一个参数值uk,并且选定了一个合适的节点矢量U,我们就可以建立一个系数矩阵为(n+1)x(n+1)的线性方程组:

n+1个控制点Pi是未知量。剩下的问题是如何确定Qk对应的参数值uk及节点矢量U,这将影响到曲线的形状和参数化。常见的选取uk的方法有均匀参数化法、弦长参数化法和向心参数化法。

2.1 Equally Spaced 均匀参数法

假设参数限定在[0,1]范围内,那么

当参数范围为[a,b]时,

均匀参数化法是最简单的构造参数的方法,但是不推荐采用这种方法,因为当数据点分布步均匀时,会产生很奇怪的形状,如打圈自交。

Figure 2.1 B-Spline curve interpolation with the uniformly spaced method[1]

2.2 Chord Length 弦长参数法

令d为总弦长,且把参数范围限定在[0,1]之间,则:

这是最常用的方法,并且一般用它就足够了,考虑到弦长参数化接近曲线的均匀参数化,在这种意义下,它给出了曲线的一个“好”的参数化。

2.3 Centripetal Method 向心参数法

这是一个更新的方法,当数据点急转弯变化时,这个方法能得到比弦长参数化更好的结果。

3.BSpline Interpolation in OPEN CASCADE

OPEN CASCADE对曲线的插值是通过GeomAPI包中的GeomAPI_Interpolate实现的。由其代码注释可知,这个类的功能是可以对一系列点进行插值得到C2连续的B样条曲线,当对插值点处的切矢不作要求时。对点直接插值的构造函数为:

GeomAPI_Interpolate (const Handle< TColgp_HArray1OfPnt > &Points, const Standard_Boolean PeriodicFlag, const Standard_Real Tolerance)

其中参数Points为插值点,PeriodicFlag为是否周期曲线,Tolerance是对插值点进行检查用的容差。Tolerance容易产生误解,根据插值曲线的定义,插值曲线是要求通过插值点的,所以不存在插值得到的曲线和插值点之间的容差。

经过查看OPEN CASCADE中插值曲线的源码,可以得出对曲线进行插值的步骤如下:

v 检查是否有重复的插值点CheckPoints;

v 生成参数BuildParameters;

v 使用BSplCLib::Interpolate()进行插值;

v 根据参数及次数生成系数矩阵,再结合插值点,对系数矩阵和插值点组成的方程组进行求解。

检查插值点代码如下:

static Standard_Boolean CheckPoints(const TColgp_Array1OfPnt& PointArray,
const Standard_Real Tolerance)
{
Standard_Integer ii ;
Standard_Real tolerance_squared = Tolerance * Tolerance,
distance_squared ;
Standard_Boolean result = Standard_True ;
for (ii = PointArray.Lower() ; result && ii < PointArray.Upper() ; ii++) {
distance_squared =
PointArray.Value(ii).SquareDistance(PointArray.Value(ii+)) ;
result = (distance_squared >= tolerance_squared) ;
}
return result ; }

由上述代码可知,Tolerance主要是用于检查插值点是否在容差范围内有重合现象。生成参数代码如下:

static void  BuildParameters(const Standard_Boolean        PeriodicFlag,
const TColgp_Array1OfPnt& PointsArray,
Handle(TColStd_HArray1OfReal)& ParametersPtr)
{
Standard_Integer ii,
index ;
Standard_Real distance ;
Standard_Integer
num_parameters = PointsArray.Length() ;
if (PeriodicFlag) {
num_parameters += ;
}
ParametersPtr =
new TColStd_HArray1OfReal(,
num_parameters) ;
ParametersPtr->SetValue(,0.0e0) ;
index = ;
for (ii = PointsArray.Lower() ; ii < PointsArray.Upper() ; ii++) {
distance =
PointsArray.Value(ii).Distance(PointsArray.Value(ii+)) ;
ParametersPtr->SetValue(index,
ParametersPtr->Value(ii) + distance) ;
index += ;
}
if (PeriodicFlag) {
distance =
PointsArray.Value(PointsArray.Upper()).
Distance(PointsArray.Value(PointsArray.Lower())) ;
ParametersPtr->SetValue(index,
ParametersPtr->Value(ii) + distance) ;
}
}

由上述代码可知,OPEN CASCADE插值生成参数的方法如下:

不是上述三种常用方法的之一,和弦长参数化法类似,但是没有去除以总弦长。生成节点矢量之前为了得到曲线的次数,做了如下处理:

if (num_poles ==  &&   !myTangentRequest)  {
degree = ;
}
else if (num_poles == && !myTangentRequest) {
degree = ;
num_distinct_knots = ;
}
else {
degree = ;
num_poles += ;
if (myTangentRequest)
for (ii = myTangentFlags->Lower() + ;
ii < myTangentFlags->Upper() ; ii++) {
if (myTangentFlags->Value(ii)) {
num_poles += ;
}
}
}

由上述代码可知,插值要求至少有两个插值点。当只有两个插值点时,插值曲线次数为1,即为直线;当有三个插值点且没有切矢的要求时,插值曲线次数为2次;当插值点数多于3个时,插值曲线次数为3。即对于多于三个点进行插值时,最高只能得到3次曲线,也即C2连续的曲线。进行B样条插值的代码如下:

void  BSplCLib::Interpolate(const Standard_Integer         Degree,
const TColStd_Array1OfReal& FlatKnots,
const TColStd_Array1OfReal& Parameters,
const TColStd_Array1OfInteger& ContactOrderArray,
const Standard_Integer ArrayDimension,
Standard_Real& Poles,
Standard_Integer& InversionProblem)
{
Standard_Integer ErrorCode,
UpperBandWidth,
LowerBandWidth ;
// Standard_Real *PolesArray = &Poles ;
math_Matrix InterpolationMatrix(, Parameters.Length(),
, * Degree + ) ;
ErrorCode =
BSplCLib::BuildBSpMatrix(Parameters,
ContactOrderArray,
FlatKnots,
Degree,
InterpolationMatrix,
UpperBandWidth,
LowerBandWidth) ;
if(ErrorCode)
Standard_OutOfRange::Raise("BSplCLib::Interpolate"); ErrorCode =
BSplCLib::FactorBandedMatrix(InterpolationMatrix,
UpperBandWidth,
LowerBandWidth,
InversionProblem) ;
if(ErrorCode)
Standard_OutOfRange::Raise("BSplCLib::Interpolate"); ErrorCode =
BSplCLib::SolveBandedSystem(InterpolationMatrix,
UpperBandWidth,
LowerBandWidth,
ArrayDimension,
Poles) ;
if(ErrorCode)
Standard_OutOfRange::Raise("BSplCLib::Interpolate");
}

先是根据参数及插值曲线次数生成系数矩阵,再对系数矩阵和插值点构成的方程组进行求解,计算出B样条曲线的控制顶点Poles。有了节点矢量,次数及控制顶点,B样条就确定下来了:

myCurve =
new Geom_BSplineCurve(poles,
myParameters->Array1(),
mults,
degree) ;
myIsDone = Standard_True ;

OPEN CASCADE提供的插值接口使用还是很简单的,如对已经知点进行插值,其用法如下:

int main(int argc, char* argv[])
{
Handle_TColgp_HArray1OfPnt aPoints = new TColgp_HArray1OfPnt aPoints(, );
Handle_Geom_BSplineCurve aBSplineCurve; aPoints.SetValue(, gp_Pnt(0.0, 0.0, 0.0));
aPoints.SetValue(, gp_Pnt(1.0, 1.0, 0.0));
aPoints.SetValue(, gp_Pnt(2.0, 6.0, 3.0)); GeomAPI_Interpolate aInterpolater(aPoints, Standard_False, Precision::Approximation()); if (aInterpolater.IsDone())
{
aBSplineCurve = aInterpolater.Curve(); GeomTools::Dump(aBSplineCurve, std::cout);
}
}

4.Conclusion

综上所述,对给定点进行B样条插值时,需要考虑参数值及节点矢量的选择。参数值和节点矢量确定后,剩下就是利用B样条基函数对给定点的参数计算得到的系数组成的线性方程进行求解。

在使用OPEN CASCADE的曲线插值类GeomAPI_Interpolate时,需要注间容差Tolerance是用来对插值点进行检查的,且插值得到的曲线最高只能是三次曲线。

5.Acknowledgments

首先,感谢cnblog提供了一个表现自己的舞台http://www.cppblog.com/eryar/,能在网上和世界连通,知道不是一个人在战斗。

其次,感谢OPEN CASCADE的开源分享,才得以学到几何造型相关的知识,比起直接啃国内教材来,学习效率不可同日而语。正如“Talk is cheap, show me the code”所说,将代码和书本结合起来学习时,收获更大。

最后,感谢国内外友人对我的肯定和鼓励,他们自强不息,激情创业的精神总是让人兴奋。

生活的理想就是为了理想的生活The ideal of life is to live for ideals!人生充满了起起落落,关键在于在顶端时尽情享受,在低谷时不失勇气。

6.References

1. Hongxin Zhang, Jieqing Feng. B-Spline Interpolation and Approximation. Zhejiang University.  2006-12-18. http://www.cad.zju.edu.cn/home/zhx/GM/009/00-bsia.pdf

2. Les Piegl, Wayne Tiller. The NURBS Book. Springer-Verlag. 1995

3. 赵罡, 穆国旺, 王拉柱译. 非均匀有理B样条. 清华大学出版社. 1995

4. 易大义, 陈道琦. 数值分析引论. 浙江大学出版社. 1998

OPEN CASCADE BSpline Curve Interpolation的更多相关文章

  1. Convert BSpline Curve to Arc Spline in OpenCASCADE

    Convert BSpline Curve to Arc Spline in OpenCASCADE eryar@163.com Abstract. The paper based on OpenCA ...

  2. OpenCascade B-Spline Basis Function

    OpenCascade B-Spline Basis Function eryar@163.com Abstract. B-splines are quite a bit more flexible ...

  3. Open CASCADE Technology: IGES Support

    2015/6/4 Open CASCADE Technology: IGES Support http://www.opencascade.org/doc/occt­6.7.0/overview/ht ...

  4. OpenCASCADE Conic to BSpline Curves-Circle

    OpenCASCADE Conic to BSpline Curves-Circle eryar@163.com Abstract. The conic sections and circles pl ...

  5. OpenCASCADE Conic to BSpline Curves-Hyperbola

    OpenCASCADE Conic to BSpline Curves-Hyperbola eryar@163.com Abstract. Rational Bezier Curve can repr ...

  6. OpenCASCADE Conic to BSpline Curves-Parabola

    OpenCASCADE Conic to BSpline Curves-Parabola eryar@163.com Abstract. Rational Bezier Curve can repre ...

  7. Geometry Curve of OpenCascade BRep

    Geometry Curve of OpenCascade BRep eryar@163.com 摘要Abstract:几何曲线是参数表示的曲线 ,在边界表示中其数据存在于BRep_TEdge中,BR ...

  8. B-spline Curves 学习之B样条曲线的导数(8)

    Derivatives of a B-spline Curve 本博客转自前人的博客的翻译版本,前几章节是原来博主的翻译内容,但是后续章节博主不在提供翻译,后续章节我在完成相关的翻译学习. (原来博客 ...

  9. Render OpenCascade Geometry Curves in OpenSceneGraph

    在OpenSceneGraph中绘制OpenCascade的曲线 Render OpenCascade Geometry Curves in OpenSceneGraph eryar@163.com ...

随机推荐

  1. jQuery Ajax请求(关于火狐下SyntaxError: missing ] after element list ajax返回json,var json = eval("("+data+")"); 报错)

    $.ajax({    contentType: "application/x-www-form-urlencoded;charset=UTF-8" ,    type: &quo ...

  2. Java throws Exception、try、catch

    throws Exception是方法后面接的 意思是向上级抛出异常 try{}里面的异常会被外面的catch捕捉到 抛出异常是throw new Exception("异常"); ...

  3. 【Linux】Too many open files

    ZA 的BOSS 最近出现Too many open files 异常,这个异常一般是由于打开文件数过多引起, 最常见原因是某些连接一致未关闭 记录一些排查用到的指令 查看每个用户最大允许打开文件数量 ...

  4. c# Repeater中CommandArgument传多个参数

    <ItemTemplate>                    <div onmouseover="javascript:this.style.cursor='hand ...

  5. JS二维数组排序组合

    需求是这样的:http://q.cnblogs.com/q/29093/ 这里简述一下: 现在有一个不确定长度的数组.比如:var temp=[["Fu","Hai&qu ...

  6. Web前端开发推荐阅读书籍

    前言 前端工程师在中国兴起也就5年左右,以前公司里没有专门前端工程师的这个职位,很多前端方面的任务都是由全栈工程师来完成,有的基础一点的后台或者设计的帮助分担一些.但是随着互联网的快速发展,特别是所谓 ...

  7. Unity3D UGUI之ScrollView弹簧效果

    unity3d版本5.3.2p4 UGUI中ScrollView包含Viewport(Content) ScrollView包含脚本.其Movement Type一共3个选项.Elastic就是弹簧效 ...

  8. iPhone6/6 Plus兩款大屏智能機

    蘋果終於順應時代潮流,於今年推出了iPhone6/6 Plus兩款大屏智能機.但很快就有人開始懷念老款iPhone的“一手掌控”,畢竟不是所有人都有一雙大手.不過近期就有傳言稱,蘋果將於明年重新推出一 ...

  9. ORM数据层框架的设计热点:更新指定的列的几种设计方案

    ORM框架的定义:对象-关系映射(Object/Relation Mapping,简称ORM) 常见的是:数据库结构=>映射Object(实体属性)=>基于实体类的操作. 还有一种:数据库 ...

  10. iOS开发系列--Objective-C之KVC、KVO

    概述 由于ObjC主要基于Smalltalk进行设计,因此它有很多类似于Ruby.Python的动态特性,例如动态类型.动态加载.动态绑定等.今天我们着重介绍ObjC中的键值编码(KVC).键值监听( ...