Quantcast
Channel: C++博客-eryar-随笔分类-2.OpenCASCADE
Viewing all 208 articles
Browse latest View live

OpenCASCADE Interpolation - Lagrange

$
0
0

OpenCASCADE Interpolation - Lagrange

eryar@163.com

Abstract. Power basis polynomial is the most simple polynomial function. It also be called power series. OpenCASCADE provides basic computation functions for polynomial functions, such as evaluate the result for a given polynomial, Lagrange interpolation, Hermite interpolation, .etc. The package named PLib, means Polynomial functions Library. The paper focus on the Lagrange interpolation usage of PLib.

Key Words. OpenCASCADE, PLib, Interpolation, Lagrange, 插值


1.Introduction

无穷级数是高等数学的一个重要组成部分,它是表示函数、研究函数性质及进行数值计算的一种工具。由高等数学中的无穷级数的概念可知,函数项级数中简单而常见的一类级数就是各项都是幂函数的函数项级数即所谓的幂级数(Power Series)。因为幂级数的形式简单,易于理解,且可以高效计算曲线上的点及各阶导数,所以在几何造型中经常用幂级数来近似表示曲线曲面。由于将函数展开成幂级数是有条件的,所有并不是所有的曲线曲面都可以用幂级数的多项式来逼近。

对无穷级数概念比较陌生的读者可以把《高等数学》的书找出来翻翻看,重温一下大学的时光。一打开做了笔记有点泛黄的旧书,就会回想起青涩的校园时光。

当时学习《高等数学》的时候感觉很抽象难理解,因为无法将理论与实践联系起来,看不到直观效果,有时也会冒出“学数学有什么用?”这种问题。当你遇到相关的问题再去看国内的教材时,觉得国内的教材写得还是很细致用心的。现在获取信息已经很便利了,如OpenCASCADE这个开源的库,其TKMath工具箱可以看成是数值计算理论联系实践的一个具体实例。结合OpenCASCADE的源码来对相关理论的学习,效率会事半功倍。

本文对幂级数的概念做简单介绍,并结合源程序详细说明OpenCASCADE中的PLib包中关于幂级数多项式的计算及Lagrange插值的用法。


2.Polynomial Evaluation

高等数学的书中把幂级数的重点落在如何将其他的函数展开成幂级数,即用幂级数来逼近函数,而没有介绍如何用数值的方法来对幂级数进行计算。在算法导论一书[2]中找到相关多项式的表示及计算的实现方法,给出了多项式在数据结构上的表示方式及求值算法。对于一个幂级数多项式:

wps_clip_image-1955

多项式的表示有系数表示法和点值表示法。系数表示法(Coefficient Representation)就是将多项式的系数组成一个向量来表示这个多项式。对用系数表示法表示的多项式的求值计算可以采用Horner法则,也是是著名的秦九韶算法。此算法的实现代码在《The NURBS Book》[3]一书中给出了,此处略去,只给出OpenCASCADE中对幂级数多项式的计算的函数的使用。

