本例子是简单的在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
【控件类】
@H_866_502@
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 else153 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
备注:源码 点击下方链接
源码下载
总结以上是内存溢出为你收集整理的C# 简单实现直线方程,抛物线方程全部内容,希望文章能够帮你解决C# 简单实现直线方程,抛物线方程所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)