[求助]样条曲线如何转换为线或圆弧?
本帖最后由 作者 于 2004-6-14 22:37:40 编辑 <br /><br /> <FONT face="Arial Unicode MS">画线命令</FONT>:spline请问高手如何转换(NURBS) 曲线为线或圆弧?
样条曲线也叫云形线(NURBS) 曲线
或者还是不能转换? 有没有高手指点小弟一下!! 如果要在VBA中编程实现,需要下面两个步骤:
(1)利用导出文件的方法,将包含样条曲线的部分导出为WMF,再将导出的文件插入当前图形,并且分解该对象,就能转换成PLINE。
(2)计算PLINE的各个顶点坐标,并且根据凸度来判断直线和曲线段,根据这些参数创建对应的直线和圆弧。
整个过程还是比较复杂的,不过大部分的相关代码可以在本论坛找到。 zfbj发表于2004-6-16 9:23:00static/image/common/back.gif如果要在VBA中编程实现,需要下面两个步骤:
(1)利用导出文件的方法,将包含样条曲线的部分导出为WMF,再将导出的文件插入当前图形,并且分解该对象,就能转...
<FONT face="Arial Unicode MS">请问如果将样条曲线导出文件为</FONT>WMF,再如何导入??
请问张版主(zfbj)第一点能不能再详细点指点给小弟!! 用SendCommand方法调用WmfOut、WmfIn命令 也可以用Export和Import方法来处理。 <FONT face="Arial Unicode MS">先谢谢几位版主</FONT>,<FONT face="Arial Unicode MS">我按照</FONT>zfbj<FONT face="Arial Unicode MS">的方法导出后再导入时</FONT>,<FONT face="Arial Unicode MS">按</FONT>X,Y<FONT face="Arial Unicode MS">以</FONT>2<FONT face="Arial Unicode MS">倍的比例插入后</FONT>,<FONT face="Arial Unicode MS">再炸开</FONT>,<FONT face="Arial Unicode MS">和原</FONT>样条曲线比较,发现有很大的误差.精度达不到要求.<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /><o:p></o:p>
因图档是从PRO/E档中转出到2D,图档需要用线割机台加工的, 线割机台的精度是0.002mm<o:p></o:p>
而导入后再炸开的全都是直线,我随便量了一下,有的距离为0.3766mm, 误差太大,所以不行.<o:p></o:p>
不知还有没有更好的方法?<o:p></o:p>
比如说能不能找到样条曲线的计算公式,下面是我从网上找到的一点点资料不知道行不行?
====================================================================================
<H1>◇ 二次Spline曲线的绘製</H1><PRE><HR>
**********************************************************************
* 二次Spline曲线的绘製 *
* 作者:邱奕南(ID:Chi'u I-Nan,笔名:青衫诗客-小邱) *
* 版权声明:以下文章内容本人仅同意供BBS 站上流传学习,但必须完整流传 *
* (含版权声明及程式),其余权利一概保留。任何未经本人同意 *
* ,将本文贩卖、刊登、节录、或其他一切侵害本人著作权之行为 *
* 者,皆需负担刑事责任及民事赔偿责任。 *
* 备註:本文若有任何错误,或需要补充之处,欢迎写信至90网C语言区告知,*
* 以便传播正确知识。 *
**********************************************************************
在MS-Windows上用过GetGlyphOutline函数的人都知道,取得的TrueType字
形资料包含了两种边线定义方式,一是TT_PRIM_LINE的多边形线,一是
TT_PRIM_QSPLINE的二次(Quadratic)Spline曲线。究竟这个二次Spline曲线
要如何绘製呢?这便是本文所要探讨的课题。首先我们来看一下Spline曲线的
定义。
对於n+1个参考点Pi,i=0~n,k阶Spline曲线的定义为:
n
P(t) = ΣPi * Ni,k(t) ,t = 0~n-k+2
i=0
其中Ni,k(t)为各参考点的加权函数,由下列递迴公式所定义:
(t-v)*Ni,k-1(t) (v-t)*Ni+1,k-1(t)
Ni,k(t) = ───────── + ───────────
v-v v-v
┌ 1若 v <= t <= v
Ni,1(t) = ┤
└ 0t值不在上述值域中
┌ 0 若 i < k-1
v = ┤ i-k+1 若 k-1 <= i <= n+1
└ n-k+2 若 n+1 < i
这个定义是颇为复杂的,我们先来看看k阶Spline曲线倒底有什么特性呢?
1.在每一个区间(v<=t<=v),函数P(t)是一个k-1次多项式。
2.在整条曲线上,P(t)在1~k-2次微分上都是连续的。
也就是说,二次Spline曲线其实便是3阶Spline曲线(k=3)。我们再看看各种
阶数的Spline曲线情况。在2阶的情况下,对每个区间t值化为0~1后,成为:
P(t) = Pi * (1-t) + Pi+1 * t
因此2阶Spline曲线,也就是多边形直线。而对於4参考点的4阶Spline曲线,经
上述公式定义计算后可得:
3 2 2 3
P(t) = (1-t)* P1 + 3t(1-t)* P2 + 3t (1-t) * P3 + t* P4
这个曲线就是常见的三次Bezier曲线。由於本文的主要目的是探讨二次Spline
曲线的绘製方式,因此只著重在3阶的Spline曲线。对於3阶Spline曲线,它有
个重要的特性,便是曲线会正切过相邻两参考点线段的中心点(前后两线例外)。
如果读者觉得上述公式定义不易了解的话,不妨利用此特性自行以几何数学导
出结果。
要绘製3阶Spline曲线,首先便得算出各种数目参考点的Ni,3值(参数点数
目至少必须3个)。以下为作者利用上述Spline曲线公式定义算得的结果,其中
以每3个相邻参考点为一区间,各t值在0~1之间:
1.参考点数恰为3个时
P(t) = (1-t)^2 * P1 + 2t(1-t) * P2 + t^2* P3
2.首段Spline曲线段
P(t) = (1-t)^2 * P1 + t(4-3t)/2 * P2 + t^2/2 * P3
3.中间各段Spline曲线段
P(t) = (1-t)^2/2 * P1 + (-2t^2+2t+1)/2 * P2 + t^2/2 * P3
4.末段Spline曲线段
P(t) = (1-t)^2/2 * P1 + (1-t)(3t+1)/2 * P2 + t^2 * P3
以下便是计算上述各曲线段的模拟线段各点的程式,其中已将t化成整数范围,
并做一些乘法去除的工作(如何去除请参见本人著之"Hermite与Bezier曲线绘
製方法研究"一文):
#define Iterative24 /* 曲线模拟的线数(必须小於32) */
#define Iterative2 (Iterative*Iterative)
#define Iterative3 (Iterative2*Iterative)
static int X_Pos, Y_Pos; // 保存计算得的曲线点
int GetQuadraticSplinePoints(int x1,int y1,int x2,int y2,int x3,int y3,
int curve_type,int **x_array,int **y_array)
{
/* ------------------------------------------------------------
作用:取得二次Spline曲线段各间隔点
输入:x1,y1,x2,y2,x3,y3 = 曲线段三参考点
curve_type = 曲线段形态
0 - 三点二次Spline曲线
1 - 四点以上二次Spline曲线首段
2 - 四点以上二次Spline曲线中段
3 - 四点以上二次Spline曲线末段
输出:x_array, y_array = x,y座标阵列
传回:点数
------------------------------------------------------------ */
int i, m1, m2, m3, k1, k2;
if (curve_type <= 1)
{
X_Pos = x1;
Y_Pos = y1;
m1 = 2*Iterative2;
m2 = 0;
}
else
{
X_Pos = (x1+x2)/2;
Y_Pos = (y1+y2)/2;
m1 = m2 = Iterative2;
}
m3 = 0;
for (i=0; i<Iterative; i++)/* 用Iterative条直线模拟 */
{
k2 = (k1 = (i << 1) + 1) - 2*Iterative;
switch(curve_type)
{
case 0 :
m1 += 2*k2;
m2 += 4*Iterative - 4*k1;
m3 += 2*k1;
break;
case 1 :
m1 += 2*k2;
m2 += 4*Iterative - 3*k1;
m3 += k1;
break;
case 2 :
m1 += k2;
m2 += 2*Iterative - 2*k1;
m3 += k1;
break;
default :
m1 += k2;
m2 += 2*Iterative - 3*k1;
m3 += 2*k1;
break;
}
X_Pos = (int) (((long) x1*m1 + (long) x2*m2 + (long) x3*m3) /
(2*Iterative2));
Y_Pos = (int) (((long) y1*m1 + (long) y2*m2 + (long) y3*m3) /
(2*Iterative2));
}
*x_array = X_Pos;
*y_array = Y_Pos;
return Iterative+1;
}
将呼叫该函数所得到的各点以多边形线段方式相连,即可得到所要的近似曲线。
呼叫时要注意辨别二次Spline曲线的各段情况。
</PRE>
===================================================================================== 你用置顶的曲线操作类试试 不行,出错了!!
<A href="http://bbs.mjtd.com/forum.php?mod=viewthread&tid=22181" target="_blank" >http://bbs.mjtd.com/forum.php?mod=viewthread&tid=22181</A>
页:
[1]
2