OpenCASCADE Conic to BSpline Curves-Parabola

eryar@163.com

Abstract. Rational Bezier Curve can represent conic curves such as circle, ellipse, hyperbola, .etc. But how to convert a conic curve to BSpline curve is still question, i.e. Represent a conic curve in BSpline form. Parabola curve is the most simple conic curve, that the parabola does not require rational functions. Let’s begin from the simplest one...

Key Words. OpenCASCADE, Convert, Parabola, BSplineCurve, Conic Curve

1. Introduction

圆锥截线(Conic或称为二次曲线)和圆在CAD/CAM中有着广泛应用。毫无疑问NURBS的一个最大优点就是既能精确表示圆锥截线和圆,也能精确表示自由曲线曲面。这个优点的意义是方便编程,使所有的曲线可以采用统一的数据结构来表示。通过有理的方式可以精确来表示这些二次曲线,那么给定一个二次曲线的相关参数(如圆的圆心和半径等),如何构造出对应的NURBS曲线呢?

在圆锥截线中,抛物线(Parabola)是不需要用有理函数来表示的,所以是形式最简单的二次曲线。先从简单的着手,来学习如何将一个抛物线从隐式方程的形式转换成NURBS曲线形式。

先简要回顾一下高中数学中关于抛物线的相关知识点,如下图所示为我上高中时数学课本中的关于抛物线方程及焦点坐标(focus)和准线(directrix)方程一个图表:

Figure 1.1 Parabola Fuction

OpenCASCADE中对应抛物线的隐式方程表示的类是gp_Parab/gp_Parab2d。本文主要介绍OpenCASCADE中如何将gp_Parab2d转换为NURBS曲线。

2. Parametric Representations

在CAD/CAM的应用中,圆锥截线有两种重要的参数表示形式:有理形式和最大内接面积形式(Rational and maximum inscribed area forms)。表示抛物线的这两种形式是相同的,如下所示:

圆锥截线的有些有理参数表示形式可能是有相当差的参数化,即均匀分布的参数值对应于曲线上分布很不均匀的点。利用线性有理函数对有理曲线进行重新参数化可以改变(因而可能改善)其参数化。

假设C(u)=(x(u), y(u))是一条在标准位置的圆锥截线的参数表示。现在我们对抛物线给出的参数方程也是上式,它是一个好的参数化:对于任意给定的整数n和参数边界a与b,取n个等间隔分布的参数:

点C(u1),C(u2), ..., C(un)形成曲线上n-1边多边形,它的闭合多边形具有最大的内接面积。

根据最大内接面积表示法可以求出节点矢量。

3. Conversion Algorithm

将隐式表示的抛物线方程转换为NURBS(有理Bezier是NURBS的特例)曲线需要确定NURBS的以下信息:节点矢量,权因子,次数,控制顶点。

因为抛物线是二次曲线,所以对应的NURBS曲线的次数也为2。因为是用有理的Bezier曲线来表示的,所以需要的控制顶点数为3。

其中节点矢量可由最大内接面积表示法来确定。下面来确定剩余的所需数据。由有理Bezier曲线的公式得二次有理Bezier曲线弧的表示形式为:

称k为形状不变因子,公式如下所示:

可以证明同一组控制顶点选取不同 的权因子,只要形状因子k相等,则由它们决定的二次有理Bezier曲线是同一条曲线段,不同的权因对应不同的参数化,而且可以根据形状不变因子对二次曲线进行分类:

v K=0;       表示退化的二次曲线:一对直线段P0P1和P1P2;

v K∈[0,1];  表示双曲线;

v K=1;       表示抛物线;

v K∈[1, +∞]; 表示椭圆;

v K=+∞;     表示连接P0和P2的直线段;

习惯上我们选择ω0=ω2=1称为标准参数化。此时由形状因子k公式得抛物线的ω1=1。所以抛物线的权因子也因此而确定,即ω0=ω1=ω2=1。

Figure 3.1 不同的权因子ω1 定义的圆锥截线