void testPolynomialEvaluation(void)
{
    
// evaluate 1 dimension polynmoial.
    Standard_Real aCoeff[3= {2.02.03.0};

    Standard_Real aResult 
= 0.0;

    
for (int i = 0; i < 3++i)
    {
        PLib::EvalPolynomial(i, 
021, aCoeff[0], aResult);

        std::cout 
<< "x=" << i << ", (2.0 + 2.0*x + 3.0*x^2): " << aResult << std::endl;
    }
}

从上述代码可以看出,OpenCASCADE的PLib包中对多项式的表示方法是采用的系数表示法。其系数分别为:2.0,2.0,3.0,即表示了幂级数:

wps_clip_image-15530

当x=0, 1,2时计算结果如下图所示:

wps_clip_image-9836

Figure 2.1 Polynomial Evaluation

3.Polynomial Interpolation

多项式的插值问题是多项式求值的逆问题。多项式求值问题几何意义就是已知曲线的表达式计算曲线上的点;而插值问题是已经曲线上的一些点来求通过这些点的曲线表达式。多项式插值中最常见最基本的问题是求一次数不超过n的代数多项式:

wps_clip_image-22611

使

wps_clip_image-6153

满足插值条件的多项式称为函数f(x)在节点xi处的n次插值多项式。由插值条件可知,插值多项式的系数满足线性方程组:

wps_clip_image-12244

由线性代数可知,其系数行列式是n+1阶Vandermonde行列式,且:

wps_clip_image-7712

因为插值的点是不同的点,所以行列式V不为0,即线性方程组有唯一解。这也是算法导论一书中这样说“从某种意义上说,多项式的系数表示法与点值表示法是等价的,即用点值形式表示的多项式都对应唯一一个系数形式的多项式”的理论依据。即插值多项式的唯一性。这里不仅指出了插值多项式存在的唯性,而且也提供了一种解法,即通过解线性方程组来确定系数。根据这个思路,给出对上面已知系数求值的多项式进行插值,代码如下所示:

void testPolynomialInterpolation(void)
{
    
// given three points: (0, 2), (1, 7), (2, 18) to interpolate a polynomial 
    math_Matrix A(13130.0);
    math_Vector B(
13);
    math_Vector X(
13);

    A(
11= 1.0; A(12= 0.0; A(13= 0.0; B(1= 2.0;
    A(
21= 1.0; A(22= 1.0; A(23= 1.0; B(2= 7.0;
    A(
31= 1.0; A(32= 2.0; A(33= 4.0; B(3= 18.0;

    
// solve functions: Ax = B
    math_Gauss aSolver(A);
    aSolver.Solve(B, X);

    
if (aSolver.IsDone())
    {
        std::cout 
<< X << std::endl;
    }
}

已知多项式通过三个点(0, 2),(1, 7),(2, 18),求通过这三个点的多项式表达式。根据插值条件列出线性方程组如下:

wps_clip_image-17126

将系数a0,a1,a2看成线性方程组的待求变量,使用类math_Gauss来对线性方程组进行求解,计算结果如下所示:

wps_clip_image-3193

Figure 3.1 Polynomial Interpolation Result

由上图可知,对线性方程组的求解结果与上节点的系数对应。

4.Lagrange Interpolation

在《计算方法》、《数值逼近》等书中看到Lagrange的名字,就想到《高等数学》书中很多与之相关的定理、定义等,如:Lagrange中值定理、Lagrange型余项、条件极值的Lagrange乘数法等等。在网上搜索了下Lagrange,原来他也是OpenCASCADE的发源地的人:法国人。Joseph-Louis Lagrange,法国著名数学家、物理学家。1736年1月25日生于意大利都灵,1813年4月10日卒于法国巴黎。他在数学、力学和天文学三个学科领域都有历史性的贡献,其中尤以数学方面的成就最为突出。以下图片来自网易公开课《数学传奇》:从笛卡尔到庞加莱—法国数学的人文传统,公开课网址:http://open.163.com/special/cuvocw/shuxuechuanqi.html

wps_clip_image-13753

wps_clip_image-31102

wps_clip_image-15311

为什么优雅浪漫的法国人的数学大师层出不穷呢?因为他们最优秀的人在学习数学。数学已经成为法国人传统文化中最优秀的一部分了。

wps_clip_image-20782

数学也是中国传统文化的一部分,中国古代数学成就也很多:《周髀算经》; 《九章算术》(三国时刘徽著); 祖冲之; 算盘。天文学:天象观察记录, 发明观测仪器:圭表;浑仪;简仪;高表;仰仪,制定历法(农历)。想想后来为什么没有大的发展,原因可能是科举制度造成的,考试的内容偏文。

Lagrange父亲是法国陆军骑兵里的一名军官,后由于经商破产,家道中落。据Lagrange本人回忆,如果幼年时家境富裕,他也就不会作数学研究了。经历了挫折之后没被打倒的人后期成就会更大,像《红楼梦》的作者曹雪芹。严重跑题了,回到Lagrange插值问题上来。从Lagrange中值定理的证明及Lagrange乘数法求极值的方式中可以看出Lagrange有个特点,那就是喜欢引入辅助函数来解决问题,可以看出Lagrange是非常精明的。对多项式插值也不例外,通过构造了一个Lagrange插值基函数来简化多项式的插值,如下公式为Lagrange插值基函数:

wps_clip_image-11405设:

wps_clip_image-30380

则Lagrange插值基函数可以表示为简洁的形式:

wps_clip_image-14218

则n次多项式

wps_clip_image-15214

满足插值条件。OpenCASCADE的PLib包中也提供了Lagrange插值的函数来进行多项式插值计算。其用法的代码如下所示:

void testLagrangeInterpolation(void)
{
    
// given three points: (0,2), (1,7), (2,18) to interpolate a polynomial
    Standard_Real aValues[3= {2.07.018.0};
    Standard_Real aParameters[
3= {0.01.02.0};
    Standard_Real aResult 
= 0.0;

    
// this do not output the coeff of the interpolate polynomial
    PLib::EvalLagrange(1.5021, aValues[0], aParameters[0], aResult);

    std::cout 
<< "Result: " << aResult << std::endl;
}

下面对PLib::EvalLagrange()函数的7个参数进行说明:

Parameter

待根据Lagrange插值多项式求值的参数

DerivativeRequest

插值多项式导数次数

Degree

插值多项式的次数

Dimension

插值多项式的维次

Values

插值多项式的值

Parameters

插值多项式的参数

Results

参数Parameter在Lagrange插值多项式中的值

上述代码计算的是这样一个问题,已知f(0)=2; f(1)=7, f(2)=18,求f(1.5)的近似值。计算结果如下图所示:

wps_clip_image-12215

Figure 4.1 Lagrange Interpolation Result

由上图可知,经过Lagrange抛物插值得到的结果与直接计算得到的结果吻合。为了更好的说明OpenCASCADE中PLib包的Lagrange插值的用意,下面将《计算方法》[6]中Lagrange插值部分中的例题进行计算来结计算结果进行比较。已知wps_clip_image-6316

分别用线性插值和抛物插值求wps_clip_image-31569的近似值。相关计算代码如下所示:

// sqrt(100)=10, sqrt(121)=11, sqrt(144)=12, evaluate sqrt(115) value.
Standard_Real aSqrtValues[3= {10.011.012.0};
Standard_Real aSqrtParameters[
3= {100.0121.0144.0};

// linear interpolation
PLib::EvalLagrange(115.0011, aSqrtValues[0], aSqrtParameters[0], aResult);
std::cout 
<< "Linear Interpolate Result: " << aResult << std::endl;

// Parabolic Interpolation
PLib::EvalLagrange(115.0021, aSqrtValues[0], aSqrtParameters[0], aResult);
std::cout 
<< "Parabolic Interpolate Result: " << aResult << std::endl;

计算结果如下所示:

wps_clip_image-28168

Figure 4.2 Linear Interpolate and Parabolic Interpolate Result

将上图4.2的结果与书中的计算结果进行对比发现,下面的结果为《计算方法》书中的结果:

wps_clip_image-11359

PLib中Lagrange插值结果准确,精度较高。

从上面的结果来看,Lagrange插值方法比直接解线性方程组的方法要简单,且Lagrange插值法比解线性方程组的实现要简单很多,只用一个函数即可。

5.Conclusion

通过将最简单的多项式进行求值,及用求解线性方程组的方法插值和Lagrange插值多项式,来学习曲线拟合中要求较高“插值”,因为其要求曲线严格通过插值点。曲线拟合中的逼近就没有这个要求,只是要求曲线与插值点之间的容差尽量小。

通过应用OpenCASCADE的PLib包中的函数,可以发现对幂级数的多项式的表示法一般会用系数表示法,且都会使用高效的Horner法则,也是秦九韶算法。

直接根据定义来插值幂次多项式时,可以使用Gauss消元法来求解线性方程组。这种方式计算工作量大,而Lagrange插值法结构紧凑,便于编程实现,且代码相对简单。通过对《计算方法》书中例题的计算,来验证PLib::EvalLagrange()函数的用法及计算结果。

6.References

1. 同济大学数学教研室. 高等数学. 高等教育出版社. 1996

2. 同济大学应用数学系. 线性代数. 高等教育出版社. 2003

3. Thomas H. Cormen. Introduction to Algorithms. The MIT Press. 2001

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

5. Shing Liu. Polynomial Library in OpenCASCADE. 2013

http://www.cppblog.com/eryar/archive/2013/05/08/200118.html

6. 易大义,沈云宝,李有法. 计算方法. 浙江大学出版社. 2002

7. 蒋尔雄,赵风光,苏仰锋. 数值逼近. 复旦大学出版社. 2012

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

9. 蔡天新. 数学传奇. http://open.163.com/special/cuvocw/shuxuechuanqi.html

10. 科学出版社名词室. 新汉英数学词汇. 科学出版社. 2004

 



eryar 2015-09-05 12:16 发表评论

Clash Detection

$
0
0

Clash Detection

eryar@163.com

Abstract. Clash detection is used for the model collision check. The paper introduce the clash detection in PDMS, and also about how to set the piping component for the operation space clash check.

Key Word. Clash Detection, Collision Detection

1. Introduction

碰撞检查是PDMS中一个用于模型检查的辅助功能。三维模型已经很直观,但是仅凭直观并不能保证模型完全没有干涉。通过碰撞检查,可以实现模型完全无碰撞,优化设计。

精确碰撞检查算法的实现较为复杂,简单的碰撞检查实现起来较为简单。即将待检查的模型的层次包围盒(BVH)生成,直接将包围盒进行碰撞检查。如果包围盒都没有碰撞,则模型就没有碰撞。如果包围盒之间存在碰撞,则需要再进一步分析了。精确的算法会根据模型的几何参数表示来计算,粗略的处理是将模型离散后的网格数据进行分析,两种处理方法各有利弊。如下图所示两个几何体的包围盒是碰撞了,但是实际上因为有个开孔是没有碰撞的。

wps_clip_image-9009

Figure 1.1 Clash Detection demo

Open CASCADE也提供了碰撞检测的功能模块Collision Detection,不过不是开源免费的。没有用过,不知道性能如何。关于Collision Detection模块更多介绍,可参考:http://www.opencascade.com/content/collision-detection

本文对PDMS中的Clash Detection进行介绍,并说明如何定义管件Piping Component,使其能够进行操作空间的碰撞检查。

2. Obstruction Levels

PDMS的Design模块中的碰撞检查Clash Detection功能可以用来检查模型中指定部分的模型的干涉Interferences情况。碰撞检查的结果取决于以下两个因素:

v Obstruction Levels

v Touch and Clearance

2.1 Obstruction Level

PDMS所有设计数据库(Design Database)和部件库数据库(Catalogue Database)中的基本几何体都有个属性:Obstruction,其取值范围是0到2,意义如下:

v OBST 0 :None,不占空间,即不参考碰撞检查;

v OBST 1 :Soft,软占有,用来对操作空间等作碰撞检查;

v OBST 2 :Hard,硬占有,表示碰撞检查;

wps_clip_image-8209 wps_clip_image-14694

Figure 2.1 Obstruction Levels in Design and Paragon module

2.2 Touch and Clearance

除了Obstruction Level以外,还有这些精度设置直接影响碰撞检查的结果,他们是Touch Gap, Overlap, Clearnace ,如下图所示:

wps_clip_image-18871

Figure 2.2 Tolerances for the Clasher

当Overlap设值为5, Touch为2,Clearance为8时,碰撞检查时的意义如下图所示:

wps_clip_image-8005

Figure 2.3 Physical Clash, Touches and Clearances

v 当两个几何体之间的重叠部分超过5mm时,就会报告一个物理的碰撞Clash;

v 当两个几何体之间的重叠部分小于5mm,就会报告一个接触Touch;

v 当两个几何体之间没有重叠,但是接触间隙小于2mm,也会报告一个接触;

v 当两个几何体之间没有重叠,但是间距大于2小于8mm,会报告一个Clearance;

v 当两个几何体之间间距大于8mm,即没有干涉发生。

3.Operating Space Check

对于一些管件如阀门或温度计之类,有个操作空间Operating Space。不满足这个操作空间,管件的安装或操作都有些不便之处。所以需要对管件的操作空间进行检测。管件的外形都是在部件库中使用多个基本几何体进行定义的。每个基本几何体都可以指定Obstruction Level,即None, Soft和Hard。假设一个阀门的操作空间如下图所示:

wps_clip_image-30923

Figuer 3.1 Operating Space for a Valve

将部件定义中的几何体的Represent指定为Piping Reserved时,会自动设置此几何体的Obstruction Level为Soft(1),即将此几何体做为操作空间进行碰撞检测。当将几何体指定为Piping Reserved时,在模型空间中并不会显示,但是在碰撞检查时会报告与其碰撞的模型。

如下图所示:

wps_clip_image-21655

Figure 3.2 Operating Space Clash

虽然阀门和设备并没有接触,但是设备与阀门的操作空间碰撞了,依然做为一种碰撞进行报告。

4.Conclusion

PDMS设计模块中的碰撞检查是进行优化设计的一种辅助功能。通过使用碰撞检查,可以做到零干涉,使设计更合理。

通过指定Obstruction Level不仅可以用来检测直接的物理碰撞,还可以用来进行操作空间的检查。

通过在软件中使用碰撞检查功能,可以理解此功能的意义。对于想深究此功能实现算法的读者,可以更有的放矢。OPEN CASCADE中也提供了碰撞检查的功能模块Collision Detection,只不过要收费。由此可见,此功能有实际应用价值。

5. References

1. AVEVA. DEISGN Reference Manual Utilities.

2. OPEN CASCADE. Collision Detection.  http://www.opencascade.com/content/collision-detection

PDF Version: Clash Detection



eryar 2015-10-21 21:01 发表评论

OPEN CASCADE BSpline Curve Interpolation

$
0
0

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。采用插值的方式时,所创建的曲线或曲面必须精确地满足所给的数据条件,例如曲线通过所给的插值点。采用逼近的方式时,创建的曲线或曲面不必精确地满足所给的数据条件,只要在一定的误差范围内接近即可,如下图所示:

wps_clip_image-19229

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

wps_clip_image-20190

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)的线性方程组:

wps_clip_image-7005

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

2.1 Equally Spaced 均匀参数法

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

wps_clip_image-29325

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

wps_clip_image-11040

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

wps_clip_image-10864

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

2.2 Chord Length 弦长参数法

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

wps_clip_image-18197

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

2.3 Centripetal Method 向心参数法

wps_clip_image-8284

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

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
+1)) ;
    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 
+= 1 ;
  }
  ParametersPtr 
=
    
new TColStd_HArray1OfReal(1,
                  num_parameters) ;
  ParametersPtr
->SetValue(1,0.0e0) ;
  index 
= 2 ;
  
for (ii = PointsArray.Lower() ; ii < PointsArray.Upper() ; ii++) {
    distance 
= 
      PointsArray.Value(ii).Distance(PointsArray.Value(ii
+1)) ;
    ParametersPtr
->SetValue(index,
                ParametersPtr
->Value(ii) + distance) ;
    index 
+= 1 ;
  }
  
if (PeriodicFlag) {
    distance 
= 
      PointsArray.Value(PointsArray.Upper()).
    Distance(PointsArray.Value(PointsArray.Lower())) ;
    ParametersPtr
->SetValue(index,
                ParametersPtr
->Value(ii) + distance) ;
  }
}

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

wps_clip_image-18962

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

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

由上述代码可知,插值要求至少有两个插值点。当只有两个插值点时,插值曲线次数为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(1, Parameters.Length(),
                  
12 * Degree + 1) ;
  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(13);
    Handle_Geom_BSplineCurve aBSplineCurve;

    aPoints.SetValue(
1, gp_Pnt(0.00.00.0));
    aPoints.SetValue(
2, gp_Pnt(1.01.00.0));
    aPoints.SetValue(
3, gp_Pnt(2.06.03.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

 



eryar 2015-11-11 22:23 发表评论

OPEN CASCADE Curve Continuity

$
0
0

OPEN CASCADE Curve Continuity

eryar@163.com

Abstract. 设计一条复杂曲线时,出于设计和制造上的考虑,常常通过多段曲线组合而成,这就需要解决曲线段之间如何实现光滑连接的问题。评价曲线间连接的光滑度的度量有两种:参数连接性和几何连续性。本文对这两种连续性分别进行介绍。

Key Words. Curve Continuity, Geometric Continuity, 参数连续性、几何连续性

1.Introduction

在实际应用中进行复杂零件的几何设计时,通常我们用到的不仅仅是整个曲线,而是满足一定的连续条件拼接而成的曲线段组成的组合曲线。关于连续条件有两种不同的度量方法。一种是满足于数学上严格定义的函数曲线可微性方法;别一种是满足相对宽松的约束条件的几何连续性方法。

本文对连续性的两种度量方法进行介绍,来理解参数连续性和几何连续性。对连续性的概念有个认识后,在使用OPEN CASCADE或其他几何造型内核时,当出现需要指定连续性的时候,不至于茫然无措。

2.Parametric Continuity

利用函数曲线的可微性,曲线在连接处具有直到n阶连续导矢,即n次连续可微,这类光滑度称之为Cn或n阶参数连续性。下面给出参数连续性Parametric Continuity的定义:

参数曲线C(u)在u=u0处为k阶参数连续(Ck连续)的充要条件是:C(u)的每个分量在u=u0处Ck连续,即

wps_clip_image-8474

如果对所有的u∈[a,b],曲线C(u)均Ck连续,则称它为关于参数u的Ck连续曲线。在函数曲线里,可微性和光滑度是一致的,函数曲线是C1连续,意味着具有连续的切矢;C2连续意味着不仅具有连续的切矢,还具有连续的曲率。由于曲线的参数选取并不唯一,同样的曲线可以有不同的参数表示,而曲线的参数连续又与参数选取紧密相关。若参数变换前曲线为Ck连续,但曲线的参数变换后可能不能在每一点处都满足Ck连续。这是个问题。

3.Geometric Continuity

实际工程设计中,人们有一种直观的感觉:两线段相连接,只要在连接点有相同的切线就认为是光滑的。但按照参数连续性度量光滑度,还必须有相同的切矢模长才能认为是C1连续的。由于参数连续性不能客观准确度量参数曲线连接的光滑度,因而经常用称之为几何连续性(Geometric Continuity)的方法来度量曲线的光滑程度。下面给出几何连续性的定义:

参数曲线C(u)是k阶几何连续的充要条件为:在弧长参数化下,曲线是Ck的。因为在弧长参数化下,曲线的参数连续与几何连续是一致的。

关于弧长参数化相关概念可参考: http://www.cppblog.com/eryar/archive/2014/08/25/208127.html

合成曲线在拼接点处满足不同于Cn连续性的某一组约束条件,称为具有n阶几何连续性,简记为Gn。事实上模型的形状是与描述它所取的参数无关的,作为形状的内在几何特征的光滑度及作为度量光滑度的几何连续性定义应该是独立于具体的参数化的。几何连续性放宽了对参数曲线光滑度的限制条件,为形状定义和形状控制提供了更多的自由度,更适合曲线在交互设计中使用,有文献称其为视觉连续性。

4.Curve Continuity

下面通过一个具体的例子来说明参数连续性和几何连续性。最后介绍OPEN CASCADE中对曲线连续性的定义。

wps_clip_image-3347

Φ(t)在[0,2]上表示一条连接V0,V1的直线段,但却有

wps_clip_image-6475

Φ(t)明明是一条直线,却非C1连续,说明用参数连续性描述光滑性是不恰当的。

wps_clip_image-9192

Figure 4.1 两条曲线拼接的连续性

如4.1所示,对于参数t∈[0,1]的两条曲线P(t)和Q(t),若要求在拼接处达到G0连续或C0连续,即两曲线在拼接处位置连续,则需要P(1) = Q(0);

若要求在拼接处达到G1连续,就是说两条曲线在拼接处满足G0连续的条件下,并有公共的切矢:

wps_clip_image-22327

当α=1时,G1连续就成为C1连续。

若要求在拼接处达到G2连续,就是说两条曲线在拼接处满足G1连续的条件下,并有公共的曲率矢。根据曲率计算公式:

wps_clip_image-24839

wps_clip_image-16585

将G1连续的条件方程代入可得:

wps_clip_image-12445

β为任意常数。当α=1,β=0时,G2连续就成为了C2连续。至此可以看到,C1连续保证G1连续,C2连续保证G2连续,但反过来不行。也就是说Cn连续的条件比Gn连续的条件要苛刻。

OPEN CASCADE中关于曲线是连续性的定义使用了GeomAbs_Shape枚举定义:

//! Provides information about the continuity of a curve:
//! -   C0: only geometric continuity.
//! -   G1: for each point on the curve, the tangent vectors
//! "on the right" and "on the left" are collinear with the same orientation.
//! -   C1: continuity of the first derivative. The "C1" curve is
//! also "G1" but, in addition, the tangent vectors " on the
//! right" and "on the left" are equal.
//! -   G2: for each point on the curve, the normalized
//! normal vectors "on the right" and "on the left" are equal.
//! -   C2: continuity of the second derivative.
//! -   C3: continuity of the third derivative.
//! -   CN: continuity of the N-th derivative, whatever is the
//! value given for N (infinite order of continuity).
//! Also provides information about the continuity of a surface:
//! -   C0: only geometric continuity.
//! -   C1: continuity of the first derivatives; any
//! isoparametric (in U or V) of a surface "C1" is also "C1".
//! -   G2: for BSpline curves only; "on the right" and "on the
//! left" of a knot the computation of the "main curvature
//! radii" and the "main directions" (when they exist) gives the same result.
//! -   C2: continuity of the second derivative.
//! -   C3: continuity of the third derivative.
//! -   CN: continuity of any N-th derivative, whatever is the
//! value given for N (infinite order of continuity).
//! We may also say that a surface is "Ci" in u, and "Cj" in v
//! to indicate the continuity of its derivatives up to the order
//! i in the u parametric direction, and j in the v parametric direction.
enum GeomAbs_Shape
{
  GeomAbs_C0,
  GeomAbs_G1,
  GeomAbs_C1,
  GeomAbs_G2,
  GeomAbs_C2,
  GeomAbs_C3,
  GeomAbs_CN
};

结合前面关于参数连续和几何连续的介绍,再看头文件中的注释就很好理解了。

5.Conclusion

综上所述,对拼接曲线光滑度进行度量有两种方法:参数连续性和几何连续性。参数连续性是严格的数学可微性定义,就像别人对你到了年纪还没结婚的看法……“肯定是要求太高了”。而几何连续性就像我们工科专业的,不是那么喜欢较真,差不多就可以了。对有些精确结果还喜欢乘以一个经验系数,放点余量。理解了对拼接曲线光滑性的度量方法,就可以在用到的时候按需选择。

6.References

1. 莫蓉. 常智勇. 计算机辅助几何造型技术. 科学出版社. 2009

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

3. 孙家广等. 计算机图形学. 清华大学出版社. 2000

4. 朱心雄. 自由曲线曲面造型技术. 科学出版社. 2008

5. Shing Liu. OPENCASCADE Curve Length Calculation.  http://www.cppblog.com/eryar/archive/2014/08/25/208127.html

 



eryar 2015-11-15 23:01 发表评论

OPEN CASCADE Gauss Least Square

$
0
0

OPEN CASCADE Gauss Least Square

eryar@163.com

Abstract. The least square can be used to solve a set of n linear equations of m unknowns(n >= m). The OPEN CASCADE class math_GaussLeastSquare implements the least square solution of the linear equations by using Gauss LU decomposition algorithm. The paper focus on the Least Square method to solve the linear equations.

Key Words. Least Square, LU Decomposition, Linear Equations
 

1.Introduction

最小二乘(Least Square)问题是一类特殊的无约束优化问题,它在科学与工程计算中有十分重要的应用。最小二乘问题产生于数据拟合问题,它是一种基于观测数据与模型数据之间的差的平方和最小来估计模型参数的方法。它最早由德国数学家高斯Gauss于1794年,在预测行星轨道时提出,当时高斯只有17岁,后来得到广泛应用。

许多工程问题常常需要根据两个变量的几组实验数值来找出这两个变量的函数关系的近似表达式,通常把这样得到的函数的近似表达式称为经验公式。经验公式建立后就可以把生产或实验中所积累的某些经验提高到理论上加以分析。

在几何造型中常常需要对曲线和曲面进行拟合(插值和逼近),根据一些采样点来拟合曲线曲面。逼近比插值更为困难。在插值问题中,只是根据采样点来建立方程组,直接求解方程组即可得到结果,不需要进行容差检查。而在逼近问题中,容差和采样点一起作为输入,一般预先不知道需要多少个控制点才能达到预期的精度,因此逼近一般都需要通过迭代来实现。通过最小二乘法即可实现达到精度要求的拟合结果,如OPEN CADCADE中的曲线曲面逼近就采用了最小二乘算法。

本文主要关注于最小二乘法求解线性方程组的原理及OPEN CASCADE中的实现和用法,为探索最小二乘法在OPEN CASCADE曲线曲面拟合方面的应用提前做些热身准备。最小二乘问题涉及到非线性最优化的相关知识,对多元函数的微积分有些要求,可以找出原来的《高等数学》或《数学分析》的课本复习下。本文关注的应用最小二乘法求解线性方程组问题只涉及到线性代数或矩阵相关的知识。

2.Principle

在罗家洪、方卫东编著的《矩阵分析引论》一书中的2.5节点到子空间距离与最小二乘法,用欧氏空间的概念来表达最小二乘法,并给出最小二乘解所满足的代数条件的证明过程。本文摘抄主要内容对最小二乘法求解线性方程组的理解。

设已给不相容实系数线性方程组(即无解的线性方程组):

wps_clip_image-1041

因为这方程组无解,设法找出一组数x1’, x2’, ..., xn’使平方偏差最小:

wps_clip_image-320

这组数称为此方程组的最小二乘解,这一方法叫做最小二乘法。经证明,最小二乘解所满足的代数方程为:

wps_clip_image-21050

它是一个线性方程组,系数矩阵为ATA,常数项为ATB。使用上述结论来解如下线性方程组:

wps_clip_image-12970

由于:

wps_clip_image-20594

所以:

wps_clip_image-20028

于是求得最小二乘解为:x1=17/6, x2=-13/6, x3=-4/6。

在OPEN CASCADE的数据工具集中TKMath,使用类math_GaussLeastSquare来利用最小二乘法来对线性方程组进行求解。其实现代码如下所示:

 

math_GaussLeastSquare::math_GaussLeastSquare (const math_Matrix& A,
                             
const Standard_Real MinPivot) :
                                      LU(
1, A.ColNumber(),
                     
1, A.ColNumber()),
                                      A2(
1, A.ColNumber(),
                     
1, A.RowNumber()),
                                      Index(
1, A.ColNumber()) {
  A2 
= A.Transposed();                    
  LU.Multiply(A2, A);

  Standard_Integer Error 
= LU_Decompose(LU, Index, D, MinPivot);
  Done 
= (!Error) ? Standard_True : Standard_False;

}

void math_GaussLeastSquare::Solve(const math_Vector& B, math_Vector& X) const{
  StdFail_NotDone_Raise_if(
!Done, " ");
  Standard_DimensionError_Raise_if((B.Length() 
!= A2.ColNumber()) ||
                   (X.Length() 
!= A2.RowNumber()), " ");

  X.Multiply(A2, B);

  LU_Solve(LU, Index, X);

  
return;
}

结合上述公式,再来理解这个代码实现的思路还是很清晰的。

3.Code Example

OPEN CASCADE的TKMath工具集中提供了类math_GaussLeastSquare实现了使用高斯LU分解算法求m个未知数的n个线性方程组的最小二乘解,其中n>=m。下面给出使用类math_GaussLeastSquare对上述线性方程组进行求解的示例程序:

 

/*
*    Copyright (c) 2015 Shing Liu All Rights Reserved.
*
*           File : main.cpp
*         Author : Shing Liu(eryar@163.com)
*           Date : 2015-11-25 21:00
*        Version : OpenCASCADE6.9.0
*
*    Description : Test Gauss Least Square method to
*                  solve linear equations.
*/

#define WNT
#include 
<math_GaussLeastSquare.hxx>

#pragma comment(lib, 
"TKernel.lib")
#pragma comment(lib, 
"TKMath.lib")


void testLeastSquare(void)
{
    math_Matrix A(
1413);
    math_Vector B(
14);
    math_Vector X(
13);

    A(
1,1= 1.0; A(1,2= 1.0; A(1,3= 0.0;  B(1= 1.0;
    A(
2,1= 1.0; A(2,2= 0.0; A(2,3= 1.0;  B(2= 2.0;
    A(
3,1= 1.0; A(3,2= 1.0; A(3,3= 1.0;  B(3= 0.0;
    A(
4,1= 1.0; A(4,2= 2.0; A(4,3= -1.0; B(4= -1.0;

    math_GaussLeastSquare aSolver(A);
    aSolver.Solve(B, X);

    
if (aSolver.IsDone())
    {
        std::cout 
<< aSolver;
        std::cout 
<< X;
    }
}

int main(int argc, char* argv[])
{
    testLeastSquare();

    
return 0;
}

程序运行结果如下图所示:

wps_clip_image-21035

由上图可知,计算结果吻合。

4.Conclusion

最小二乘法在系统理论中处理最小优化问题时有重要应用,本文主要关注于线性方程组的最小二乘法求解,且对方程个数与未知数个数不要求相等。最小二乘法也是在我们学习高等数学的多元函数微分后,提出的一个实用的函数公式拟合方法。虽然本文所述的最小二乘法主要用于方程组的求解,但是OPEN CASCADE中曲线曲面的逼近也是采用了最小二乘法,这里最小二乘法就涉及到非线性最优化的相关理论。

纵观OPEN CASCADE的数学工具集TKMath中,大量地用到了非线性最优化理论,如类math_BFGS就实现了Broyden-Fletcher-Goldfarb-Shanno(BFGS),用于计算多变量函数的最小值,类math_FRPR实现了Fletcher-Reeves-Polak-Ribiere算法。BFGS算法是拟牛顿方法,是解决无约束优化问题既快又稳定的算法。这些最优化算法广泛地用于OPEN CASCADE中曲线曲面拟合、光顺及求交等算法中。所以有必要对最优化方法,非线性最优化理论等知识进行学习。掌握一些最优化方法,不仅可以方便理解OPEN CASCADE中的核心关键算法,还可以将这些理论方法灵活应用在自己的程序中,提高软件质量。由于本人能力有限,先在这儿抛砖引玉,感兴趣的读者可以结合相关书籍对非线性最优化理论进行学习,研究,应用,创新。

5.References

1. 同济大学数学教研室. 高等数学. 高等教育出版社. 1996

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

3. 罗家洪. 方卫东. 矩阵分析引论. 华南理工大学出版社. 2006

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

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

6. 王宜举. 修乃华. 非线性最优化理论与方法. 科学出版社. 2012

 



eryar 2015-11-25 22:06 发表评论

OPEN CASCADE Multiple Variable Function

$
0
0

OPEN CASCADE Multiple Variable Function

eryar@163.com

Abstract. Multiple variable function with gradient and Hessian matrix is very very import in OPEN CASCADE optimization algorithms. In order to understand these optimization algorithm better, let’s study some basic knowledge about Gradient, Hessian Matrix.

Key Words. Multiple Variable Function, Gradient, Hessian Matrix, 最优化算法,

1. Introduction

当函数只有一个自变量时,感觉相对简单,一切还在掌握之中。如参数u表示的B样条曲线,当参数u在[0,1]之间变化时,就可以得到与参数对应的曲线上的点。当函数有多个自变量时,就有点力不从心,毕竟人们都喜欢安稳,不喜欢太多的变化。当变化太多时,得到的结果也更丰富多彩。如有两个参数u,v表示的B样条曲面,参数变化的范围是一个u∈[0,1],v∈[0,1]矩形空间,与参数u,v对应的是一片曲面上的点。

在实际应用中,与多元函数的一阶导数(Gradient梯度)、二阶导数(Hessian Matrix)和多元函数的极值等概念也是理解非线性最优化问题的基础知识。

OPEN CASCADE中一些求极值和逼近等算法中就使用了非线性最优化算法,如下类图所示:

wps_clip_image-13250

Figure 1.1 Multiple Variable Function in OPEN CASCADE

如上图所示,具有二阶导数(Hessian Matrix)的多元函数应用到全局优化的求极值算法中。在用能量法实现的曲线光顺(Fair Curve)算法中也使用到了具有二阶导数的多元函数。为了更好地理解最优化的具体实现,先学习下OPEN CASCADE中与多元函数有关概念的表达方式:多元函数、梯度Gradient和Hessian Matrix。

2.Multiple Variable Function

在《高等数学》中给出了多元函数的定义:设D是平面上一个点集。如果对于每个点P(x,y)∈D,变量z按照一定法则总有确定的值和它对应,则称z是变量x,y的二元函数。点集D称为该函数的定义域,x,y称为自变量,z称为因变量。当自变量的个数大于1个时,即n≥2,n元函数统称为多元函数。

在OPEN CASCADE中与多元函数最直接的对应就是类Geom_Surface,即参数表示的曲面,参数u,v的取值区域为多元函数的定义域,当指定uv时得到的曲面上的点即为多元函数值。OPEN CASCADE的数学包中还给出了更抽象地多元函数类:math_MultipleVarFunction。

wps_clip_image-27986

Figure 2.1 math_MultipleVarFunction class diagram

由上面的类图可知,类math_MultipleVarFunction是个抽象类,有两个纯虚函数:

v NbVariables() const = 0:自变量的个数;

v Value(const math_Vector& X, Standard_Real& F) = 0:计算指定自变量X对应的函数值F。自变量X是个向量,其中的值分别对应多个自变量;

下面给出一个多元函数的具体应用,即计算二重积分。题目来源为《高等数学》教材习题9-2(1):

wps_clip_image-32123

在OPEN CASCADE中计算上述二重积分代码如下所示:

/*
*    Copyright (c) 2015 Shing Liu All Rights Reserved.
*
*           File : main.cpp
*         Author : Shing Liu(eryar@163.com)
*           Date : 2015-11-28 21:00
*        Version : OpenCASCADE6.9.0
*
*    Description : Test Gauss Multiple integration.
*/

#define WNT
#include 
<math_MultipleVarFunction.hxx>
#include 
<math_GaussMultipleIntegration.hxx>

#pragma comment(lib, 
"TKernel.lib")
#pragma comment(lib, 
"TKMath.lib")

class math_TestFunction : public math_MultipleVarFunction
{
public:
    
virtual Standard_Integer NbVariables() const
    {
        
return 2;
    }

    
virtual Standard_Boolean Value(const math_Vector& X, Standard_Real& F)
    {
        F 
= X(1* X(1+ X(2* X(2);

        
return Standard_True;
    }
};

void testMultipleIntegration(void)
{
    math_Vector aLower(
12);
    math_Vector aUpper(
12);
    math_IntegerVector aOrder(
1210);

    aLower(
1= -1.0;
    aLower(
2= -1.0;

    aUpper(
1=  1.0;
    aUpper(
2=  1.0;

    math_TestFunction aFunction;
    math_GaussMultipleIntegration aIntegrator(aFunction, aLower, aUpper, aOrder);

    
if (aIntegrator.IsDone())
    {
        std::cout 
<< aIntegrator;
    }
}

int main(int argc, char* argv[])
{
    testMultipleIntegration();

    
return 0;
}

通过从抽象类math_MultipleVarFunction派生出一个具体的多元函数类,在虚函数Value()计算指定向量X对应的函数值,通过函数NbVariables()确定自变量的个数。为什么可以对类math_Vector的对象用括号直接进行取值和赋值呢?因为在这个类中重载了括号运算符。计算结果如下图所示:

wps_clip_image-16350

Figure 2.2 Integration Value

因为使用math_GaussMultipleIntegration时需要指定积分区域,且只能为常数,所以如下所示的积分区域中包含变量的多重积分就不能计算:

wps_clip_image-25551

OPEN CASCADE中与多元函数对应的一元函数的积分计算参考:

OPEN CASCADE Gauss Integration:

http://www.cppblog.com/eryar/archive/2014/09/11/208275.html

3.Gradient

在二元函数情形,设计函数z=f(x,y)在平面区域D内具有一阶连续偏导数,则对于每一点P(x,y)∈D都可以定出一个向量:

wps_clip_image-11171

这向量称为函数z=f(x,y)在点P(x,y)的梯度(gradient),记作gradf(x,y)。对于多元函数u=f(X),X=(x1,x2, ..., xn)T,有如下定义:

设u=f(X),X∈S,若在点x0=(x1(0),x2(0), ..., xn(0))T处对于自变量X=(x1,x2, ..., xn)T的各个分量的偏导数wps_clip_image-6754都存在,则称函数u=f(X)在点x0处一阶可导,并称向量wps_clip_image-6111是u=f(X)在点x0处的梯度Gradient或一阶导数。

无约束优化最优性的一阶必要条件是:若x0是无约束优化问题的局部最优值点,则wps_clip_image-11497

由数学分析可知,wps_clip_image-17726的方向为f(X)的等值面(等值线)的法线在点x0处的方向,即沿梯度方向函数值变化最快。目标函数梯度为零的点称为无约束优化问题的稳定点。稳定点可能是目标函数的极大值点,也可能是极小值点,甚至二者都不是。最后一种情况对应的点称为函数的鞍点,即在从该点出发的一个方向上是函数的极大值,而在另一个方向上是极小值点。

对无约束优化问题,目标函数在最优值点的任意方向上的导数都为零,即目标函数在最优值点的切平面是水平的。不过无约束优化问题的局部最大值点和鞍点也满足上述条件。因此,要确认一个稳定点是否为最优值点,还需要考虑该点的二阶最优性条件。

wps_clip_image-13848

在OPEN CASCADE中与此对应的类是math_MultipleVarFunctionWithGradient,即具有梯度的多元函数。这个类也是抽象类,不能直接实例化,若要使用需要派生出新类,并实现以下几个纯虚函数:

v NbVariables() const = 0:多元函数自变量个数;

v Value(const math_Vector& X, Standard_Real& F) = 0:计算多元函数在指定变量X处对应的函数值F,通过引用传出;

v Gradient(const math_Vector& X, math_Vector& G) = 0:计算多元函数在指定变量X处的梯度值,通过引用传出;

v Values(const math_Vector& X, Standard_Real& F, math_Vector& G) = 0:计算多元函数在指定变量X处的函数值F和梯度值G;

4.Hessian Matrix

多元函数的二阶导数和Hessian Matrix的定义如下:设u=f(X),x0∈S,若f在点x0∈S处对于自变量x∈S的各分量的二阶偏导数wps_clip_image-13678都存在,则称函数f(X)在点x0处二阶可导,且称矩阵

wps_clip_image-876

为f(X)在点x0处的二阶导数或Hessian Matrix,Hessian Matrix有时也记作H(x0)。

无约束最优化最优性条件的二阶必要条件为:设f(X)在点x0∈S处二次可微,若x0最f(X)的局部极小点,则wps_clip_image-12381wps_clip_image-13308半正定。

无约束最优化最优性条件的二阶充分条件为:设f(X)在点x0∈S处二次可微,若wps_clip_image-23609wps_clip_image-4836正定,则x0是函数f(X)的严格局部极小点。

二次型是X=(x1,x2,...,xn)T的二次齐次函数,它在研究非线性最优化问题中具有重要作用。通过线性代数中正定二次型相关定理,可以得出Hessian Matrix正定的判断条件。相对于高等数学中关于二元函数极值充分条件的定理,使用Hessian Matrix更具一般性,适用于任意多元函数。终于知道正定二次型的一个应用,将原来在线性代数课本中突然冒出这么个抽象概念,能与实际应用有些关联。看来线性代数必需在实际应用中才能有所理解,如关于现代控制工程中的微分方程组的求解,会用到特征值的理论;无约束最优化问题中极值充分条件的说明要用到正定二次型理论等。难怪当时在学习线性代数的时候那么吃力,对这些抽象概念不理解,学习的时候就只能是机械的记忆,如果以后用不到,肯定都还给老师了。OPEN CASCADE中与Hessian Matrix对应的类是math_MultipleVarFunctionWithHessian,其类图如下所示:

wps_clip_image-18096

Figure 4.1 math_MultipleVarFunctionWithHessian class diagram

由上面类图可知,math_MultipleVarFunctionWithHessian派生自带梯度的多元函数类math_MultipleVarFunctionWithGradient。因此,比带梯度的多元函数类多个求值的虚线函数:

Values(const math_Vector&X, Standard_Real&F, math_Vector&G, math_Matrix&H) = 0

通过这个线虚函数计算出多元函数在指定变量X处的函数F,梯度值G和Hessian Matrix H。

因为math_MultipleVarFunctionWithHessian有纯虚函数,所以也不能直接实例化,需要根据实际情况从其派生类来使用。正如本文开头所示的类图中几个类一样,从带有Hessian Matrix的多元函数派生出新类来计算全局极值和曲线光顺,如下类图所示:

wps_clip_image-12818

Figure 4.2 math_MultipleVarFunctionWithHessian class diagram

5.Conclusion

在OPEN CASCADE的数学包Package math中不仅描述了只有一个自变量的一元函数math_Function,也描述了具有多个自变量的多元函数,及其一阶导数(梯度)和二阶导数(Hessian Matrix)。通过应用多元函数的积分计算,可以看出OCC对这些概念进行的类封装还是很清晰,便于理解和使用。对于这些基础概念的介绍,便于理解后面具体的优化算法的使用。

从OPEN CASCADE中的优化算法可以看出,核心是数学这个精巧工具的熟练应用。可以找出《高等数学》、《线性代数》、《最优化方法》、《非线性最优化理论与方法》、《数值分析》等相关书籍,通过对比OPEN CASCADE中的程序实现有效的理论联系实践,提高学习效率。而对高等数学和线性代数可以做到温故知新,对原来百思不解的问题可以有个Aha!的恍然大悟,找到学习的乐趣。

6. References

1. 同济大学数学教研室. 高等数学. 高等教育出版社. 1996

2. 同济大学应用数学系. 线性代数. 高等教育出版社. 2003

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

4. 《运筹学》教材编写组. 运筹学. 清华大学出版社. 2012

5. 何坚勇. 最优化方法. 清华大学出版社. 2007

6. 杨庆之. 最优化方法. 科学出版社. 2015

7. 王宜举, 修乃华. 非线性最优化理论与方法. 科学出版社. 2012

 



eryar 2015-11-29 16:22 发表评论

Apply Newton Method to Find Extrema in OPEN CASCADE

$
0
0
     摘要: Apply Newton Method to Find Extrema in OPEN CASCADE eryar@163.com Abstract. In calculus, Newton’s method is used for finding the roots of a function. In optimization, Newton’s method is...  阅读全文

eryar 2015-12-06 10:47 发表评论

pipedata3d–Ladder


Function Set in OPEN CASCADE

$
0
0

Function Set in OPEN CASCADE

eryar@163.com

Abstract. The common math algorithms library provides a C++ implementation of the most frequently used mathematical algorithms. These include: algorithms to solve a set of linear algebraic equations, algorithms to find the minimum of a function of one or more independent variables, algorithms to find roots of one, or of a set of non-linear equations, algorithm to find the eigenvalues and eigenvectors of a square matrix. The solver for function set is used widely in extrema value evaluation, point project on to curve and surface, also used to solve the point inverse for geometry curve and surface. The paper focus on the function set concept and its solver in OPEN CASCADE.

Key Words. Function Set, Non-Linear Equation Solver, Equations Root, 

1. Introduction

OPEN CASCADE的math包中提供了常见的数值计算的功能,如矩阵的加减乘除,转置及方阵的特征值和特征向量的计算,求解线性方程组;一元函数或多元函数的微分、积分及极值的计算;线性和非线性(Non-Linear Equations)方程组(Function Set)的计算等等。大部分功能和另一个开源科学计算库gsl类似,只是采用面向对象的方式,更便于使用。方程组(Function Set)的相关计算与多元函数(MultiVarFunction)一样地在OPEN CASCADE库广泛地应用,如一些极值计算算法,拟合算法、点在曲线曲面上投影的相关问题等等,都会涉及到方程组求解的计算。如下类图所示。

下面的类图为方程组类Math_FunctionSet的类图,由类图可知,从其派生的类数量很多,由此可见其在OPEN CASCADE中的重要性。本文主要对其用法进行说明,理解其用法后,便于对其他相关算法的理解。

在理解math包中大部分算法后,也是掌握了一个数学计算工具,以后遇到相关的问题,可以尽量地用数学的方式进行解决,提高数学的应用水平。

wps_clip_image-11974

Figure 1.1 math_FunctionSet class diagram in OPENCASCADE

2. Function Set

很多科学理论和工程技术问题都最终转化成非线性方程或方程组的求解,如对理论数据或实验观察的数据进行拟合用到的最小二乘法,就是一个典型的非线性方程组求解的问题。而在几何中的应用就更广泛了,像计算直线与平面的交点问题,点到自由曲线曲面的投影问题等等。鉴于方程组的广泛应用,OPEN CASCADE的数学包中提供了一个抽象类math_FunctionSet来与之对应,方便方程组在程序中的计算。

wps_clip_image-8206

对于普通的方程组,主要设置了三个抽象函数:

v NbVariables():方程组中变量的个数;

v NbEquations():方程组中方程的个数;

v Value():计算指定变量的方程组的值;

带微分的方程组类比普通方程组多两个抽象函数:

v Derivatives():计算指定变量的方程组的微分值;

v Values():计算指定变量的方程组的值和微分值;

因为都是抽象类,所以不能直接使用。下面结合《计算方法》书中的题目,来说明方程组在OPENCASCADE中的计算方法。下面的题目来自《计算方法》第二版P213页例17:设有非线性方程组:

wps_clip_image-5997

从几何上看其解就是圆和曲线的交点。下面给出OPENCASCADE中的计算代码:

/*
*    Copyright (c) 2016 Shing Liu All Rights Reserved.
*
*           File : main.cpp
*         Author : Shing Liu(eryar@163.com)
*           Date : 2016-01-12 21:00
*        Version : OpenCASCADE6.9.0
*
*    Description : test function set.
*/
#define WNT
#include 
<math_FunctionSetRoot.hxx>
#include 
<math_FunctionSetWithDerivatives.hxx>

#pragma comment(lib, 
"TKernel.lib")
#pragma comment(lib, 
"TKMath.lib")

/**
 * @brief test function for a circle and a curve:
 * 
 *  F1(x1,x2) = (x1)^2 + (x2)^2 -4
 *  F2(x1,x2) = e^(x1) + x2 - 1
 *
 * The derivatives of the function set are:
 *  Dx1f1(x1,x2) = 2.0 * x1
 *  Dx2f1(x1,x2) = 2.0 * x2
 *  Dx1f2(x1,x2) = e^(x1)
 *  Dx2f2(x1,x2) = 1.0
 
*/
class test_FunctionSet: public math_FunctionSetWithDerivatives
{
public:
    
virtual Standard_Integer NbVariables() const
    {
        
return 2;
    }

    
virtual Standard_Integer NbEquations() const
    {
        
return 2;
    }

    
virtual Standard_Boolean Value(const math_Vector& X, math_Vector& F)
    {
        F(
1= X(1* X(1+ X(2* X(2- 4.0;
        F(
2= exp(X(1)) + X(2- 1.0;

        
return Standard_True;
    }

    
virtual Standard_Boolean Derivatives(const math_Vector& X, math_Matrix& D)
    {
        D(
1,1= 2.0 * X(1);
        D(
1,2= 2.0 * X(2);
        D(
2,1= exp(X(1));
        D(
2,2= 1.0;

        
return Standard_True;
    }

    
virtual Standard_Boolean Values(const math_Vector& X, math_Vector& F, math_Matrix& D)
    {
        Value(X, F);
        Derivatives(X, D);

        
return Standard_True;
    }
};

void testFunctionSet(void)
{
    test_FunctionSet aTestFunctionSet;

    math_FunctionSetRoot aSolver(aTestFunctionSet);
    math_Vector aStartPoint(
120.0);

    
// initial guess point(-2.0, 0.0)
    aStartPoint(1= -2.0;
    aStartPoint(
2= 0.0;
    aSolver.Perform(aTestFunctionSet, aStartPoint);
    std::cout 
<< aSolver << std::endl;

    
// initial guess point(0.0, -2.0)
    aStartPoint(1= 0.0;
    aStartPoint(
2= -2.0;
    aSolver.Perform(aTestFunctionSet, aStartPoint);
    std::cout 
<< aSolver << std::endl;
}

int main(int argc, char* argv[])
{
    testFunctionSet();
    
return 0;
}

计算结果如下图所示:

wps_clip_image-798

Figure 2.1 Evaluate result

3. Application

在曲线和曲面的极值计算、曲面和曲面的极值计算及点和曲面的极值计算中都用到了求解方程组的算法,如下类图所示:

wps_clip_image-28754

Figure 3.1 Extrema algorithms implemented by Function Set

其中点和曲面极值的计算也适用于曲面上点的参数的反求。与曲线上点的参数反求类似,曲线上点的参数反求是计算非线性方程的根;曲面上点的参数反求则扩展到了非线性方程组。问题求解的关键还是建立数学模型,如点到曲线上的投影由下图可知:

wps_clip_image-26321

Figure 3.2 Point project on curve

构造的函数为:

wps_clip_image-7217

上式表示曲线上过参数u的切线与曲线上参数u的点到指定点的向量的数量积,当f(u)=0时数量积为0,即为点垂直于曲线上过参数u的切线,对此非线性方程求解,即得到了点到曲线的投影。同理,点到曲面的投影也可以建立类似的方程组:

wps_clip_image-30692

其中曲面对参数u,v的偏导数表示在曲面在u,v方向上的切线,两个函数意义和一个方程的意义类似,即点到曲面上某一点的向量与切线的数量积。当向量与两个切线方向的数量积为0的时候,即此向量与这两个切线都垂直,就是点到曲面的投影。这也是OPEN CASCADE中计算点与曲面极值的实现原是,其类为Extrema_FuncExtPS,为了使用类math_FunctionSetRoot对方程组进行求解,Extrema_FuncExtPS也是由类math_FunctionSetWithDerivatives派生,类定义代码如下:

//! Functional for search of extremum of the distance between point P and
//! surface S, starting from approximate solution (u0, v0).
//!
//! The class inherits math_FunctionSetWithDerivatives and thus is intended
//! for use in math_FunctionSetRoot algorithm .
//!
//! Denoting derivatives of the surface S(u,v) by u and v, respectively, as
//! Su and Sv, the two functions to be nullified are:
//!
//! F1(u,v) = (S - P) * Su
//! F2(u,v) = (S - P) * Sv
//!
//! The derivatives of the functional are:
//!
//! Duf1(u,v) = Su^2    + (S-P) * Suu;
//! Dvf1(u,v) = Su * Sv + (S-P) * Suv
//! Duf2(u,v) = Sv * Su + (S-P) * Suv = Dvf1
//! Dvf2(u,v) = Sv^2    + (S-P) * Svv
//!
//! Here * denotes scalar product, and ^2 is square power.
class Extrema_FuncExtPS  : public math_FunctionSetWithDerivatives
{
public:

  DEFINE_STANDARD_ALLOC

  
  Standard_EXPORT Extrema_FuncExtPS();
  
  Standard_EXPORT Extrema_FuncExtPS(
const gp_Pnt& P, const Adaptor3d_Surface& S);
  
  
//! sets the field mysurf of the function.
  Standard_EXPORT void Initialize (const Adaptor3d_Surface& S);
  
  
//! sets the field mysurf of the function.
  Standard_EXPORT void SetPoint (const gp_Pnt& P);
  
  Standard_EXPORT Standard_Integer NbVariables() 
const Standard_OVERRIDE;
  
  Standard_EXPORT Standard_Integer NbEquations() 
const Standard_OVERRIDE;
  
  
//! Calculate Fi(U,V).
  Standard_EXPORT Standard_Boolean Value (const math_Vector& UV, math_Vector& F) Standard_OVERRIDE;
  
  
//! Calculate Fi'(U,V).
  Standard_EXPORT Standard_Boolean Derivatives (const math_Vector& UV, math_Matrix& DF) Standard_OVERRIDE;
  
  
//! Calculate Fi(U,V) and Fi'(U,V).
  Standard_EXPORT Standard_Boolean Values (const math_Vector& UV, math_Vector& F, math_Matrix& DF) Standard_OVERRIDE;
  
  
//! Save the found extremum.
  Standard_EXPORT virtual Standard_Integer GetStateNumber() Standard_OVERRIDE;
  
  
//! Return the number of found extrema.
  Standard_EXPORT Standard_Integer NbExt() const;
  
  
//! Return the value of the Nth distance.
  Standard_EXPORT Standard_Real SquareDistance (const Standard_Integer N) const;
  
  
//! Returns the Nth extremum.
  Standard_EXPORT const Extrema_POnSurf& Point (const Standard_Integer N) const;

protected:


private:

  gp_Pnt myP;
  Adaptor3d_SurfacePtr myS;
  Standard_Real myU;
  Standard_Real myV;
  gp_Pnt myPs;
  TColStd_SequenceOfReal mySqDist;
  Extrema_SequenceOfPOnSurf myPoint;
  Standard_Boolean myPinit;
  Standard_Boolean mySinit;

};

 

根据其注释可知,建立的方程组和上述方程组相同,并且还计算了方程组的一阶偏导数如下:

wps_clip_image-24065

通过类math_FunctionSetRoot对上述方程组进行求解,即可得到点到曲面的极值。

4. Conclusion

线性和非线性方程组的求解在几何中也有大量的应用。线性方程组可以利用矩阵的概念进行求解,如Gauss消元法。而非线性方程组的求解也是有相关的算法,如Newton法等,具体理论可参考《计算方法》等相关书籍。掌握这些数学工具之后,关键是将几何问题抽象成数学问题,然后利用这些数学工具来解决实际问题。从而可以将《高等数学》、《线性代数》等理论知识,通过《计算方法》在计算机中的实现,来用理论指导实践,通过实践加深理论的理解。也让枯燥的理论更生动、有趣。

与OPEN CASCADE数学包中其他概念如一元函数,多元函数等概念一样,非线性方程组及其求解也是一个重要概念。理解这些类的原理之后,便于对其他几何造型算法的实现原理进行理解。

5. References

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

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

3. 易大义,沈云宝,李有法. 计算方法. 浙江大学出版社. 2002

4. 蒋尔雄,赵风光,苏仰锋. 数值逼近. 复旦大学出版社. 2012

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

6. 同济大学数学教研室. 高等数学. 高等教育出版社. 1996

7. 同济大学应用数学系. 线性代数. 高等教育出版社. 2003



eryar 2016-01-13 19:38 发表评论

OPEN CASCADE编译视频

$
0
0

为了帮助OPEN CASCADE新手顺利编译OPEN CASCADE源码,特录制了一个视频,
有了这个视频,OPEN CASCADE的编译再也不麻烦啦!


eryar 2016-01-20 21:49 发表评论

OpenCascade Jobs

$
0
0
OpenCascade Jobs

OpenCascade工作相关信息发布,有意者可以直接发邮件:eryar@163.com

鞋博士鞋博士经过8年沉淀,在鞋类工业4.0全流程平台上积累了相当的技术实力,获投资商亲睐。
新的一年,在投资商协助下,将踏上新的征途,因此诚邀您加盟顶层技术合伙人。
如果您具备以下实力,我们期待您的加盟:

1、熟悉C++

2、熟悉图形学

3、学过矩阵,优化理论者优先

4、能阅读英文技术文档

5、人品好,踏实稳重

 

待遇:达到行业正常水平,我们提供如下待遇:

1年C++经验:8000(税后)

2年C++经验:10000(税后)

3年C++经验:11000(税后)

4年C++经验:12000(税后)

5年C++经验:14000(税后)

 

工作地点:东莞或广州

工资参照:东莞房价:1万左右,实际不超过一万。我们将提供中等偏上的薪酬以及顶层技术合伙人的股权待遇。



eryar 2016-02-24 20:22 发表评论

OpenCASCADE Ring Type Spring Modeling

$
0
0

OpenCASCADE Ring Type Spring Modeling

eryar@163.com

Abstract. The general method to directly create an edge is to give a 3D curve as the support(geometric domain) of the edge. The curve maybe defined as a 2D curve in the parametric space of a surface: PCurve. When you understand the pcurve, you can modeling some interesting shapes, such as bottle neck thread, helix spring, ring type spring. Etc. The paper is focus on the Ring Type Spring Modeling in OpenCASCADE Draw Test Harness by Tcl script.

Key Words. Spring, Helix, Tcl/Tk, 环形弹簧

1. Introduction

在上网的时候不经意看到了ZWCAD论坛上的这么一个帖子:环形弹簧三维建模练习:http://www.zwcad.com/community/forum.php?mod=viewthread&tid=2302

wps_clip_image-2001

Figure 1.1 Ring Type Spring

从上图可见,这个图形还是很有趣的,论坛中给出了在ZW中造型的一种方法,即先创建一个螺旋圆环,再用圆形陈列来得到这个环形弹簧。

如何在OpenCASCADE中来造型呢?我想的方法是利用扫掠,关键就是扫掠的路径环形螺放线的构造出来。因为原来使用过pcurve来生成过一个普通的弹簧,所以在想能不能在这个基础上进行扩展,来对这种环形弹簧来造型。

2.PCurve 

根据pcurve的定义:The curve may be defined as a 2d curve in the parametric space of a surface. 可以看出pcurve的两个特点:

v pcurve是一条二维曲线;

v 与曲面相关;

即pcurve就是曲面参数空间中一条二维曲线,pcurve上的点就是曲面参数空间中的点,其映射过程为:pcurve根据一个参数x计算得到一个二维点(u,v),将这个二维点(u,v)作为曲面的参数计算出曲面上的点S(u,v),即为pcurve对应到曲面上的曲线。因为是环形的,所以我联想到了Torus曲面,如下图所示:

wps_clip_image-2987

Figure 2.1 Torus in OpenCASCADE Draw Test Harness

在Draw Test Harness中生成一个圆环面还是很简单的,只需要以下几条命令:

pload ALL 

torus t 
1 0.3 

mkface f t 

vdisplay f 

根据利用圆柱面来对普通弹簧造型的方法“Make Helix Curve in OpenCASCADE”

http://www.cppblog.com/eryar/archive/2015/07/09/211212.html ,是否可以利用圆环面来生成圆环弹簧呢?实践是检验真理的唯一标准,随便尝试,反正失败了也没有什么损失。要利用pcurve就要找出曲面及其参数空间的一条二维曲线,现在初步确定了曲面为torus面,下面再来寻找pcurve。根据《OpenCASCADE BRep Format》中对于Torus的参数表示方程为:

wps_clip_image-16710

wps_clip_image-3246

由参数方程可知,torus面的参数空间为0到2PI的一个正方形区域,如下图所示:

wps_clip_image-5822

Figure 2.2 PCurve of Torus Face

当u=0或v=0时,曲面的参数方程为:

wps_clip_image-24802

wps_clip_image-493wps_clip_image-14106

Figure 2.3 Torus curves when u=0 and v=0

对应到参数空间分别为u轴上的直线和v轴上的直线。当u取几个固定值,v在参数空间任意变化时,即可以得到圆环面上几个圆形曲线。当u,v参数连续变化时,先用最简单的一次曲线直线来尝试下,Tcl脚本如下所示:

 

# 
# make helix torus in OpenCASCADE. 
# Shing Liu(eryar@163.com) 
# 2016-02-20 21:00 


pload MODELING VISUALIZATION 

# use torus surface. 
torus aTorus 10 2 

set aSlope 
0.05 
line aLine2d 
0 0 $aSlope 1 
trim aSegment aLine2d 
0 2*pi 

# make edge by the pcurve. 
mkedge aHelixEdge aSegment aTorus 0 2*pi/$aSlope 

# there is no curve 3d in the pcurve edge. 
# so need this to approximate one. 

mkedgecurve aHelixEdge 0.01 

# display the edge. 
vdisplay  aHelixEdge 

生成结果如下图所示:

wps_clip_image-19095

Figure 2.4 Torus Curve made by pcurve

其中螺距的调整可以通过调整pcurve的斜率来实现。

wps_clip_image-17217

Figure 2.5 Torus Spring

由图可见,pcurve使用直线效果比较理想。曲线生成之后,只需要将一个轮廓沿着曲线扫掠即可。

3.Modeling in Draw Test Harness

将上述放在一起来实现一个环形弹簧的造型,为了便于测试,主要是在Draw Test Harness中使用Tcl脚本来测试效果。使用Tcl脚本来测试效果有很多好处,主要就是不需要编写C++代码,也不用编译,可以实时检验结果。而且OpenCASCADE的Tcl脚本也可以很方便地翻译成C++代码。所以学习一下Tcl脚本还是有很多好处的,如Tcl具有跨平台的特性,通过使用脚本,可以对参数化有更进一步的理解等。言归正传,下面给出环形弹簧造型的Tcl脚本:

 

#
# make helix torus(Ring Type Spring) in OpenCASCADE.
# Shing Liu(eryar@163.com)
# 2016-02-20 21:00
#


pload MODELING VISUALIZATION

# use torus surface.
torus aTorus 10 2

set aSlope 
0.05
line aLine2d 
0 0 $aSlope 1
trim aSegment aLine2d 
0 2*pi

# make edge by the pcurve.
mkedge aHelixEdge aSegment aTorus 0 2*pi/$aSlope

# there is no curve 3d in the pcurve edge.
# so need this to approximate one.

mkedgecurve aHelixEdge 0.01

wire aHelixWire aHelixEdge

# make the profile.
circle aProfile 12 0 0 1 1 1 0.3
mkedge aProfile aProfile
wire aProfile aProfile
mkplane aProfile aProfile

# display the profile.
vdisplay aProfile aHelixEdge

# loft the circle along the helix curve.
pipe aSpring aHelixWire aProfile

# display the result.
vdisplay aSpring
#vsetmaterial aSpring steel
vsetgradientbg 180 200 255 180 180 180 2
vsetdispmode 
1
vzbufftrihedron

set ray tracing
if { ! [catch {vrenderparams -raytrace -shadows -reflections -fsaa -rayDepth 5}] } {
  vtextureenv on 
1
}

生成结果如下图所示:

wps_clip_image-6995

下图是使用Ray Tracing后显示的效果,感觉不错:

wps_clip_image-31391

wps_clip_image-23847

4. Conclusion

综上所述,理解了pcurve后可以对一些规则的有趣的曲线进行造型。另外学会在Draw Test Harness中使用Tcl脚本来尝试自己的想法,将会感觉到脚本的便利性。其实在OpenCASCADE的官网上也是提倡使用Tcl脚本来报告bug。

5. References

1. OpenCASCADE BRep Format

2. Shing Liu. Make Helix Curve in OpenCASCADE. 

http://www.cppblog.com/eryar/archive/2015/07/09/211212.html

3. ZW3D community topic:

http://www.zwcad.com/community/forum.php?mod=viewthread&tid=2302

 



eryar 2016-03-05 00:51 发表评论

Tcl internal variables

$
0
0

Tcl internal variables

eryar@163.com

在Tcl中内置了一些变量,并赋予了一定的功能。内置变量列表如下:

变量名称

功能描述

argc

指命令行参数的个数。

argv 

指包含命令行参数的列表。 

argv0  

是指被解释的文件或由调用脚本的名称的文件名。

env  

用于表示是环境变量数组元素。

errorCode 

为最后的Tcl错误的错误代码。

errorInfo 

为最后Tcl错误的堆栈跟踪信息。

tcl_interactive 

分别将其设置为1和0交互和非交互模式之间切换。

tcl_library 

用于设置的标准Tcl库的位置。 

tcl_pkgPath 

提供一般都安装包的目录列表。

tcl_patchLevel 

指的是Tcl解释目前的补丁级别。 

tcl_platform  

用于表示使用对象,包括byteOrder, machine, osVersion平台和操作系统数组元素。

tcl_precision  

指的是精度,即位数转换为浮点数时,字符串保留。默认值是12。

tcl_prompt1 

指的是主提示符。

tcl_prompt2 

指无效的命令二次提示。

tcl_rcFileName 

为用户提供了具体的启动文件。 

tcl_traceCompile 

用于控制字节码编译的跟踪。用0表示无输出,1为概要和2为详细。

tcl_traceExec 

用于控制执行的字节码的跟踪。用0表示无输出,1为概要和2为详细。

tcl_version  

返回Tcl解释器的最新版本。

使用内置变量的例子,获取Tcl版本信息,获取环境变量,更改Tcl提示符:
# tcl version 
puts $tcl_version 

# tcl env variable 
puts $env(username) 

puts 
$env(path) 

# tcl prompt 
set tcl_prompt1 {puts -nonewline "command>"

 

wps_clip_image-30168



eryar 2016-03-12 10:51 发表评论

RvmTranslator 3.1 is released

$
0
0

RvmTranslator 3.1 is released

Fix the crash reported by Luca from Italy. The crash is made by the invalidate shapes that the RvmTranslator can not translate correctly. Thanks for Luca.

wps_clip_image-22109

Figure 1. Ship model translate by RvmTranslator

Download RvmTranslator:

Version

Download

RvmTranslator1.0

Download

RvmTranslator2.0

Download

RvmTranslator2.1

Download

RvmTranslator2.2

Download

RvmTranslator3.0

Download

RvmTranslator3.1

Download

 



eryar 2016-03-14 23:29 发表评论

OpenCASCADE Interpolations and Approximations

$
0
0

OpenCASCADE Interpolations and Approximations

eryar@163.com

Abstract. In modeling, it is often required to approximate or interpolate points to curves and surfaces. In interpolation, the process is complete when the curve or surface passes through all the points; in approximation, when it is as close to these points as possible. The paper is the translation of the OpenCASCADE Modeling Data user guide.

Key Words. Interpolation, Approximation, Fitting

1.Introduction

在几何造型中,经常会需要根据点去拟合(插值Interpolation或逼近Approximation)曲线曲面。插值要求拟合所得的曲线或曲面必须通过所有拟合点;而逼近要求拟合所得曲线或曲面尽可能地靠近全部拟合点。OpenCASCADE中提供了曲线曲面拟合的功能有:

v 对二维点进行二维B样条或Bezier曲线插值;

v 对二维点进行二维B样条或Bezier曲线逼近;

v 对三维点进行三维B样条或Bezier曲线或B样条曲面插值;

v 对三维点进行三维B样条或Bezier曲线或B样条曲面逼近;

程序中使用拟合功能有两种方式:

v 使用高级功能:提供简单的方法调用来获得拟合结果;

v 使用低级功能:专为想对拟合有更多控制的用户设计;

插值和逼近也是数值分析或计算方法中的主要内容。用B样条作为插值或逼近函数是数值分析中的一个具体方法。通过对OpenCASCADE中插值和逼近算法的学习,加深对一些算法,如最小二乘法,多元函数求极值等数学知识的理解。

本文主要是对OpenCASCADE的文档Modeling Data 中的插值和逼近部分进行翻译,并给出了使用其低级功能具体的代码示例。

2.Analysis of a set of points

包GProp中的类PEquation提供了对点集、点云数据进行分析的功能,可以用来验证在给定的精度范围内是否重合、共线或共面等,如果检测结果是,那么算法将计算出这些点的重合点、线或面。如果检测结果不是,则算法会计算出点集或点云的包围盒。

3.Basic Interpolation and Approximation

包Geom2dAPI和GeomAPI提供了拟合(逼近和插值)简单的方法。

v 2D Interpolation: 类Geom2dAPI_Interpolate可以用于生成一条通过一系列点的二维B样条曲线。如果需要,还可以设置点相应的切矢及参数来对插值曲线做进一步的约束。

v 3D Interpolation: 类GeomAPI_Interpolate可以用于生成一条通过一系列点的三维B样条曲线。如果需要,还可以设置点相应的切矢及参数来对插值曲线做进一步的约束。因为是高级功能,所以需要很少的代码就可以得到插值曲线,用法如下:

GeomAPI_Interpolate Interp(Points);

Handle_Geom_BSplineCurve C = Interp.Curve()

v 2D Approximation: 类Geom2dAPI_PointsToBSpline可以用于生成逼近一系列点的二维B样条曲线。你需要定义曲线次数范围,连续性和容差。容差值只是用来检查逼近点之间是不是有重合点,或者切矢是否太小。逼近曲线将会是C2连续或2次曲线,当有切矢约束时,将会得到C1连续的曲线。

wps_clip_image-12820

v 3D Approximation:类GeomAPI_PointsToBSpline可以用于生成逼近一系列点的三维B样条曲线。你需要定义曲线次数范围,连续性和容差。容差值只是用来检查逼近点之间是不是有重合点,或者切矢是否太小。逼近曲线将会是C2连续或2次曲线,当有切矢约束时,将会得到C1连续的曲线。类的用法如下:

GeomAPI_PointsToBSpline Approx(Points, DegMin, DegMax, Continutity, Tol);

Handle_Geom_BSplineCurve K = Approx.Curve()

v Surface Approximation:类GeomAPI_PointsToBSplineSurface可以用于根据点集拟合B样条曲面。

4.Advanced Approximation

包AppDef和AppParCurves提供了低级的功能,允许对拟合有更多地控制。低级功能提供了如下函数接口API:

v 定义拟合切矢的规则,这些切矢有原点和极值;

v 根据各自参数平行地拟合一系列曲线;

v 光滑拟合:生成光顺(faired curve)的曲线。

注:包AppDef和AppParCurves中通过宏定义实现了一种类似多态的功能,但是程序调试不方便,导致一些类名没有看到声明文件,对程序的理解造成一些不便。

4.1 Approximation by multiple point constraints

包AppDef中提供了低级工具用于对带约束的点集进行Bezier或B样条曲线拟合。其中的功能有:

v 定义一组约束点,使用类AppDef_MultiPointConstraint;

v 定义一组约束线,使用类AppDef_MultiLine;

v 拟合Bezier曲线,使用类AppDef_Compute;

v 拟合B样条曲线,使用类AppDef_BSplineCompute;

v 定义变分标准Variational Criteria;

注:在类AppDef_Variational中可以看到Variational Optimization变分优化。对于工科出来的人来说,这些概念还真是有些陌生,还是学数学的人厉害!

其中类AppDef_MultiLine的用法也有点特别,通过文档中的图来理解下:

wps_clip_image-28658

其中:Pi, Qi, Ri, ..., Si可以是二维点或三维点;

按组来定义,其中Pn, Qn, Rn, ..., Sn都是在类AppDef_MultiPointConstraint中定义;

P1, P2, .., Pn或Q, R,..., S的点系列用来拟合。

类AppDef_Compute用Bezier曲线来拟合点;

类AppDef_BSplineCompute用B样条曲线来拟合点;

注:需要仔细理解AppDef_MultiPointConstraint和AppDef_MultiLine的用法。

4.2  Example: How to approximate a curve with low-level tools

使用低级功能的过程可分为如下几步:

v 定义拟合点;

v 根据拟合点创建MultiLine;

v 使用AppDef_Compute或AppDef_BSplineCompute来拟合曲线;

下面给出使用低级功能的代码示例:

 

/*
*    Copyright (c) 2016 Shing Liu All Rights Reserved.
*
*           File : main.cpp
*         Author : Shing Liu(eryar@163.com)
*           Date : 2016-03-17 21:00
*        Version : OpenCASCADE6.9.0
*
*    Description : test the low-level tools of approximation.
*/

#define WNT

#include 
<TColgp_Array1OfPnt.hxx>

#include 
<AppDef_MultiPointConstraint.hxx>
#include 
<AppDef_MultiLine.hxx>
#include 
<AppDef_Compute.hxx>
#include 
<AppDef_BSplineCompute.hxx>

#pragma comment(lib, 
"TKernel.lib")
#pragma comment(lib, 
"TKMath.lib")
#pragma comment(lib, 
"TKGeomBase.lib")


void testBezierApprox()
{
    TColgp_Array1OfPnt aPoints(
13);
    aPoints.SetValue(
1, gp_Pnt(0.00.00.0));
    aPoints.SetValue(
2, gp_Pnt(1.00.00.0));
    aPoints.SetValue(
3, gp_Pnt(1.01.00.0));

    AppDef_MultiLine aMultiLine(aPoints);

    AppDef_Compute aBezierApprox(aMultiLine);
    aBezierApprox.Value().Dump(std::cout);

}

void testBSplineApprox()
{
    AppDef_MultiLine aMultiLine(
3);

    AppDef_MultiPointConstraint aMPC1(
20);
    AppDef_MultiPointConstraint aMPC2(
20);
    AppDef_MultiPointConstraint aMPC3(
20);

    aMPC1.SetPoint(
1, gp_Pnt(0.00.00.0));
    aMPC1.SetPoint(
2, gp_Pnt(0.02.00.0));

    aMPC2.SetPoint(
1, gp_Pnt(1.00.00.0));
    aMPC2.SetPoint(
2, gp_Pnt(1.02.00.0));

    aMPC3.SetPoint(
1, gp_Pnt(1.01.00.0));
    aMPC3.SetPoint(
2, gp_Pnt(1.03.01.0));

    aMultiLine.SetValue(
1, aMPC1);
    aMultiLine.SetValue(
2, aMPC2);
    aMultiLine.SetValue(
3, aMPC3);

    AppDef_BSplineCompute aBSplineApprox(aMultiLine);
    aBSplineApprox.Value().Dump(std::cout);
}

int main(int argc, char* argv[])
{
    testBezierApprox();

    testBSplineApprox();

    
return 0;
}

程序运行结果如下图所示:

wps_clip_image-1016

5.Conclusion

关于点的插值和逼近是《数据逼近》或《数值分析》或《计算方法》书中关注的内容。从文档中可以看到包AppDef中的一些关键字:Gradient, BFGS, LeastSquare等,根据这些关键字可以看出OpenCASCADE中逼近使用的算法了。

wps_clip_image-27642

通过使用AppDef_MultiPointConstraint及AppDef_MultiLine等低级接口,来理解拟合数据点输入及拟合结果的输出。进而去学习BFGS、LeastSquare等数学理论工具在实际中的应用。对于多元函数,梯度及BFGS等概念还好接受,对于变分法优化之类理论已经超出了工科数学的范围,不过结合实际去学习这些概念应该会更有效率。



eryar 2016-03-17 23:10 发表评论

OpenCASCADE Data Exchange - 3D PDF

$
0
0

OpenCASCADE Data Exchange - 3D PDF

eryar@163.com

Abstract. Today most 3D engineering model data are save to 3D PDF files. Universal 3D(U3D) along side Product Representation Compact(PRC), U3D is the historical foundation used to embed 3D interactive data and models into a PDF file. But PRC is now the preferred and most feature-rich method to embed 3D data into a PDF file. So the paper is focus on to translate OpenCASCADE geometry data to 3D PDF by embedding PRC file.

Key Words. PDF 3D, OpenCASCADE, U3D, PRC, libharu


1.Introduction

如今很多工程模型会转换成3D PDF格式,这样用户可以使用免费的Adobe Reader去查看模型,减轻用户软件授权费用。3D PDF可用于工程设计、制造、数值造型、医学、空间、地理及石油气的探索,建筑工程和环境调查,也可作为CAM、CAE、PLM的数据交换文件。还可用于培训、市场、存档及工程汇报等。

那么问题来了,如何将三维模型导入PDF文件呢?Adobe提供了嵌入两种文件格式U3D(Universal 3D)和PRC(Product Representation Compact)的方式来将三维模型导入PDF中。

U3D出现的时间较早,在sourceforge上有个u3d的库:

https://sourceforge.net/projects/u3d/

可用于将三维模型转换成U3D格式。其中MeshLab就是使用了这个工具,先将三维网格模型转换成IDTF格式,再调用IDTFConverter程序将其转换成U3D格式。下载了u3d的源码看了下,使用还比较复杂,而且软件授权方式是GPL的。

PRC是出现的比U3D要晚,所以PRC支持的几何形状比U3D要多,包括支持NURBS曲线曲面,还支持复杂的组合体。在网上找了下实现PRC文件读写的源码存在于一款数学软件Asymptote中,https://sourceforge.net/projects/asymptote

发现这个库使用起来相对U3D的要简单,且支持NURBS曲线曲面。

三维模型准备好了,需要将这些模型文件嵌入到PDF中。在网上找了下有个开源库libharu还是很不错的。

综上所述,准备考虑使用PRC->3D PDF的套路来实现将OpenCASCADE中的几何模型转换成3D PDF文件。

wps_clip_image-22938

2.Code Example

结合上述思路,下载相应的库并编译通过,只需要如下简单的代码就可以将模型嵌入PDF中了,代码如下:

 

/*
*    Copyright (c) 2016 Shing Liu All Rights Reserved.
*
*           File : main.cpp
*         Author : Shing Liu(eryar@163.com)
*           Date : 2016-03-24 21:00
*        Version : OpenCASCADE6.9.0
*
*    Description : test embed 3d model into 3d pdf.
*/

#include
"oPrcFile.h"

#include
"hpdf.h"

#pragma comment(lib,
"libprc.lib")
#pragma comment(lib,
"libhpdfd.lib")

void testPrc(void)
{
    prc::oPRCFile aPrcFile(
"test.prc");

    prc::PRCmaterial materialGreen(
        prc::RGBAColour(
0.0,0.18,0.0),
        prc::RGBAColour(
0.0,0.878431,0.0),
        prc::RGBAColour(
0.0,0.32,0.0),
        prc::RGBAColour(
0.0,0.072,0.0),
       
1.0,0.1);

   
// Sphere
    aPrcFile.begingroup("Sphere");
    aPrcFile.addSphere(
1.0, materialGreen);
    aPrcFile.endgroup();

    aPrcFile.addCylinder(
0.8, 6.0, materialGreen);

    aPrcFile.finish();

   
// embed prc file to pdf.
    HPDF_Doc aPdfDoc = HPDF_New (NULL, NULL);
   
if (!aPdfDoc)
    {
        printf(
"error: cannot create PdfDoc object");
       
return;
    }

    HPDF_Rect aRect
= {0, 0, 800, 800};
    HPDF_Page aPage
= HPDF_AddPage(aPdfDoc);
    HPDF_Page_SetWidth(aPage, aRect.right);
    HPDF_Page_SetHeight(aPage,aRect.top);

    HPDF_U3D aU3D
= HPDF_LoadU3DFromFile(aPdfDoc, "test.prc");
    HPDF_Annotation aAnnot
= HPDF_Page_Create3DAnnot(aPage, aRect, HPDF_TRUE, HPDF_FALSE, aU3D, NULL);

    HPDF_SaveToFile(aPdfDoc,
"test.pdf");

    HPDF_Free(aPdfDoc);
}

int main(int argc, char* argv[])
{
    testPrc();

   
return 0;
}

生成的test.pdf如下图所示:

wps_clip_image-20731 

Download 3D PDF test.pdf


3.Conclusion

通过将三维模型转换成U3D或PRC格式,就可以嵌入PDF中生成3D PDF。因为Adobe Reader的免费使用,所以可以减轻用户软件授权费用。若三维软件系统可以生成3D PDF也是一个功能亮点。

本文详细说明了如何将几何模型嵌入3D PDF中,并给出了代码示例。OpenCASCADE中的NURBS曲线曲面也可以直接转换成PRC格式。虽然PRC中也有BREP体,但是正确转换的前提是需要开发人员对两者的BREP有清晰的认识,难度较大。一种简单的处理方法是将模型全部转换成网格数据,再转换成PRC。

4.References

1. http://www.pdf3d.com/understanding-how-pdfe-u3d-and-prc-are-related-to-3d-pdf/

2. http://www.pdf3d.com/about-prc/

3. http://www.pdf3d.com/u3d/



eryar 2016-03-24 23:16 发表评论

Compile FreeCAD on Windows

$
0
0

Compile FreeCAD on Windows

eryar@163.com

1.Introduction

FreeCAD是一个参数化的三维造型软件,主要用于任意大小的实际模型的设计。参数化的建模方式可以通过修改相关参数从而方便地修改你的设计。FreeCAD是开源软件,并提供了便利地自定义方式,也提供了脚本,从而根据自己的需要去扩展功能。FreeCAD是跨平台(Windows, Mac和Linux),可以读写许多开放的模型文件,如STEP,IGES,STL,SVG,DXF,OBJ,IFC,DAE等。

如果说学习OpenCASCADE可以了解一些几何内核底层的算法,那么学习FreeCAD则可以用来实现一些具体的功能,从而将三维的技术应用到实际的生活中去,创造出有意义的功能。

本文详细说明如何在Windows平台上编译FreeCAD源码。如果你已经可以正常编译OpenCASCADE这种开源库的源码,那么编译FreeCAD还是很简单的。

2.Preparation

编译FreeCAD源码之前,需要做些准备工作:下载源码及所需的第三方库。其中源码可以从github上下载,地址为:https://github.com/FreeCAD

为了方便其源码的编译,FreeCAD将所需要的第三方库打包在一起取名LibPack,方便开发者自己编译。LibPack可以从sourceforge上下载:

https://sourceforge.net/projects/free-cad/files/FreeCAD%20LibPack/

wps_clip_image-26073

Figure 2.1 Download LibPack of FreeCAD

找到与自己编译器版本一致的LibPack下载。如果想在Visual Studio2008中编译,则下载FreeCADLibs_11.1_x86_VC9.7z。下载好源码和LibPack就万事具备了,我们先来粗略地看下LibPack中都有哪些库:

wps_clip_image-30453

Figure 2.2 3rd party libraries used in FreeCAD

从include可以看出,几何内核主要使用了oce(OpenCASCADE社区版),脚本使用了Python,显示使用了Inventor,网格库还使用了SMESH,逆向工程的功能使用了pcl,还用到了boost及eigen矩阵计算库,程序界面使用了Qt等。由此可见,FreeCAD中的第三方库的数量比OpenCASCADE中的要多,所以编译成功的关键就是要将这些第三方库配置正确。

还好FreeCAD的开发团队提供了这些第三方库,如果自己去准备这些库也要花不少时间和精力。

3.Compiling

FreeCAD在Windows中编译主要使用CMake,通过CMake生成Visual Studio工程文件。如果直接Configure源码文件夹中的CMakeLists.txt会有如下图所示的错误:

wps_clip_image-18431

Figure 3.1 Could not find libpack error

根据错误信息,说是没有在指定目录找到libpack,所以自己将FREECAD_LIBPACK_DIR设置到下载的libpack中去之后,就可以Configure成功了,如下图所示:

wps_clip_image-26076

Figure 3.2 CMake success

Configure成功后,即可使用Generate来生成FreeCAD_trunk.sln工程文件,从而用Visual Studio来打开和编译了。

wps_clip_image-8433

Figure 3.3 FreeCAD projects in Visual Studio

看着自己编译一个模块,在FreeCAD的功能选择中就多出一个模块,还是很有感觉的。自己动手编译下,经过漫长的等待后得到可以运行的程序也是有些收获。

4.Play

编译成功后,就迫不及待地想测试下很有亮点的功能,如网格设计、逆向工程、机器人等模块。

wps_clip_image-3527

Figure 4.1 Shape in Wireframe mode

wps_clip_image-12981

Figure 4.2 Shape Mesh

wps_clip_image-28814

Figure 4.3 Assembly in FreeCAD

看到Assembly中只有那一个按钮,装配功能基本上不能用。如果有了装配功能,那么FreeCAD的功能就和常见的那些三维软件功能类似了。装配功能中需要用到了三维的约束,像什么面对齐,同轴等,商用软件会用到西门子的约束求解库DCM,DCM相关信息可参考simens官方网站:

https://www.plm.automation.siemens.com/en_us/products/open/d-cubed/

有需要DCM的可直接与他们联系,不过价格也是不便宜的。

wps_clip_image-9288

Figure 4.4 DCM of SIEMENS

没有了google找点东西还是很费劲,用baidu和bing中文版的都没找到什么有用的东西。用了Bing英语版的,才找到,如下图同样输入关键字dcm3d,百度中出来的东西完全无用:

wps_clip_image-10165

Figure 4.5 Search result of DCM3d

FreeCAD中机器人功能的视频:http://www.tudou.com/listplay/5zDaAoucSXQ/

wps_clip_image-20045

Figure 4.6 Robot in FreeCAD



eryar 2016-05-08 11:07 发表评论

OpenCASCADE Expression Interpreter by Flex & Bison

$
0
0

OpenCASCADE Expression Interpreter by Flex & Bison

eryar@163.com

Abstract. OpenCASCADE provide data structure of any expression, relation or function used in mathematics. Flex and Bison are tools for building programs that handle structured input. They were originally tools for building compilers, but they have proven to be useful in many other areas. The Expression Interpreter in OpenCASCADE is made by Flex and Bison. So let’s know something about Flex and Bison.

Key Words. OpenCASCADE, Expression Interpreter, Flex, Bison

1.Introduction

OpenCASCADE的TKMath中提供了数学表达式求解的包Expr和ExprIntrp,用来对数学表达式或函数进行解析计算。所谓的数学表达式如:sin(10)+20*6-6/3等。以前在《数据结构》的书上看到用栈的方式来对简单表达式求值,感觉已经很不错了。但是如果表达式中包含三角函数、对数、指数等,程序就要复杂了。如何简单、优雅地去解决这个问题,当时也是很茫然。

工作中遇到前辈自己写了一个用于定义几何的语言,还可以计算表达式。虽然没有看到源码,对其已是崇拜不已。后来接触了脚本语言,像Tcl/Tk,Python之类,发现原来利用这些开源库,也是可以实现一个简单、稳定的自定义开发语言。因为这类脚本不仅可以计算表达式,还可以计算带参数的表达式,如:

set x 3 
set y 
4  
set z [expr 
sqrt($x*$x+$y*$y)]  

只要你在Unix环境中写过程序,你必定会邂逅神秘的Lex&YACC,就如GUN/Linux用户所熟知的Flex&Bison,这里的Flex就是由Vern Paxon实现的一个Lex,Bison则是GNU版本的YACC。学习过《编译原理》的同学们对这两个神器应该不会陌生。使用这两个工具,不仅可以实现一个表达式解析计算器,还可以用来解析SQL语法,如PostgreSQL中就是使用他们实现SQL语法解析。甚至还可以实现一个编译器。

因为是Unix上的工具,在Windows上需要使用winflexbison,可以从sourceforge上下载:https://sourceforge.net/projects/winflexbison/

本文介绍如何使用Flex来理解OpenCASCADE中ExprInterp的实现,开阔视野。OpenCASCADE中ExprInterp的用法见:Evaluate Math Expression

http://www.cppblog.com/eryar/archive/2013/10/09/203625.html

2.Flex Example

FLEX是一个自动化工具,可以按照定义好的规则自动生成一个C函数yylex(),也成为扫描器(Scanner)。这个C函数把文本串作为输入,按照定义好的规则分析文本串中的字符,找到符合规则的一些字符序列后,就执行在规则中定义好的动作(Action)。例如在规则中可以这样定义:如果遇到一个换行字符\n,那么就把行计数器的值加一。 

Flex文件就是一个文本文件,内容包括定义好的一系列词法规则。文件的命名习惯上以小写字母l(L)来作为文件后缀。如果为了清晰,也可以用.flx或者.flex作为文件的后缀名。Flex文件完成后,就执行下列命令: 

$ flex example.flex 

这个命令执行后将生成一个C文件,默认文件名为lex.yy.c。这个C文件主要内容就是函数yylex()的定义。 

如果要直接将这个文件编译成为一个可执行程序,还有一些要注意的地方。如果在Flex文件中没有提供main()函数的定义,那么这个C文件中不会有main()函数。此时单独编译这个C文件的时候,一定要加上-lfl的连接库参数;若提供了main()函数,就不必要提供这个连接库参数了。连接库libfl提供了一个缺省的main函数。缺省的main()函数中只是简单地调用yyflex()函数,而自己提供的main()函数则可以根据需要加入许多其他的处理代码。 

词法规范定义文件给出了单词构成规则。词法文件在习惯上用字母l(即L的小写)来作为后缀。Flex文件由三个部分组成。或者说三个段。三个段之间用两个%%分隔。 

定义段(definitions) 

%% 

规则段(rules) 

%% 

用户代码段(user code) 

下面给出一个简单的Flex程序,代码如下所示:

 

/* hello world for Flex. */
%option noyywrap
%{
int char_count = 0;
int line_count = 0;
%}

%%

\n { 
++char_count; ++line_count; }
.  { 
++char_count; }

%%

int main(int argc, char* argv[])
{
    yylex();
    
    printf(
"# of lines = %d, # of chars = %d\n", line_count, char_count);
    
    
return 0;
}

将上述文件保存为hello.lex,然后运行如下图所示命令:

wps_clip_image-23184

会生成一个lex.yy.c的源程序,将这个C源文件编译,链接即可生成一个可执行程序。运行程序如下图所示:

wps_clip_image-834

3.Flex and Bison in occ

在OpenCASCADE的文件夹中也有相关的语法规则定义,如下图所示:

wps_clip_image-1855

由上图可知,OpenCASCADE的表达式解析功能的实现也是利用了Flex和Bison。

wps_clip_image-32767

wps_clip_image-19144

4.Conclusion

借助于Flex和Bison这两个强大的工具,你可以实现一个高级的计算器,即任意数学表达式计算器。

OpenCASCADE的ExprInterp使用了Flex和Bison实现了数学表达式的解析计算。当理解了工具的用途,有兴趣的读者不妨结合《编译原理》等理论知识,对工具的原理进行一番探究。

5.References

1. 严蔚敏, 吴伟民. 数据结构(C语言版). 清华大学出版社. 1997

2. 赵建华, 郑滔, 戴新宇 译. 编译原理. 机械工业出版社. 2011

3. John Levine, flex & bison. O’REILLY. 2009



eryar 2016-05-27 23:08 发表评论

Make Helix Shape in occQt

$
0
0

Make Helix Shape in occQt

PCurve is a powerful modeling method, to make helix shapes in occQt to help you understand pcurve better, then you can also can model some intereting shape based on pcurve.

OpenCASCADE does not provide helix curve directly, but you can build a helix curve by the pcurve of a surface(curve on surface). When you understand the pcurve of a surface, you can make a helix curve easily.

helix

 

References:

https://github.com/eryar/occQt/issues/11

http://www.cppblog.com/eryar/archive/2015/07/09/211212.html

http://www.cppblog.com/eryar/archive/2016/03/05/212931.html



eryar 2016-06-05 13:44 发表评论

IsoAlgo3d - PCF format 3d visualization tool

$
0
0

IsoAlgo3d - PCF format 3d visualization tool

eryar@163.com

IsoAlgo3d is a PCF format 3d visualization tool. I publish it on github to open the source code. Its license is GPL, you can use the IsoAlgo3d freely.

https://github.com/eryar/IsoAlgo3d

You can download the source code and contribute your modification.

IsoAlgo3d now can visualize pipe and elbow component:

wps_clip_image-32562

For other component I will build the model by SKEY in the source code in the first release version. But finally the model is defined in a parametric way, then you can customize the model for a given SKEY.

Any feedback and suggestions about IsoAlgo3d is welcome.



eryar 2016-06-16 23:21 发表评论
Viewing all 208 articles
Browse latest View live


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>