📡 GDI+ 绘制极坐标图 、 雷达图
一个简单的
简单绘制极坐标系
图中曲线是一个天线方向图
文中是直接在窗体上绘制
写在前面的话
做事情
我不会多线程
欢迎把改造后的代码回传给我
目标设定
boss
ok
分析坐标系
说实话
嗯
那么我只需要画出同心圆
画出同心圆的方法

1 // 画圆 2 private void drawCircles(Graphics g, Rectangle rect) 3 { 4 // 圆的直径等于绘图区域最短边 5 float diameter = Math.Min(rect.Width, rect.Height); 6 // 半径 7 float radius = diameter / 2; 8 // 圆心 9 PointF center = new PointF( 10 rect.X + rect.Width / 2, 11 rect.Y + rect.Height / 2 12 ); 13 14 // 画几个圆,先试试5 个 15 int count = 5; 16 float diameterStep = diameter / count; 17 float radiusStep = radius / count; 18 19 // 生成圆的范围 20 RectangleF cirleRect = new RectangleF(); 21 cirleRect.X = center.X - radius; 22 cirleRect.Y = center.Y - radius; 23 cirleRect.Width = cirleRect.Height = diameter; 24 25 // 画同心圆 26 for (int i = 0; i < count; i++) 27 { 28 g.DrawEllipse(Pens.Gray, cirleRect); 29 30 cirleRect.X += radiusStep; 31 cirleRect.Y += radiusStep; 32 cirleRect.Width -= diameterStep; 33 cirleRect.Height -= diameterStep; 34 } 35 }
把这段代码添加到
Good
1 e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias; // 图形抗锯齿 2 e.Graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias; // 文字抗锯齿
接下来就要画辐条了
辐条怎么画呢
从少到多看看辐条的规律
用黑色的笔画出圆

1 // 提出来公用 2 float diameter, radius; 3 PointF center; 4 // 画圆 5 private void drawCircles(Graphics g, Rectangle rect) 6 { 7 // (略) 8 } 9 10 // 辐射线 11 private void drawSpokes(Graphics g) 12 { 13 int count = 8; 14 if (count > 0) 15 { 16 // 计算角度 17 float angle = 0; 18 float angleStep = 360 / count; 19 PointF endPoint = new PointF(); 20 21 for (int i = 0; i < count; i++) 22 { 23 // 得到终点 24 endPoint = getPoint(angle); 25 g.DrawLine(Pens.Gray, center, endPoint); 26 27 angle += angleStep; 28 angle %= 360; 29 } 30 } 31 } 32 33 // 计算终点 34 private PointF getPoint(double angle) 35 { 36 PointF pt = new PointF(); 37 38 pt.X = (float)(radius * Math.Cos(angle * Math.PI / 180) + center.X); 39 pt.Y = (float)(radius * Math.Sin(angle * Math.PI / 180) + center.Y); 40 41 return pt; 42 }
把代码加到
Yeah, baby
永不满足的客户
没过半天
说起加上数字
1 // 画角度值 2 g.DrawString(angle.ToString("0") + "°", this.Font, Brushes.Gray, endPoint);
哦
1 //drawDiagramCircles(e.Graphics, this.ClientRectangle); 2 // 缩小点画圆的区域 3 Rectangle rect = this.ClientRectangle; 4 rect.Inflate(0, -20); 5 drawDiagramCircles(e.Graphics, rect);
ok
1 // 把要画的字符串提出来便于操作 2 string angleString = angle.ToString("0") + "°"; 3 4 // 画角度值,如果文字在90-270 度区间内, 5 PointF textPoint = endPoint; 6 7 if (angle == 270) 8 textPoint.Y -= TextRenderer.MeasureText(angleString, this.Font).Height; // 用 TextRenderer 测量字符串大小 9 else if (angle < 270 && angle > 90) 10 textPoint.X -= TextRenderer.MeasureText(angleString, this.Font).Width; 11 else 12 textPoint.X += 8; // 随便来点漂移 13 14 g.DrawString(angleString, this.Font, Brushes.Gray, textPoint);
看看效果
嗯哼
加入数据点
光画一副坐标系那肯定是什么都干不了的
所以
1 float min = 0; 2 float max = 100;
为了便于后续操作
1 public class PolarValue 2 { 3 float ang = 0; 4 float val = 0; 5 6 // 角度 7 public float Angle 8 { 9 get { return ang; } 10 set { ang = value; } 11 } 12 13 // 数值 14 public float Value 15 { 16 get { return val; } 17 set { val = value; } 18 } 19 20 public PolarValue(float angle, float value) 21 { 22 this.ang = angle; 23 this.val = value; 24 } 25 } 26 27 // 数据列表 28 public List<PolarValue> values = new List<PolarValue>();
现在我有了一组数据点
1 private PointF getMappedPoint(PolarValue pv) 2 { 3 // 计算映射在坐标图中的半径 4 float r = radius * (pv.Value - min) / (max - min); 5 // 计算GDI+坐标 6 PointF pt = new PointF(); 7 pt.X = (float)(r * Math.Cos(pv.Angle * Math.PI / 180) + center.X); 8 pt.Y = (float)(r * Math.Sin(pv.Angle * Math.PI / 180) + center.Y); 9 return pt; 10 }
写到这里
1 // 合并后的映射方法 2 private PointF getMappedPoint(float angle, float value) 3 { 4 // 计算映射在坐标图中的半径 5 float r = radius * (value - min) / (max - min); 6 // 计算GDI+坐标 7 PointF pt = new PointF(); 8 pt.X = (float)(r * Math.Cos(angle * Math.PI / 180) + center.X); 9 pt.Y = (float)(r * Math.Sin(angle * Math.PI / 180) + center.Y); 10 return pt; 11 }
修改调用的地方
1 // 在drawSpokes() 中 2 // (略) 3 // 得到终点 4 endPoint = getMappedPoint(angle, max);
现在可以一口气把所有数据点画出来了
1 private void drawPoints(Graphics g, List<PolarValue> pointList) 2 { 3 // 计算下一点 4 PointF nextPt; 5 for (int i = 0; i < pointList.Count; i++) 6 { 7 if ((i + 1) < pointList.Count) 8 nextPt = getMappedPoint(pointList[i + 1].Angle, pointList[i + 1].Value); 9 else 10 nextPt = getMappedPoint(pointList[0].Angle, pointList[0].Value); 11 12 // 连接当前点和下一点 13 g.DrawLine( 14 Pens.Black, 15 nextPt, 16 getMappedPoint(pointList[i].Angle, pointList[i].Value)); 17 } 18 }
随便添加几个数据
圆圈=3
圆圈=6
圆圈=9
一些变化
好了
我们要怎么做
如果稍微改造下
嗯好了
if(jQuery('#no-reward').text() == 'true') jQuery('.bottom-reward').addClass('hidden');
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?