由二次有理Bezier曲线公式可知,当u=0和u=1时,C(0)=P0, C(1)=P2,即曲线通过特征多边形的首末顶点。由此可确定抛物线的两个控制顶点P0和P2,现在只剩下最后一个P1顶点未确定。

P1点可以由二次有理Bezier曲线的公式列方程计算得出,但这并不是一个方便的方法。一种更方便的方法是:在这条曲线上指定第三个点,该点对应于某个特定的参数,例如u=1/2。点S=C(1/2)称为圆锥截线的肩点(shoulder point),如图3.1所示。将u=1/2代入二次有理Bezier公式得:

其中M是弦P0P2的中点。肩点S=C(1/2)。所以由上式可确定P1点。下面将各个控制顶点的计算列出如下所示:

设抛物线的起止区间为[UF,UL],则因为曲线通过特征多边形的顶点,所以通过首点P0=(X0,Y0)=(X0,UF)。又由抛物线的参数方程可知:

同理可计算出通过末点P2的坐标,将他们分别列出如下:

由计算肩点S的公式,将Sy=Y1=C(u1)=(UF+UL)/2代入可得:

所以P1点的坐标为:

至此,抛物线的三个控制顶点P0,P1,P2都已计算出来了。即抛物线的NURBS表示所需的数据都已经得到了。下面看看OpenCASCADE中的实现代码。

4. Code Analysis

OpenCASCADE的Math工具集中有个包Covert用来将圆锥曲线曲面转换为NURBS曲线曲面。其中转换抛物线的类为:Convert_ParabolaToBSplineCurve,实现代码如下所示:

//=======================================================================
//function : Convert_ParabolaToBSplineCurve
//purpose :
//=======================================================================
Convert_ParabolaToBSplineCurve::Convert_ParabolaToBSplineCurve
(const gp_Parab2d& Prb,
const Standard_Real U1 ,
const Standard_Real U2 )
: Convert_ConicToBSplineCurve (MaxNbPoles, MaxNbKnots, TheDegree)
{
Standard_DomainError_Raise_if( Abs(U2 - U1) < Epsilon(.),
"Convert_ParabolaToBSplineCurve"); Standard_Real UF = Min (U1, U2);
Standard_Real UL = Max( U1, U2);
Standard_Real p = Prb.Parameter(); nbPoles = ;
nbKnots = ;
isperiodic = Standard_False;
knots->ChangeArray1()() = UF; mults->ChangeArray1()() = ;
knots->ChangeArray1()() = UL; mults->ChangeArray1()() = ; weights->ChangeArray1()() = .;
weights->ChangeArray1()() = .;
weights->ChangeArray1()() = .; gp_Dir2d Ox = Prb.Axis().XDirection();
gp_Dir2d Oy = Prb.Axis().YDirection();
Standard_Real S = ( Ox.X() * Oy.Y() - Ox.Y() * Oy.X() > .) ? : -; // poles expressed in the reference mark
poles->ChangeArray1()() =
gp_Pnt2d( ( UF * UF) / ( . * p), S * UF );
poles->ChangeArray1()() =
gp_Pnt2d( ( UF * UL) / ( . * p), S * ( UF + UL) / . );
poles->ChangeArray1()() =
gp_Pnt2d( ( UL * UL) / ( . * p), S * UL ); // replace the bspline in the mark of the parabola
gp_Trsf2d Trsf;
Trsf.SetTransformation( Prb.Axis().XAxis(), gp::OX2d());
poles->ChangeArray1()().Transform( Trsf);
poles->ChangeArray1()().Transform( Trsf);
poles->ChangeArray1()().Transform( Trsf);
}

由上面的代码可知,先设置曲线次数为2,再设置节点矢量为[UF,UF,UF,UL,UL,UL],即首参数UF和末参数UL的重数皆为3,由节点矢量可知转换后的NURBS曲线为Bezier曲线。

三个控制顶点对应的权因也都设置为1。三个控制顶点计算方法按上一节中所述。关键是P1点的计算。上面的计算方法仅为个人观点,欢迎讨论交流。

