在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;
}
}