数字微分分析,本质是根据轨迹上的每个点的速度在各轴的分配比例转换成脉冲的分配比例
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using MathNet.Numerics; using MathNet.Numerics.LinearAlgebra.Generic; using MathNet.Numerics.LinearAlgebra.Double; using System.Drawing.Drawing2D; using System.Drawing.Text; namespace MC.UI { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { try { #region 画图指令 if (string.IsNullOrWhiteSpace(textBox1.Text)) return; var lines = textBox1.Lines; var gList = new List<G>(); foreach (var line in lines) { if (string.IsNullOrWhiteSpace(line)) continue; var arr = line.Split(",".ToCharArray(), StringSplitOptions.RemoveEmptyEntries); if (arr.Length == 2) { gList.Add(new G(arr[0],arr[1])); } } #endregion pictureBox1.Image = DrawImg(gList); tabControl1.SelectedIndex = 0; } catch (Exception ex) { MessageBox.Show(ex.Message); } } private void button2_Click(object sender, EventArgs e) { try { #region 直线插补,倍率10 var gList = new List<G>(); int x = 0, y = 0; int len = 2;//每步长度 int xe=400,ye=150; var xe1 = xe / len; var ye1 = ye / len; var max = Math.Max(xe1, ye1); var n =Math.Ceiling( Math.Log(max, 2)); Console.WriteLine("n:" + n); var periodNum = Math.Pow(2.0, n); double sX=0, sY = 0; for (int step = 0; step < periodNum; step++) { sX += xe1; sY += ye1; bool xOver = false; bool yOver = false; if (sX >= periodNum) { //X累加器溢出 sX -= periodNum; xOver = true; } if (sY >= periodNum) { //Y累加器溢出 sY -= periodNum; yOver = true; } if (xOver) { x = x + len; } if (yOver) { y = y + len; } if (xOver || yOver) { gList.Add(new G(x.ToString(), y.ToString())); } } #endregion pictureBox1.Image = DrawImg(gList); tabControl1.SelectedIndex = 0; } catch (Exception ex) { MessageBox.Show(ex.Message); } } private void button3_Click(object sender, EventArgs e) { try { #region 圆弧插补,第一象限逆时针圆 var gList = new List<G>(); int x0=400,y0=0; int xe=0, ye=400; int len = 1;//每步长度 int xi = x0, yi = y0; //移动到圆弧开始点 gList.Add(new G(x0.ToString(),y0.ToString())); int xe1 = xe / len, ye1 = ye / len; int x01 = x0 / len, y01 = y0 / len; var max =Math.Max( Math.Max(xe1, ye1),Math.Max(x01,y01)); var n = Math.Ceiling(Math.Log(max, 2)); Console.WriteLine("n:" + n); var periodNum = Math.Pow(2.0, n); double sX = 0, sY = 0; while (!( Math.Abs(xe-xi)<=len && Math.Abs(ye-yi)<=len )) { bool xOver = false; bool yOver = false; sX += yi/len; sY += xi/len; if (sX >= periodNum) { //X累加器溢出 sX -= periodNum; xi = xi - len; xOver = true; } if (sY >= periodNum) { //Y累加器溢出 sY -= periodNum; yi = yi + len; yOver = true; } if (xOver || yOver) { gList.Add(new G(xi.ToString(), yi.ToString())); } else { //两个坐标都没变化 } } #endregion pictureBox1.Image = DrawImg(gList); tabControl1.SelectedIndex = 0; } catch (Exception ex) { MessageBox.Show(ex.Message); } } #region private static Matrix<double> _M = null; public static Point TransCoordinate(Point p) { if (_M == null) { #region //x,y,z-- x由左到右,y由上到下,z由屏幕向外坐标, //平移到600,600,然后绕y轴转180度的坐标转换矩阵 double[,] a = { {1 , 0 ,0 ,600}, {0 , -1 ,0 ,600}, {0 , 0 ,-1 , 0 }, {0 , 0 ,0 , 1 } }; _M = DenseMatrix.OfArray(a); #endregion } var B = DenseVector.OfEnumerable(new double[] { p.X, p.Y, 0, 1 }); var C = _M.Multiply(B); return new Point((int)C[0], (int)C[1]); } private static Point P(int x, int y) { return TransCoordinate(new Point(x, y)); } public static Bitmap DrawImg(List<G> gList) { int w = 1200; int h = 1200; var bmp = new Bitmap(w, h); var g = Graphics.FromImage(bmp); g.SmoothingMode = SmoothingMode.AntiAlias; //使绘图质量最高,即消除锯齿 g.InterpolationMode = InterpolationMode.HighQualityBicubic; g.CompositingQuality = CompositingQuality.HighQuality; g.TextRenderingHint = TextRenderingHint.ClearTypeGridFit; g.FillRectangle(new SolidBrush(Color.White), 0, 0, w, h); #region 定义画笔 var pen0 = new Pen(Brushes.AliceBlue, 0.1f); pen0.DashStyle = DashStyle.DashDot; pen0.Color = Color.Black; var pen1 = new Pen(Brushes.AliceBlue, 0.5f); pen1.Color = Color.Black; var pen1_red = new Pen(Brushes.AliceBlue, 0.5f); pen1_red.Color = Color.Red; var pen2 = new Pen(Brushes.AliceBlue, 1); pen2.Color = Color.Black; var pen10 = new Pen(Brushes.AliceBlue, 10f); pen10.Color = Color.Black; var font = new Font("宋体", 12, FontStyle.Regular); var font10 = new Font("宋体", 10, FontStyle.Regular); var font8 = new Font("宋体", 8, FontStyle.Regular); var brush = new SolidBrush(Color.Black); var brush_red = new SolidBrush(Color.Red); #endregion int x0 = 0; int y0 = 0; int x1=0; int y1=0; foreach (var it in gList) { if (it.X == "x") { x1 = x0; } else { x1 = int.Parse(it.X); } if (it.Y == "y") { y1 = y0; } else { y1 = int.Parse(it.Y); } g.DrawLine(pen1, P(x0,y0), P(x1,y1)); x0 = x1; y0 = y1; } return bmp; } public class G { public String X { get; set; } public String Y { get; set; } public G(String x, String y) { X=x; Y=y; } } #endregion } }
代码下载 :
https://files.cnblogs.com/files/wdfrog/MC.UI.rar
//对于其他曲线
下面是椭圆,长短轴是2:1,平方后是4:1,
对椭圆方程两边求x的导数可以得到dy/dx ,得表达式,dy/dx 对应这点(X,Y)得Vy/Vx之比
try { #region 椭圆弧插补,第一象限逆时针圆 var gList = new List<G>(); int x0 = 200, y0 = 0; int xe = 0, ye = 400; int len = 1;//每步长度 int xi = x0, yi = y0; //移动到圆弧开始点 gList.Add(new G(x0.ToString(), y0.ToString())); int xe1 = xe / len, ye1 = ye / len; int x01 = x0 / len, y01 = y0 / len; var max = Math.Max(Math.Max(xe1, ye1), Math.Max(x01, y01)); var n = Math.Ceiling(Math.Log(max, 2)); Console.WriteLine("n:" + n); var periodNum = Math.Pow(2.0, n)*4;// (400 / 200)^2 double sX = 0, sY = 0; while (!(Math.Abs(xe - xi) <= len*2 && Math.Abs(ye - yi) <= len*2)) { bool xOver = false; bool yOver = false; sX += yi / len; sY +=(4 * xi) / len; if (sX >= periodNum) { //X累加器溢出 sX -= periodNum; xi = xi - len; xOver = true; } if (sY >= periodNum) { //Y累加器溢出 sY -= periodNum; yi = yi + len; yOver = true; } if (xOver || yOver) { gList.Add(new G(xi.ToString(), yi.ToString())); } else { //两个坐标都没变化 } //if (xi <= -1 || yi <= -1) break; } #endregion pictureBox1.Image = DrawImg(gList); tabControl1.SelectedIndex = 0; } catch (Exception ex) { MessageBox.Show(ex.Message); }
`注意根据代码每次累加的数(xe,ye--对于直线)是一样的所以xe+xe = xe *2 ,也就是相当于左移一位
根据前面的视频可知,累加ye 或 xe最大取2^n -1 ,而累加寄存器最大取2^n , 而数2^n - 1 在n位寄存器里全是1111....,再累加一次2^n-1必定是溢出的
而对应前i位(左边的)是0的,左移1位相当于乘以2,左移i位等于乘以2^i, 相当于要累加2^i次才能溢出