最后根据有理Bezier曲线的仿射不变性:对有理Bezier曲线进行旋转、平移和缩放变换,其表达式不变,只是控制点发生了改变。新的控制点可以通过对原控制点作变换得到。即要对有理Bezier曲线进行仿射变换,只需对其控制点作变换即可。

圆锥截线的转换类的使用是很简单的,且计算都是在构造函数中完成。下面给出一个将抛物线转换为NURBS曲线的具体示例来说明其用法。

/*
* Copyright (c) 2014 eryar All Rights Reserved.
*
* File : Main.cpp
* Author : eryar@163.com
* Date : 2014-10-02 20:46
* Version : 1.0v
*
* Description : OpenCASCADE conic to BSpline curve-Parabola.
*
* Key words : OpenCascade, Parabola, BSpline Curve, Convert
*/ #define HAVE_CONFIG_H #include <gp_Parab2d.hxx> #include <Convert_ParabolaToBSplineCurve.hxx> void DumpConvertorInfo(const Convert_ConicToBSplineCurve &theConvertor)
{
Standard_Integer aCounter = ; std::cout << "Convert Result" << std::endl;
std::cout << "Degree: " << theConvertor.Degree() << std::endl;
std::cout << "Periodic: " << (theConvertor.IsPeriodic() ? "yes" : "no") << std::endl; std::cout << "Knots: " << std::endl;
for (Standard_Integer i = ;i <= theConvertor.NbKnots(); ++i)
{
for (Standard_Integer j = ; j <= theConvertor.Multiplicity(i); ++j)
{
std::cout << ++aCounter << ": " << theConvertor.Knot(i) << std::endl;
}
} std::cout << "Poles(Weight): " << std::endl;
for (Standard_Integer i = ; i <= theConvertor.NbPoles(); ++i)
{
gp_Pnt2d aPole = theConvertor.Pole(i); std::cout << i << ": " << aPole.X() << ", " << aPole.Y()
<< " W(" << theConvertor.Weight(i) << ")" << std::endl;
}
} void TestParabolaConversion(void)
{
gp_Parab2d aParabola(gp::OX2d(), 1.0); Convert_ParabolaToBSplineCurve aConvertor(aParabola, 1.0, M_PI); DumpConvertorInfo(aConvertor);
} int main(int argc, char **argv)
{
TestParabolaConversion(); return ;
}

程序开始部分需要定义HAVE_CONFIG_H,这与在Windows中编程定义WNT有所不同。程序输出结果如下图所示:

Figure 4.1 Convert Parabola to BSpline Curve Result

5. Conclusion

NURBS的一个优势就是统一了曲线曲面的表示方法,即不仅可以表示自由曲线曲面,还可精确表示圆锥曲线曲面。其中抛物线是最简单的圆锥截线,从简单的抛物线转换成NURBS曲线着手,学习NURBS是如何来表示圆锥截线的。

第一次使用Debian系统来编程,选用了一个轻量级的IDE开发工具Codelite,用法与Visual Studio类似。期间也遇到包含引用目录及程序运行时找不到动态库的问题。其中在Codelite中添加引用库路径的方法如下图所示:

Figure 5.1 Set Library Path and Add Libraries in Codelite

添加上述引用库后,解决了链接错误,但是直接运行程序,发现也有与在Windows中类似的问题,即缺少依赖的动态库,如下图所示为使用lld命令检查程序的依赖项。最后通过向ld.so.conf中添加动态库所在的目录解决了问题。相关命令如下所示:

