david.xw 发表于 2004-6-14 18:04:00

[求助]样条曲线如何转换为线或圆弧?

本帖最后由 作者 于 2004-6-14 22:37:40 编辑 <br /><br /> <FONT face="Arial Unicode MS">画线命令</FONT>:spline



请问高手如何转换(NURBS) 曲线为线或圆弧?


样条曲线也叫云形线(NURBS) 曲线


或者还是不能转换?

david.xw 发表于 2004-6-15 21:11:00

有没有高手指点小弟一下!!

zfbj 发表于 2004-6-16 09:23:00

如果要在VBA中编程实现,需要下面两个步骤:


(1)利用导出文件的方法,将包含样条曲线的部分导出为WMF,再将导出的文件插入当前图形,并且分解该对象,就能转换成PLINE。


(2)计算PLINE的各个顶点坐标,并且根据凸度来判断直线和曲线段,根据这些参数创建对应的直线和圆弧。


整个过程还是比较复杂的,不过大部分的相关代码可以在本论坛找到。

david.xw 发表于 2004-6-16 17:56:00

zfbj发表于2004-6-16 9:23:00static/image/common/back.gif如果要在VBA中编程实现,需要下面两个步骤:



(1)利用导出文件的方法,将包含样条曲线的部分导出为WMF,再将导出的文件插入当前图形,并且分解该对象,就能转...

<FONT face="Arial Unicode MS">请问如果将样条曲线导出文件为</FONT>WMF,再如何导入??



请问张版主(zfbj)第一点能不能再详细点指点给小弟!!

雪山飞狐_lzh 发表于 2004-6-16 20:49:00

用SendCommand方法调用WmfOut、WmfIn命令

mccad 发表于 2004-6-16 20:56:00

也可以用Export和Import方法来处理。

david.xw 发表于 2004-6-17 10:20:00

<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 &lt;= t &lt;= v
    Ni,1(t) = ┤
            └ 0t值不在上述值域中

         ┌ 0   若 i &lt; k-1
    v = ┤ i-k+1 若 k-1 &lt;= i &lt;= n+1
         └ n-k+2 若 n+1 &lt; i

这个定义是颇为复杂的,我们先来看看k阶Spline曲线倒底有什么特性呢?

    1.在每一个区间(v&lt;=t&lt;=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 &lt;= 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&lt;Iterative; i++)/* 用Iterative条直线模拟 */
   {
      k2 = (k1 = (i &lt;&lt; 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>



=====================================================================================

雪山飞狐_lzh 发表于 2004-6-17 10:25:00

你用置顶的曲线操作类试试

david.xw 发表于 2004-6-17 11:53:00

不行,出错了!!


雪山飞狐_lzh 发表于 2004-6-17 12:03:00

<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
查看完整版本: [求助]样条曲线如何转换为线或圆弧?