C# 简单实现直线方程,抛物线方程
发布时间:2020-12-16 01:13:59 所属栏目:百科 来源:网络整理
导读:本例子是简单的在WinForm程序中实现在坐标系中绘制直线方程,抛物线方程,点。重新学习解析几何方面的知识。仅供学习分享使用,如有不足之处,还请指正。 涉及知识点: 直线方程的表达方式:一般表达式Ax+By+C=0 抛物线表达式:y=Ax 2 +Bx+C 坐标转换:由于W
本例子是简单的在WinForm程序中实现在坐标系中绘制直线方程,抛物线方程,点。重新学习解析几何方面的知识。仅供学习分享使用,如有不足之处,还请指正。 涉及知识点:
---------------------------------------------------------------------------------------------------------------------- 效果图 如下: --------------------------------------------------------------------------------------------------------- 多边形扩展 【如下图所示】 //求多边形对应的边的平行线,然后再求相邻平行线的交点,连起来即是扩展多边形 核心算法 主要代码如下: 【方程类】 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 } 【控件类】 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 } 【主界面类】 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 } ?【扩展多边形代码】 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 } ?备注:源码 点击下方链接 源码下载 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |