自定义类实现绘制曲线

在C#中,自定义类实现绘制曲线函数的功能,模拟DrawCurve()函数的方法,效果见下图:
在这里插入图片描述
在这里插入图片描述

代码如下:

        public class fpoint
        {
            public float x;
            public float y;
        }
        public class qxData
        {
            public fpoint K = new fpoint();//控制点
            public float S;//距离
            public float F1;//方位角
            //public float q1;
            public float q2;//切线
            public float q3;
            public int kind;//分类  }
        public class qxPart
        {
            public fpoint A ;
            //public fpoint B ;
            public float S;//直线距离;
            public float F1;//
            public float Vx1;
            public float Vy1;
            public float q2;//B点切线
            //
            public float Vx2;
            public float Vy2;
            public float t;
            public float ax;
            public float ay;
            public float sx;
            public float sy;

        }
        public class qx
        {
            public List<qxData> qD = new List<qxData>();
            public List<qxPart> qP = new List<qxPart>();
            public float Deg = 10;
            private float rN,rM;
            //生成曲线
            public void makeCurve()
            {
                jsqD(ref qD);
                jsqP(qD);
            }
            //计算曲线数据
            private void jsqD(ref List<qxData> qd)
            {
                if (qd.Count < 3) { return; }
                rM = (float)Math.Sin(Deg / 1.414 / 180 * Math.PI);
                rN = (float)Math.Cos(Deg *2/ 180 * Math.PI+Math.PI);
                float s3 = 0;
                fpoint tfp;
                int j = 0;
                qxData qd1, qd2;
                for (int i = 0; i < qd.Count; i++)
                {
                    if (i == qd.Count - 1)
                    {
                        qd[i].S = 0;
                        tfp = new fpoint();
                        tfp.x = qd[i - 1].K.x + qd[i - 1].S / 2 * (float)Math.Cos(qd[i - 2].F1);
                        tfp.y = qd[i - 1].K.y + qd[i - 1].S / 2 * (float)Math.Sin(qd[i - 2].F1);
                        qd[i].F1 = qd[i - 1].F1;
                        qd[i].S = qd[i - 1].S;
                        jsAz0(tfp, qd[i].K, ref s3, ref qd[i].q2);//
                        qd[i].kind = -3;
                        qd[i].q3 = 0;
                    }
                    else
                    {
                        jsAz0(qd[i].K, qd[i + 1].K, ref qd[i].S, ref qd[i].F1);
                        if (i == 0)
                        {
                            tfp = new fpoint();
                            jsAz0(qd[i + 1].K, qd[i + 2].K, ref qd[i + 1].S, ref qd[i + 1].F1);
                            tfp.x = qd[i + 1].K.x + qd[i + 1].S * 2 * (float)Math.Cos(qd[i].F1);
                            tfp.y = qd[i + 1].K.y + qd[i + 1].S * 2 * (float)Math.Sin(qd[i].F1);
                            jsAz0(qd[i + 2].K, tfp, ref s3, ref qd[i].q2);//
                        }
                        else
                        {
                            qd[i].q2 = jsAz1(qd[i - 1].F1, qd[i].F1);
                        }
                    }
                }
                
                for (int i = 0; i < qd.Count - 1; i++)
                {
                    qd1 = qd[i]; qd2 = qd[i + 1];
                    if (jsAz2(ref qd1, ref qd2, ref j) && j != 0)
                    {
                        for (j = j - 1; j >= 0; j--)
                        {
                            qd[j].q2 = (float)(qd[j].F1 - Math.Sin(qd[j + 1].q2 - qd[j].F1) / Math.Abs(Math.Sin(qd[j + 1].q2 - qd[j].F1)) * Deg / 180 * Math.PI);
                        }
                    }

                }
                qd[0].kind = jskind(qd[0].q2, qd[0].F1, qd[1].q2);
                qd[0].q3 = jsAz3(qd[0].kind, qd[0].F1, qd[0].q2);
                for (int i = 1; i < qd.Count - 1; i++)
                {
                    qd[i].kind = jskind(qd[i].q2, qd[i].F1, qd[i + 1].q2);
                    qd[i].q3 = jsAz3(qd[i].kind, qd[i].F1, qd[i].q2);
                }
            }
            //计算曲线单位参数
            private void jsqP(List<qxData> qd)
            {
                if (qd.Count < 3) { return; }
                foreach (qxData dd in qd)
                {
                    switch (dd.kind)
                    {
                        case -3:
                            break;
                        case -2:
                        case 0:
                            jsqP_2(ref qP, dd, qd[qd.IndexOf(dd) + 1].q2, qd[qd.IndexOf(dd) + 1].S);
                            break;
                        case 2:
                            jsqP2(ref qP, dd, qd[qd.IndexOf(dd) + 1].q2, qd[qd.IndexOf(dd) + 1].S);
                            break;
                        default:
                            break;
                    }

                }
            }
            private void jsqP_2(ref List<qxPart> qP, qxData dd, float pq2, float l2)
            {
                int j = qP.Count;
                qxPart tqp = new qxPart();
                tqp.A = dd.K;
                tqp.S = dd.S;
                tqp.F1 = dd.F1;
                if (j == 0)
                {
                    tqp.Vx1 = (float)Math.Cos(dd.q2) * 1;
                    tqp.Vy1 = (float)Math.Sin(dd.q2) * 1;
                }
                else
                {
                    tqp.Vx1 = qP[j - 1].Vx2;
                    tqp.Vy1 = qP[j - 1].Vy2;
                }
                tqp.q2 = pq2;
                tqp.sx = tqp.S * (float)Math.Cos(tqp.F1);
                tqp.sy = tqp.S * (float)Math.Sin(tqp.F1);
                jsqP1(ref tqp, l2, dd.kind);
                qP.Add(tqp);
            }
            private void jsqP2(ref List<qxPart> qP, qxData dd, float pq2, float l2)
            {
                qxData tdd = new qxData();
                tdd.K = dd.K;
                tdd.F1 = dd.F1;
                tdd.kind = -2;
                tdd.q2 = dd.q2;
                tdd.S = dd.S / 2;
                jsqP_2(ref qP, tdd, dd.q3, dd.S / 2);

                //
                tdd = new qxData();
                tdd.K.x = (float)Math.Cos(dd.F1) * dd.S / 2 + dd.K.x;
                tdd.K.y = (float)Math.Sin(dd.F1) * dd.S / 2 + dd.K.y;
                tdd.S = dd.S / 2;
                tdd.F1 = dd.F1;
                tdd.q2 = dd.q3;
                tdd.kind = -2;
                jsqP_2(ref qP, tdd, pq2, l2);
            }
            private Boolean jsqP1(ref qxPart tqp, float l2, int kind)
            {
                if (Math.Abs(Math.Cos(tqp.q2) * l2) <= rM)
                {
                    tqp.Vx2 = 0;
                    tqp.ax = (tqp.Vx2 * tqp.Vx2 - tqp.Vx1 * tqp.Vx1) / 2 / tqp.sx;
                    if (tqp.ax == 0) { return false; }
                    tqp.t = (tqp.Vx2 - tqp.Vx1) / tqp.ax;
                    tqp.ay = (tqp.sy - tqp.Vy1 * tqp.t) * 2 / tqp.t / tqp.t;
                    tqp.Vy2 = tqp.ay * tqp.t + tqp.Vy1;
                }
                else if (kind == 0)
                {
                    tqp.t = tqp.S / (float)Math.Sqrt(tqp.Vx1 * tqp.Vx1 + tqp.Vy1 * tqp.Vy1);
                    tqp.ax = 0;
                    tqp.ay = 0;
                    tqp.Vx2 = tqp.Vx1;
                    tqp.Vy2 = tqp.Vy1;

                }
                else
                {
                    float k = (float)Math.Tan(tqp.q2);
                    tqp.t = 2 * (tqp.sy - k * tqp.sx) / (tqp.Vy1 - k * tqp.Vx1);
                    tqp.ax = (tqp.sx - tqp.Vx1 * tqp.t) * 2 / tqp.t / tqp.t;
                    tqp.ay = (tqp.sy - tqp.Vy1 * tqp.t) * 2 / tqp.t / tqp.t;
                    tqp.Vx2 = tqp.ax * tqp.t + tqp.Vx1;
                    tqp.Vy2 = tqp.ay * tqp.t + tqp.Vy1;
                }

                return true;
            }
            //计算距离 方位角
            private Boolean jsAz0(fpoint p1, fpoint p2, ref float s, ref float a)
            {
                s = (float)Math.Sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y));
                if (s == 0) { return false; }
                if (p2.y - p1.y < 0)
                {
                    a = (float)(2 * Math.PI - Math.Acos((p2.x - p1.x) / s));
                }
                else
                {
                    a = (float)Math.Acos((p2.x - p1.x) / s);
                }
                return true;
            }
            //计算角平分线方位角
            private float jsAz1(float f1, float f2)
            {
                float a;
                if (Math.Abs((f1 + f2) / 2 - f1) < Math.PI / 2 || Math.Abs((f1 + f2) / 2 - f2) < Math.PI / 2)
                {
                    a = (f1 + f2) / 2;
                }
                else
                {
                    a = (f1 + f2) / 2 + (float)Math.PI;
                }
                return a % (2 * (float)Math.PI);
            }
            //计算切线2 q2=n[i+1].q1
            private Boolean jsAz2(ref qxData qd1, ref qxData qd2, ref int j)
            {
                float b = (float)Math.Abs(Math.Sin(qd1.q2 - qd1.F1));
                float c = (float)Math.Abs(Math.Sin(qd2.q2 - qd1.F1));
               
                if (b <= rM && c > rM)
                {
                    qd1.q2 = (float)(qd1.F1 - Math.Sin(qd2.q2 - qd1.F1) / Math.Abs(Math.Sin(qd2.q2 - qd1.F1)) * Deg / 180 * Math.PI);
                }
                else if (b <= rM && c <= rM)
                {
                    j++;
                    return false;
                }
                else if (b > rM && c <= rM)
                {
                    qd2.q2 = (float)(qd1.F1 - Math.Sin(qd1.q2 - qd1.F1) / Math.Abs(Math.Sin(qd1.q2 - qd1.F1)) * Deg / 180 * Math.PI);
                }
                float e = (float)Math.Cos(qd2.q2 - qd1.q2);
                if (e < rN)
                {
                   qd2.q2 = (float)(qd1.q2+ Math.Sin(qd1.q2 - qd1.F1) / Math.Abs(Math.Sin(qd1.q2 - qd1.F1)) *2* Deg / 180 * Math.PI);
                }
                return true;
            }
            private float jsAz3(int i3, float f3, float h3)
            {
                float a;
                if (i3 == 2)
                {
                    a = (float)(f3 - Math.Sin(h3 - f3) / Math.Abs(Math.Sin(h3 - f3)) * Deg * Math.PI / 180);
                }
                else
                {
                    a = 0;
                }
                return a;
            }
            //h3=n[i].q2;f3=n[i].f1;h4=n[i+1].q2
            private int jskind(float h3, float f3, float h4)
            {
                int a;
                float b = (float)Math.Sin(h3 - f3);
                float c = (float)Math.Sin(h4 - f3);
                if (b * c > 0)
                {
                    a = 2;//S型
                }
                else if (b * c < 0)
                {
                    a = -2;//C型
                }
                else
                {
                    a = 0; //---
                }
                return a;
            }
        }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值