绘制AutoCad中的曲线(Curve)
来源:互联网 发布:网络接入方式 编辑:程序博客网 时间:2024/05/19 22:26
在处理Dwg图纸的时候,有时候会遇到曲线(Curve)。经过研究发现,曲线的真正定义为Spline,而采用的图形为 非均匀B样条曲线。
作为B样条曲线,可以通过添加多个控制点来控制曲线的细节,而这正是贝塞尔曲线做不到的。同时,修改某个控制点的位置也仅仅修改该控制点附近的曲线。
关于B样条的数学方程的代码很多,例如:
http://blog.csdn.net/tingzhushaohua/article/details/71437169?locationNum=13&fps=1
在这里我们直接找到一个可以用的类库来使用:
public enum BsplineType { Uniform,//均匀B样条 QuasiUniform,//准均匀B样条 PiecewiseBezier,//分段贝奇尔 NonUniform,//非均匀B样条 Null}public class BsplineCurve { /// <summary> /// 取样数量 /// </summary> public double LinePoint = 10.0; #region 参数 private int n;//曲线控制顶点数 private int k;//曲线次数 public BsplineType curve_type;//B样条曲线类型 List<double> Bvalue = new List<double>(); /*******节点矢量******/ public List<double> knots_value = new List<double>();//节点矢量相异节点 public List<int> knots_muti = new List<int>();//节点矢量重复度 /******控制顶点及权因子*****/ public List<Pos> ControlPoint = new List<Pos>();//控制顶点序列 public List<double> wlist = new List<double>();//控制顶点的权因子序列 /******曲线上点序列及基函数点序列*****/ public List<Pos> CurvePoint = new List<Pos>();//样条曲线上的点的序列 public List<List<Pos>> BasicFuncPoint = new List<List<Pos>>();//B样条基函数点列 #endregion public BsplineCurve()//默认构造函数 { n = 0; k = 0; curve_type = BsplineType.QuasiUniform; } public BsplineCurve(BsplineType type, int times, List<Pos> plist)//参数构造函数 { curve_type = type; this.k = times; this.n = plist.Count - 1; ControlPoint.AddRange(plist); for (int i = 0; i <= n; i++) { wlist.Add(1); } } #region 四种类型B样条 节点矢量的创建 private void GenerateKnots()//节点矢量创建及方法选择 { /*对于4种B样条曲线类型,有4种节点矢量生成方式*/ switch (curve_type) { case BsplineType.Uniform: CreateKnots_Uniform(); break; case BsplineType.QuasiUniform: CreateKnots_QuasiUniform(); break; case BsplineType.PiecewiseBezier: CreateKnots_PiecewiseBezier(); break; case BsplineType.NonUniform: CreateKnots_NonUniform(); break; default: // MessageBox.Show("节点矢量生成出错!!"); break; } } private void CreateKnots_Uniform()//均匀B样条节点矢量创建 { knots_muti.Clear(); knots_value.Clear(); double temp, ui = 0; int i; //生成均匀B样条的节点矢量 temp = 1.0 / (n - k + 1); ui = -k * temp; for (i = 0; i <= n + k + 1; i++) { knots_value.Add(ui); knots_muti.Add(1); ui += temp; } } private void CreateKnots_QuasiUniform()//准均匀B样条节点矢量创建 { knots_muti.Clear(); knots_value.Clear(); double temp, ui = 0; int i; temp = 1.0 / (n - k + 1); ui = 0; for (i = 0; i <= n - k + 1; i++) { knots_value.Add(ui); knots_muti.Add(1); ui += temp; } //首末节点重复度为K+1重 knots_muti[0] = k + 1; knots_muti[n - k + 1] = k + 1; } private void CreateKnots_PiecewiseBezier()//分段Bezier曲线点矢量创建 { knots_muti.Clear(); knots_value.Clear(); int i, j; double temp = 0; double ui; if (n % k == 0) { i = n / k; temp = 1.0 / i; ui = 0; for (j = 0; j <= i; j++) { knots_value.Add(ui); knots_muti.Add(k); ui += temp; } knots_muti[0]++; knots_muti[i]++; } else { // MessageBox.Show("n/k != 整数"); } } private void CreateKnots_NonUniform()//非均匀B样条节点矢量创建 { knots_muti.Clear(); knots_value.Clear(); /*******采用Hartley-Judd方法**********/ List<double> lengthi = new List<double>(); List<double> molecule = new List<double>(); molecule.Clear(); lengthi.Clear(); double deltaX, deltaY, length, temp, denominator = 0; int i, j; for (i = 1; i <= n; i++) { deltaX = ControlPoint[i].X - ControlPoint[i - 1].X; deltaY = ControlPoint[i].Y - ControlPoint[i - 1].Y; length = Math.Sqrt(deltaX * deltaX + deltaY * deltaY); lengthi.Add(length); } knots_value.Add(0); knots_muti.Add(k + 1); //计算分母denominator,每一项的分子molecule[i] for (i = 1; i <= n - k + 1; i++) { temp = 0; for (j = i; j <= i + k - 1; j++) { temp += lengthi[j - 1]; denominator += lengthi[j - 1]; } molecule.Add(temp); } for (i = 1; i <= n - k; i++) { knots_value.Add(knots_value[i - 1] + molecule[i - 1] / denominator); knots_muti.Add(1); } knots_value.Add(1); knots_muti.Add(k + 1); } #endregion #region 计算曲线上的离散点 public void CreateCurve()//计算B样条曲线离散点 { int i, j; double u = 0; double du = 0; double h = 0.02; Bvalue.Clear(); for (j = 0; j <= k; j++) { Bvalue.Add(1.0); } GenerateKnots();//创建节点矢量 CurvePoint.Clear(); BasicFuncPoint.Clear(); for (j = 0; j <= n; j++) { BasicFuncPoint.Add(new List<Pos>()); } u = 0; for (i = 0; i <= n; i++) { if (knots_value[i] > 0) break; } //Find the first more than 0 for (; i < knots_value.Count() && knots_value[i] <= 1.00000001; i++) { du = knots_value[i]; h = (knots_value[i] - knots_value[i - 1]) / LinePoint; do { AddCurvePoint(u); u += h; } while (u < du); u = du; } //此时u==1,但未计算u=1处的点坐标,故手动计算节点为1的 AddCurvePoint(1); if (curve_type == BsplineType.Uniform) CalculateUniformBfunc1st(); } private void AddCurvePoint(double u) { int i; double tempx, tempy; double sum; int j; bool Isnode = false; for (i = k + 1; i <= n; i++)//确定u所在区间号,u-[ui,ui+1] { if (u < KnotValue(i)) break; } i--;//确定u所在子区间 /*Bvalue为基函数Ni,--Ni+p在u点的值*/ if (u == KnotValue(i) && u > 0) Isnode = true; CalculateBvalue(u, i); for (j = 0; j <= k; j++) { BasicFuncPoint[i - k + j].Add(new Pos((float)u, (float)Bvalue[j])); } if (Isnode == true) BasicFuncPoint[i - k - 1].Add(new Pos((float)u, (float)Bvalue[k])); tempx = 0; tempy = 0; sum = 0; for (j = 0; j <= k; j++) { sum += Bvalue[j] * wlist[i - k + j]; } for (j = 0; j <= k; j++) { tempx += Bvalue[j] * wlist[i - k + j] / sum * ControlPoint[i - k + j].X; tempy += Bvalue[j] * wlist[i - k + j] / sum * ControlPoint[i - k + j].Y; } CurvePoint.Add(new Pos((float)tempx, (float)tempy)); } private double KnotValue(int j)//计算节点j的值,考虑节点重复度 { double u = 0; int l = knots_value.Count; int index = 0; for (int i = 0; i < l; i++) { index += knots_muti[i]; if (index - 1 >= j) { u = knots_value[i]; break; } } return u; } private void CalculateBvalue(double u, int i)//计算每一点的基函数值 { int j, r; double temp = 0, saved = 0; List<double> left = new List<double>(); List<double> right = new List<double>(); for (j = 0; j <= k; j++) { left.Add(1); right.Add(1); } Bvalue[0] = 1; for (j = 1; j <= k; j++) { left[j] = u - KnotValue(i + 1 - j); right[j] = KnotValue(i + j) - u; saved = 0; for (r = 0; r < j; r++) { temp = Bvalue[r] / (right[r + 1] + left[j - r]); Bvalue[r] = saved + right[r + 1] * temp; saved = left[j - r] * temp; } Bvalue[j] = saved; } } private void CalculateUniformBfunc1st()//计算均匀B样条的基函数 { double dh, u; List<double> knoth = new List<double>(); List<double> Bfunc = new List<double>(); int i, j, r; double temp = 0, saved = 0; List<double> left = new List<double>(); List<double> right = new List<double>(); for (j = 0; j <= k; j++) { left.Add(1); right.Add(1); } dh = knots_value[1] - knots_value[0]; temp = -k * dh; for (i = 0; i < 3 * k + 2; i++) { knoth.Add(temp + i * dh); } for (i = 0; i <= k; i++) Bfunc.Add(1); dh /= 5; u = 0; BasicFuncPoint[0].Clear(); for (i = k; i < 2 * k + 1; i++) { while (u <= knoth[i + 1]) { Bfunc[0] = 1; for (j = 1; j <= k; j++) { left[j] = u - knoth[i + 1 - j]; right[j] = knoth[i + j] - u; saved = 0; for (r = 0; r < j; r++) { temp = Bfunc[r] / (right[r + 1] + left[j - r]); Bfunc[r] = saved + right[r + 1] * temp; saved = left[j - r] * temp; } Bfunc[j] = saved; } u += dh; BasicFuncPoint[0].Add(new Pos((float)u, (float)Bfunc[2 * k - i])); } } } #endregion }
调用的代码如下:
BsplineCurve bc = new BsplineCurve(BsplineType.NonUniform, item.Degree,item.Points);bc.CreateCurve();var points = bc.CurvePoint;
阅读全文
0 0
- 绘制AutoCad中的曲线(Curve)
- 贝塞尔曲线 (Bézier curve) 理论及绘制方法
- 使用java绘制希尔伯特曲线(hilbert curve)
- 用Java绘制科赫曲线(koch curve)
- Unity中的曲线绘制
- AutoCAD中的Spline曲线算法分析(一)
- AutoCAD中的Spline曲线算法分析(二)
- 用 C# 绘制曲线图(Curve图,增加自动适应和多曲线绘制)
- 用 C# 绘制曲线图(Curve图,增加自动适应和多曲线绘制)
- 用 C# 绘制曲线图(Curve图,增加自动适应和多曲线绘制)
- 贝赛尔曲线 Bezier Curve
- opengl绘制Bezier Curve
- 【转】gamma曲线 (gamma curve)
- Bezier curve(贝塞尔曲线)
- autocad反转曲线方向
- R-D Curve绘制方法
- AutoCAD二次开发技术在工程图纸绘制中的应用
- 绘制曲线
- 总结:网络协议
- 链表
- JavaScript 中的数据&变量&内存
- 火柴棍等式
- hibernate和jdbc区别
- 绘制AutoCad中的曲线(Curve)
- 栈
- codevs 1995 黑魔法师之门
- bzoj 1492: [NOI2007]货币兑换Cash cdq分治
- New
- 【Java笔记】Week03 -- 面向对象的深入接触
- 前端_仿app欢迎界面_度假村
- 正则表达式反斜杠为何四个斜杠?
- 以自定义圆形进度条为例阐述自定义view步骤