绘制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;



原创粉丝点击