# cat /etc/ld.so.conf 
include ld.so.conf.d/*.conf 
# echo "/home/eryar/opencascade-6.7.1/lib" >> /etc/ld.so.conf 
# ldconfig 

注:以上命令需要有root权限。

Figure 5.2 Use lld command to check depends

通过解决以上的问题,来适应在Debian中使用Codelite开发程序。

6. References

1. 人民教育出版社中学数学室. 数学第二册(上). 人民教育出版社. 2000

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

3. 王仁宏,李崇君,朱春钢. 计算几何教程. 科学出版社. 2008

PDF Version and Sample Code: OpenCASCADE Conic to BSpline Curves-Parabola

OpenCASCADE Conic to BSpline Curves-Parabola的更多相关文章

  1. OpenCASCADE Conic to BSpline Curves-Circle

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

  2. OpenCASCADE Conic to BSpline Curves-Hyperbola

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

  3. B-spline Curves 学习前言与动机(1)

    B-spline Curves 学习之前言 本博客转自前人的博客的翻译版本,前几章节是原来博主的翻译内容,但是后续章节博主不在提供翻译,后续章节我在完成相关的翻译学习. (原来博客网址:http:// ...

  4. B-spline Curves 学习之B样条曲线的移动控制点、修改节点分析(7)

    B-spline Curves: Moving Control Points 本博客转自前人的博客的翻译版本,前几章节是原来博主的翻译内容,但是后续章节博主不在提供翻译,后续章节我在完成相关的翻译学习 ...

  5. B-spline Curves 学习之B样条曲线的系数计算与B样条曲线特例(6)

    B-spline Curves: Computing the Coefficients 本博客转自前人的博客的翻译版本,前几章节是原来博主的翻译内容,但是后续章节博主不在提供翻译,后续章节我在完成相关 ...

  6. B-spline Curves 学习之B样条曲线性质(5)

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

  7. B-spline Curves 学习之B样条曲线定义(4)

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

  8. B-spline Curves 学习之B样条基函数的定义与性质(2)

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

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

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

随机推荐

  1. 总结js的一些复制方法

    1.复制对象: var item1={XXX}; var item2=$.extend(true,{},item1);//深度克隆对象(jQuery方法). lodash也有相关方法:https:// ...

  2. [ACM训练] 算法初级 之 搜索算法 之 广度优先算法BFS (POJ 3278+1426+3126+3087+3414)

    BFS算法与树的层次遍历很像,具有明显的层次性,一般都是使用队列来实现的!!! 常用步骤: 1.设置访问标记int visited[N],要覆盖所有的可能访问数据个数,这里设置成int而不是bool, ...

  3. css 深入浅出定位

    前面我们简单的了解了盒子模型,这里我们就不复习了哈.有什么不清楚的去看我的上一篇博文.其实说定位之前大家一定要先理解一个东西:文档流,那什么是文档流?和文档有关系吗?是dom树吗? 这一对的问题我们应 ...

  4. 用soapUI测试webservice

    测试webservice时,有时需要写一个客户端来向服务端发起请求才可以测试服务,最近看到一款工具soap ui,也可以调试VS2010中的程序. 首先要把webservice 发布到本地,网上已经有 ...

  5. Selenium_等待页面加载完毕

    隐式等待 WebDriver driver = new FirefoxDriver(); driver.get("www.baidu.com"); driver.manage(). ...

  6. 基于黑名单的xss过滤器

    /** * 类名称:AntiXssFilter * @version * 类描述:基于黑名单的xss过滤器 * @version * 创建人:xxx * @version * 创建时间:2015年11 ...

  7. 设计模式(十三) 职责链(chain of responsibility)

    软件领域中的设计模式为开发人员提供了一种使用专家设计经验的有效途径.设计模式中运用了面向对象编程语言的重要特性:封装.继承.多态,真正领悟设计模式的精髓是可能一个漫长的过程,需要大量实践经验的积累.最 ...

  8. 在C#中使用消息队列RabbitMQ

    1.什么是RabbitMQ.详见 http://www.rabbitmq.com/. 作用就是提高系统的并发性,将一些不需要及时响应客户端且占用较多资源的操作,放入队列,再由另外一个线程,去异步处理这 ...

  9. python 根据现有文件树创建文件树

    # -*- coding: utf-8 -*- import os, errno def fileName(path):#获取文件夹 str = '' for i in range(1,len(pat ...

  10. Oracle like查询

    查询方式:LIKE '%xx%' 普通: SELECT * FROM TABLE T WHERE T.COLUNM LIKE '%xx%' 优化:使用 INSTR SELECT * FROM TABL ...