加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

C# 简单实现直线方程,抛物线方程

发布时间:2020-12-16 01:13:59 所属栏目:百科 来源:网络整理
导读:本例子是简单的在WinForm程序中实现在坐标系中绘制直线方程,抛物线方程,点。重新学习解析几何方面的知识。仅供学习分享使用,如有不足之处,还请指正。 涉及知识点: 直线方程的表达方式:一般表达式Ax+By+C=0 抛物线表达式:y=Ax 2 +Bx+C 坐标转换:由于W

本例子是简单的在WinForm程序中实现在坐标系中绘制直线方程,抛物线方程,点。重新学习解析几何方面的知识。仅供学习分享使用,如有不足之处,还请指正。

涉及知识点:

  • 直线方程的表达方式:一般表达式Ax+By+C=0
  • 抛物线表达式:y=Ax2+Bx+C
  • 坐标转换:由于WinForm中的坐标原点是左上角,数学二维坐标系的原点是在中间,所以需要转换
  • 单位转换:WinForm的单位是Pixls,但坐标系的单位不是,需要进行缩放。
  • 画图方法:程序中使用GDI+进行画图。

----------------------------------------------------------------------------------------------------------------------

效果图

如下:

---------------------------------------------------------------------------------------------------------

多边形扩展

【如下图所示】

//求多边形对应的边的平行线,然后再求相邻平行线的交点,连起来即是扩展多边形

核心算法

主要代码如下:

