明经CAD社区

 找回密码
 注册

QQ登录

只需一步,快速开始

搜索
查看: 5589|回复: 14

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

  [复制链接]
发表于 2004-6-14 18:04:00 | 显示全部楼层 |阅读模式
本帖最后由 作者 于 2004-6-14 22:37:40 编辑

画线命令:spline 请问高手如何转换(NURBS) 曲线为线或圆弧? 样条曲线也叫云形线(NURBS) 曲线 或者还是不能转换?
 楼主| 发表于 2004-6-15 21:11:00 | 显示全部楼层
有没有高手指点小弟一下!!
发表于 2004-6-16 09:23:00 | 显示全部楼层
如果要在VBA中编程实现,需要下面两个步骤:


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


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


整个过程还是比较复杂的,不过大部分的相关代码可以在本论坛找到。
 楼主| 发表于 2004-6-16 17:56:00 | 显示全部楼层
zfbj发表于2004-6-16 9:23:00如果要在VBA中编程实现,需要下面两个步骤: (1)利用导出文件的方法,将包含样条曲线的部分导出为WMF,再将导出的文件插入当前图形,并且分解该对象,就能转...
请问如果将样条曲线导出文件为WMF,再如何导入?? 请问张版主(zfbj)第一点能不能再详细点指点给小弟!!
发表于 2004-6-16 20:49:00 | 显示全部楼层
用SendCommand方法调用WmfOut、WmfIn命令
发表于 2004-6-16 20:56:00 | 显示全部楼层
也可以用Export和Import方法来处理。
 楼主| 发表于 2004-6-17 10:20:00 | 显示全部楼层
先谢谢几位版主,我按照zfbj的方法导出后再导入时,X,Y2倍的比例插入后,再炸开,和原样条曲线比较,发现有很大的误差.精度达不到要求. 因图档是从PRO/E档中转出到2D,图档需要用线割机台加工的, 线割机台的精度是0.002mm 而导入后再炸开的全都是直线,我随便量了一下,有的距离为0.3766mm, 误差太大,所以不行. 不知还有没有更好的方法? 比如说能不能找到样条曲线的计算公式,下面是我从网上找到的一点点资料不知道行不行? ====================================================================================

◇ 二次Spline曲线的绘製


********************************************************************** * 二次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[i+k]-t)*Ni+1,k-1(t) Ni,k(t) = ───────── + ─────────── v[i+k-1]-v v[i+k]-v[i+1] ┌ 1 若 v <= t <= v[i+1] Ni,1(t) = ┤ └ 0 t值不在上述值域中 ┌ 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[i+1]),函数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 Iterative 24 /* 曲线模拟的线数(必须小於32) */ #define Iterative2 (Iterative*Iterative) #define Iterative3 (Iterative2*Iterative) static int X_Pos[Iterative+1], Y_Pos[Iterative+1]; // 保存计算得的曲线点 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[0] = x1; Y_Pos[0] = y1; m1 = 2*Iterative2; m2 = 0; } else { X_Pos[0] = (x1+x2)/2; Y_Pos[0] = (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[i+1] = (int) (((long) x1*m1 + (long) x2*m2 + (long) x3*m3) / (2*Iterative2)); Y_Pos[i+1] = (int) (((long) y1*m1 + (long) y2*m2 + (long) y3*m3) / (2*Iterative2)); } *x_array = X_Pos; *y_array = Y_Pos; return Iterative+1; } 将呼叫该函数所得到的各点以多边形线段方式相连,即可得到所要的近似曲线。 呼叫时要注意辨别二次Spline曲线的各段情况。
=====================================================================================
发表于 2004-6-17 10:25:00 | 显示全部楼层
你用置顶的曲线操作类试试
 楼主| 发表于 2004-6-17 11:53:00 | 显示全部楼层
不行,出错了!!


本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

x
发表于 2004-6-17 12:03:00 | 显示全部楼层
您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|CAD论坛|CAD教程|CAD下载|联系我们|关于明经|明经通道 ( 粤ICP备05003914号 )  
©2000-2023 明经通道 版权所有 本站代码,在未取得本站及作者授权的情况下,不得用于商业用途

GMT+8, 2024-11-28 05:27 , Processed in 0.171241 second(s), 25 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表