【方程类】

  1 using System;
  2  System.Collections.Generic;
  3  System.Linq;
  4  System.Text;
  5 
  6 namespace DemoGeometry
  7 {
  8     /// <summary>
  9     /// 方程基类
 10     </summary>
 11     public abstract class Equation
 12     {
 13         int A { get; set; }
 14         int B {  15         int C {  16 
 17          18          判断是否有效
 19          20         <returns></returns>
 21         bool IsValid();
 22 
 23          24          通过Y值获取x值
 25          26         <param name="y"></param>
 27          28         float GetValueFromY(float y);
 29          30          通过X获取Y值
 31          32         <param name="x"></param>
 33          34         float GetValueFromX( x);
 35     }
 36 
 37      38      直线方程类一般式:Ax+By+C=0(A、B不同时为0)【适用于所有直线】
 39      40      LinearEquation:Equation
 41  42          43          通过X值得到Y值
 44          45          46          47         override  x)
 48         {
 49             if (B == 0)
 50             {
 51                 return .MaxValue;
 52             }
 53             return -A * x * 1.0f / B - C * 1.0f / B;
 54         }
 55 
 56          y)
 57  58             if (A ==  59  60                  61  62             return -B * y * 1.0f / A - C *  A;
 63  64 
 65          66          判断是否有效方程
 67          68          69          IsValid()
 70  71             bool flag = true;
 72             0 && B ==  73  74                 flag = false 75  76             return flag;
 77  78 
 79         string ToString()
 80  81             string.Format("{0}x+{1}y+{2}=0",A,B,C);
 82  83  84 
 85      86      抛物线方程表达式 y=ax2+bx+c
 87      88      ParabolicEquation:Equation
 89  90 
 91          92          判断是否有效的方程
 93          94          95          96  97             //A 不得等于0
 98             return A !=  99 100 
101         102         103         104         105         106         107 108             double y = A * Math.Pow(x,2) + B * x + C;
109             .Parse(y.ToString());
110 111 
112         113 114             return 0.0f115 116 117 }
View Code

【控件类】

 System.ComponentModel;
 System.Drawing;
  5  System.Data;
  8  System.Windows.Forms;
  9 
 10  11  12      13      坐标系控件
 14      15     partial  AxisControl : UserControl
 16  17         #region 属性
 18 
 19         private Axis _AxisX = new Axis() {  XName = x };
 21          X轴
 22          23         public Axis AxisX { get { this._AxisX; }  }
 24 
 25         private Axis _AxisY = new Axis() { XName = y Y轴
 28          29         public Axis AxisY { ._AxisY; } }
 30 
 边界留空白
private int bound = 10 35 
 36         int Bound
 37  38              bound; }
 39             set { bound = value; }
 40  41 
 表示单位,10个像素表示1
 45         int unit = 30 46 
 Unit
 unit; }
 50             set { unit = 51  52 
 53          54          文本字体
 55         private Font t_Font = new Font(Arial 57 
 58         private PointF center;
 59 
 60         int index =  61 
 62         int lineWidth = 2 63 
 64         #endregion
 65 
 66         public AxisControl()
 67  68             InitializeComponent();
 69  70 
 71         void InitInfo() {
绘制坐标轴
 73             var width = this.Width * 1.0f 74             var height = this.Height *  75             center = new PointF(width / 2,height / );
 76  77 
 78          79          重绘界面函数
 80          81         <param name="e"></param>
 82         protected  OnPaint(PaintEventArgs e)
 84             base.OnPaint(e);
 85             InitInfo();
 86             Graphics g = e.Graphics;
 87              88              89             Pen pen = new Pen(Color.Black);
 90             var left = new PointF(bound,center.Y);//
 91             var right = new PointF(width - bound,center.Y);
 92             var bottom = new PointF(center.X,height - bound);
 93             var top =  PointF(center.X,bound);
 94             g.DrawString(0",t_Font,Brushes.Black,new PointF(center.X + bound/));
 95             画X轴,X轴的箭头
            g.DrawLine(pen,left,right);
 97             g.DrawLine(pen,1)">new PointF(right.X - bound/),1)"> 98             g.DrawLine(pen,right.Y + bound/ 99             var xName = string.IsNullOrEmpty(this._AxisX.XName) ? " : ._AxisX.XName;
100             g.DrawString(xName,1)">new PointF(right.X - bound,right.Y + 2 * bound));
101             绘制X轴的刻度
102             var xMax = Math.Floor((right.X - left.X) / (2*unit));103             this._AxisX.Max = .Parse( xMax.ToString());
104             for (var i = 0; i < xMax; i++) {
105                 正刻度
106                 g.DrawLine(pen,1)">new PointF(center.X + (i + 1) * unit,center.Y),center.Y - 107                 g.DrawString((i + 1).ToString(),center.Y+108                 负刻度
109                 g.DrawLine(pen,1)">new PointF(center.X - (i + 110                 g.DrawString(-"+(i + 111 112             画Y轴,Y轴的箭头
114             g.DrawLine(pen,1)">new PointF(top.X - bound/115             g.DrawLine(pen,1)">new PointF(top.X + bound/116             var yName = string.IsNullOrEmpty(_AxisY.XName) ?  : _AxisY.XName;
117             g.DrawString(AxisY.XName,1)">new PointF(top.X + 2 * bound,top.Y -118             绘制Y轴的刻度
119             var yMax = Math.Floor((bottom.Y - top.Y) / (2 * unit));120             this._AxisY.Max = .Parse(yMax.ToString());
121             0; i < yMax; i++122 123                 124                 g.DrawLine(pen,center.Y- (i + 1) * unit),1)">new PointF(center.X+ 1) * unit ));
125                 g.DrawString((i +  unit));
126                 127                 g.DrawLine(pen,center.Y + (i + 128                 g.DrawString(" + (i + 129 130 131 
132         133          判断直线方程是否在坐标轴范围内
134         135         <param name="linear"></param>
136         137          CheckLineIsValid(LinearEquation linear)
138 139             bool flagX = 140             bool flagY = 141             var y = linear.GetValueFromX(0f);
142 
143             判断y坐标的值有没有越界
144             if (y == .MaxValue)
145 146                 表示是垂直于x轴的直线
147                 var x0 = -linear.C* linear.A;
148                 if (x0 >= 0 - this._AxisX.Max && x0 < ._AxisX.Max)
149                 {
150                     flagY = 151                 }
152                 else
153 154                     flagY = 155 156                 
157 158             159 160                 if (y <= this._AxisY.Max && y >= ._AxisY.Max)
161 162                     flagY = 163 164                 165 166                     flagY = 167 168 169             判断x坐标的值
170             var x = linear.GetValueFromY(0f);
171             if (x == 172 173                 var y0 = -linear.C* linear.B;
174 
175                 if (y0 <= this._AxisY.Max && y0 >= 176 177                     flagX = 178 179                 180 181                     flagX = 182 183 184             185 186                 if (x <= this._AxisX.Max && x >= 187 188                     flagX = 189 190                 191 192                     flagX = 193 194 195 
196             return flagX && flagY;只有x,y都满足条件,才是有效的
197 198 
199         200          判断点是否在坐标轴范围内
201         202         203          CheckPointIsValid(PointF point)
204 205             206             207             if (point.X <= this._AxisX.Max && point.X >= 208 209                 flagX = 210 211             if (point.Y <= this._AxisY.Max && point.Y >= 212 213                 flagY = 214 215             return flagX && flagY;
216 217 
218         219          检查抛物线方程是否有效
220         221         <param name="parabolic"></param>
222         223          CheckParabolicIsValid(ParabolicEquation parabolic) {
224             List<PointF> lstPoint = GetPointFromEquation(parabolic);
225             if (lstPoint.Count > 226 227                 228 229             else {
230                 231 232 233 
234         235          将刻度转换成像素
236         237         public List<PointF> ConvertScaleToPixls(List<PointF> lstScale)
238 239             List<PointF> lstPixls = new List<PointF>();
240             if (lstScale != null && lstScale.Count > 241                 var p = lstScale.Select(s => new PointF(center.X + s.X * unit,center.Y - s.Y *242                 lstPixls = p.ToList();
243 244              lstPixls;
245 246 
247         248          转换刻度到像素
249         250         <param name="s"></param>
251         252          PointF ConvertScaleToPixls(PointF s)
253 254              unit);
255 256 
257         258          生成直线
259         260         261          GenerateLinear(LinearEquation linear) {
262 
263             Color lineColor = Color.Blue;线条的颜色
264             Graphics g = .CreateGraphics();
265             分别获取两个端点的值,连成线即可
266             var x1 = ._AxisX.Max;
267             var y2 = ._AxisY.Max;
268             var x3 = 269             var y4 = 270             var y1 = linear.GetValueFromX(x1);
271             var x2 = linear.GetValueFromY(y2);
272             var y3 = linear.GetValueFromX(x3);
273             var x4 = linear.GetValueFromY(y4);
274             var point1 =  PointF(x1,y1);
275             var point2 =  PointF(x2,y2);
276             var point3 =  PointF(x3,y3);
277             var point4 =  PointF(x4,y4);
278             List<PointF> lstTmp = () { point1,point2,point3,point4 };
279             List<PointF> lstPoint=280             foreach (PointF point in lstTmp)
281 282                 判断点是否合理
283                 if (CheckPointIsValid(point))
284 285                     lstPoint.Add(point);
286 287 288             if (lstPoint.Count() < 289                 如果点的个数小于2,不能绘制直线
290                 291 292             将刻度点,转换成像素点
293             List<PointF> lstPixlsPoint = ConvertScaleToPixls(lstPoint);
294             g.DrawLine(new Pen(lineColor,lineWidth),lstPixlsPoint[0],1)">1]);
295             g.DrawString(L{0}new PointF(lstPixlsPoint[1].X + 1].Y - 296             this.lblInfo.Text += L{0}:{1}x+{2}y+{3}=0 ; 297             index++298             299 300 
301         302          生成点
303         304         <param name="point"></param>
305         306          GeneratePoint(PointF point)
307 308             Graphics g = 309             PointF p = ConvertScaleToPixls(point);
310             g.FillEllipse(Brushes.Red,p.X,p.Y,1)">4,1)">4311             g.DrawString(P{0}new PointF(p.X + 312             P{0}:({1},{2}) ; 313             index++314             315 316 
317          GenerateParabolic(ParabolicEquation parabolic)
318 319             List<PointF> lstPoint =320             321             List<PointF> lstPixlsPoint =322             Color lineColor = Color.SeaGreen;323             Graphics g = 324             g.DrawCurve( Pen(lineColor,lstPixlsPoint.ToArray());
325             g.DrawString(326             P{0}:y={1}x2+{2}x+{3} ; 327             index++328             329 330 
331         332          从抛物线方程中取点值
333         334         335         336         public List<PointF> GetPointFromEquation(ParabolicEquation parabolic) {
337             List<PointF> lstPoint = 338             从坐标轴最小值开始,隔0.5 取一个
339             int j=340             float i = this._AxisX.Max; i <= this._AxisX.Max; i = i + 0.5f341 342                 PointF p =  PointF(i,parabolic.GetValueFromX(i));
343                 再判断点是否在坐标轴内
344                 if (CheckPointIsValid(p) && (j==0 || lstPoint[j-1].X==i-))
345 346                     lstPoint.Add(p);抛物线内的点应该是连续的
347                     j++348 349 350              lstPoint;
351 352 
353         354          清除已经画上去的线条
355         356         357          Clear() {
358             Graphics g = 359             g.Clear(Color.White);
360             this.lblInfo.Text = ""361             this.Refresh();重新刷新界面,清除已经画上去的线条
362             index = 363             364 365 366 
367     368      坐标轴描述
369     370      Axis{
371 
372         373          刻度表示最大值
374         375         int Max { 376 
377         378          名称
379         380         string XName{get;;}
381 
382         // 383         // 间隔
384         385         public int Interval{get;set;}
386 387 }
View Code

【主界面类】

 12      MainForm : Form
 13  MainForm()
 15  17 void btnLine_Click(object sender,EventArgs e)
 20  21             if (.linearControl1.IsValid())
 22  23                 var a = .linearControl1.A;
 24                 var b = .linearControl1.B;
 25                 var c = .linearControl1.C;
 26                 判断方程的参数,是否有效
 27                 LinearEquation linear = new LinearEquation() { A = a,B = b,C = c };
 28                 if (!linear.IsValid())
 29  30                     MessageBox.Show(输入的方程参数无效 31                      32  33                 .axisControl1.CheckLineIsValid(linear))
 34  35                     MessageBox.Show(输入的方程不在坐标轴内 36                      38                 .axisControl1.GenerateLinear(linear);
 39                 flag)
 41                     MessageBox.Show(生成直线失败 42                      43  44  45 void btnClear_Click(.axisControl1.Clear();
 51 
 52         void btnPoint_Click( 53  54             .pointControl1.IsValid())
 55  56                 float x = .pointControl1.X;
 57                 float y = .pointControl1.Y;
 58                 PointF point =  PointF(x,y);
 59                 .axisControl1.CheckPointIsValid(point)) {
 60                     MessageBox.Show(输入的点不在坐标轴内 61                      62  63                 .axisControl1.GeneratePoint(point);
 64                  65  66                     MessageBox.Show(生成点失败 67                      70             
 71  72 
 73         void btnParabolic_Click( 74  75             .parabolicControl1.IsValid())
 77                 .parabolicControl1.A;
 78                 .parabolicControl1.B;
 79                 .parabolicControl1.C;
 80                  81                 ParabolicEquation parabolic = new ParabolicEquation() { A = a,1)"> 82                 parabolic.IsValid())
 84                     MessageBox.Show( 85                      86  87                 .axisControl1.CheckParabolicIsValid(parabolic))
 88  89                     MessageBox.Show( 90                      91  92                 .axisControl1.GenerateParabolic(parabolic);
 93                  94  95                     MessageBox.Show(生成抛物线失败 96                      97  98 100 101 }
View Code

?【扩展多边形代码】

  1    2          生成多边形
  3           4         <param name="lstPoints"></param>
  5           6         bool GeneratePolygon(List<PointF> lstPoints,1)">bool isOriginal=  7 
  8             Color lineColor = Color.Red;  9              (isOriginal)
 11                 lineColor = Color.Red;
 13              14                 lineColor = Color.Blue;
 16             
 17             Graphics g =  18             画点
 19             foreach (var p  lstPoints) {
 20                 .GeneratePoint(p);
 21  22              23             List<PointF> lstPixlsPoint = ConvertScaleToPixls(lstPoints);
 24             绘制多边形
 25             g.DrawPolygon( 26              27  28 
 扩展多边形,即在现有多边形的基础上进行扩展
bool GenerateExpandPolygon(List<PointF> lstPoints,PointF center,1)"> distance) {
 35             1.求多边形对应的外扩平行斜线
 36             List<LinearEquation> lstLines = new List<LinearEquation> 37             int len = lstPoints.Count();
int i = 0; i < len; i++var p0 = lstPoints[i];第i个元素
 40                 var p1 = lstPoints[(i + 1) % len];第i+1个元素
 41                 LinearEquation linearEquation =  LinearEquation();
 42                 if (p0.X == p1.X)
 44                     垂直于x轴,没有斜率
 45                     linearEquation.A =  46                     linearEquation.B =  47                     if (p0.X > center.X)
                    {
 49                         linearEquation.C = -(p0.X + distance);
                    }
 51                      52                         linearEquation.C = -(p0.X - 54                     
else if (p0.Y == p1.Y)
 58                     垂直于y轴,斜率为0
 59                     linearEquation.A =  60                     linearEquation.B = if (p0.Y > center.Y)
 63                         linearEquation.C = -(p0.Y + 64  65                      66                         linearEquation.C = -(p0.Y - 69                  70                     先求两点对应的点斜式方程y=kx+b
 71                     float k = (p0.Y - p1.Y) / (p0.X - p1.X);
 72                     float b = p0.Y - k * p0.X;
 73                     求出平行线对应的b即可。
 74                     float b_center = center.Y - k * center.X;
 75                     linearEquation.A = k;
 76                     linearEquation.B = -1;如果此处为-1,则C=b
 78                     if (b > b_center)
 79  80                         如果在原点上方
 81 
 82                         linearEquation.C =(b+(float) Math.Abs((distance/(Math.Sin(-Math.PI/2-Math.Atan(k))))));
 84                      85                         如果在原点下方
 86                         linearEquation.C = (b - (float)Math.Abs((distance / (Math.Sin(-Math.PI / 2 - Math.Atan(k))))));
 87  89                 this.GenerateLinear(linearEquation);
 90                 lstLines.Add(linearEquation);
 92             List<PointF> lstNewPoints = 2.求相邻外扩平行斜线的交点
 94              95                 var line0 = lstLines[i];
 96                 var line1 = lstLines[(i + 1) % len];
 97                 float x =  98                 float y =  99                 if (line0.A == 101                     y = -line0.C / line0.B;
102                     x= line1.GetValueFromY(y);
103 104                 if (line0.B == 105 106                     x = -line0.C / line0.A;
107                     y = line1.GetValueFromX(x);
108 109                 if (line1.A == 111                     y = -line1.C / line1.B;
112                     x = line0.GetValueFromY(y);
114                 if (line1.B == 116                     x = -line1.C / line1.A;
117                     y = line0.GetValueFromX(x);
118 119                 120                     两个都有斜率的直线的交点
121                     float k0 = -line0.A /122                     float k1 = -line1.A /123                     float b0 = -line0.C /124                     float b1 = -line1.C /125                     x = (b1 - b0) / (k0 - k1);
126                     y =127 128                 lstNewPoints.Add(130             this.GeneratePolygon(lstNewPoints,1)">131             132             133         }
View Code

?备注:源码 点击下方链接

源码下载

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读