一个绘制极坐标图、雷达图的简单例子

© 2012-2023 Conmajia
Updated 9th March, 2023
Initiated 24th May, 2012

剧本:豆瓣评分 1.0

某天,boss 接到一单生意,给山寨手机厂做一个天线测试数据的管理控件,主要用来显示山寨天线的方向图,像这样式的:

 

职高肄业多年的 boss 拍着胸口向客户保证没问题,本司最擅长的就是科技与狠活吧啦吧啦。给底下我们几个马仔听得一愣一愣的,心说这傻叉懂个锤子。

兴许是爷的气质过于出众,boss 前脚送走贵客,后脚就站到爷的工位旁。这孙子一边扒拉已经把他那猪头勒出红印的装逼金丝眼镜,一边使唤小爷:小 Q 啊,公司新到一单业务。你是公司的骨干,这个活我想来想去,还是交给你合适。

听听听听,这像话吗?真想抽他两个大嘴巴子。

但是吧,常言道“一分钱难倒英雄汉”,贫穷让爷不得不向资本家低头。这活儿最终还是落到了爷身上。天线图啊,极坐标啊,草他马啊,老子要懂这些玩意儿,还犯得着搁这儿低声下气打螺丝么?可我能咋办,还是得干活儿,不然准被炒鱿鱼卷铺盖滚蛋回老家。

这给爷愁的,正一茬茬抽着闷烟呢,突然灵机一动:这原理不原理的先别管,弄个“看起来”差不多得了。

 极坐标、同心圆、科学原理,你看爷理不理

很多时候,打工仔喜欢“转码”,瞎几把搞搞编程,捣鼓捣鼓“前端”、“界面”之类的,相当一部分原因在于这活儿投入产出比很高:随便弄一下,看着差不多就能交差了。比如现在,我并不懂具体原理甚至都不需要拜读客户需求,只从效果图上我就能先搞一个差不离出来。

用 GDI+ 先来一个画圈圈。

using System.Drawing;
// 在正方形里画一堆圈圈
public void drawCircles(Graphics g, Rectangle r) {
	r.Width = r.Height;
    double d = r.Height;
    // 随便画几个康康
    int n = 5;
    double s = d / n;
    for (int i = 0; i < count; i++) {
    	using (Rectangle ri = new Rectangle (
    		r.X - s / 2 * i, r.Y - s / 2 * i,
    		r.Width - s * i, r.Width - s * i
    	)) {
    		g.DrawEllipse(Pens.Gray, ri);
    	}
    }  
}

画出来是这样的。

 See?这不就有内味儿了吗?下一步整啥好呢?要不弄那图上的辐条吧,从圆心向外的射线,看着中学几何就好使,无非就是圆弧上的点连到圆心呗。

还是那句话,勾股定理,yyds。

// r 是先前画圈圈用到的正方形范围
// n 是辐条数量
public void drawSpokes(Graphics g, Rectangle r, int n) {
	double a = 0.0;			// 从零开始的旋转度数
	double s = 360.0 / n;	// 辐条间距
	for (int i = 0; i < n; i++) {
		g.DrawLine(Pens.Gray,
			r.X + r.Width / 2,		// 起点 x
			r.Y + r.Width / 2,		// 起点 y
			r.X + r.Width / 2 * Math.Cos(a + s * i),	// 终点 x
			r.Y + r.Width / 2 * Math.Sin(a + s * i)	// 终点 y
		);
}

// 偶数辐条看起来会像穿过圆心的直线
drawSpokes(g, Form1.ClientRectangle, 8);

 啊♂~baby~这效果一下子就出来了。

添加刻度文字

接下来好像该添上刻度数字了,可这看起来也太复杂了叭! 

似乎如果我以大圆的半径 r_0 为基础,加上对应文字显示区的半径,我就能找到文字显示的位置 r_1=r_0+\frac{\max(w,h)}{2},其中 wh 是文字的宽和高。以这种方式绘制的文字不会被坐标图挡住,效果其实不错的。 

// 假设要显示的刻度文字为 t,r 是绘制圆圈的区域
// 测量文字大小
Size s = TextRenderer.MeasureText(t, this.Font);
// 计算 r1
double r1 = r.Width + Math.Max(s.Width, s.Height) / 2;
// 绘制文字,假设 a 是这个方向的偏转角度
g.DrawString(t, this.Font, Brushes.Gray, 
	r.X + r1 * Math.Cos(a) - s.Width / 2,	// 文字左上角 x
	r.Y + r1 * Math.Sin(a) - s.Height / 2	// 文字左上角 y
);

这里有一个例子,和上面的效果差不多,大差不差的,意思意思得了,一个月几百块拼什么命啊 😂

搞定交差

枯坐一下午,前列腺炎快给爷整犯了,终于搞定坐标图。现在只要加上数据连线显示的功能就可以交差咯。这不难,甚至有点简单 🐶 因为这只需要计算数据点在图上的位置然后连接邻近的数据点。

public void drawPoints(Graphics g, List<PolarValue> l) {  
    // 计算下一点  
    PointF nextPt;  
    for (int i = 0; i < pointList.Count; i++) {  
        if ((i + 1) < pointList.Count)  
            nextPt = getMappedPoint(pointList[i + 1].Angle, pointList[i + 1].Value);  
        else  
            nextPt = getMappedPoint(pointList[0].Angle, pointList[0].Value);  
        // 连接两点  
        g.DrawLine(Pens.Black,
        	nextPt,
        	getMappedPoint(pointList[i].Angle, pointList[i].Value));
    }  
} 

改下坐标、画笔设置什么的,就可以交差啦!像这样:

 

 

更多的玩法(应付)

忽悠走了这家客户,下次遇到游戏客户让你做角色战力图,可以在这个基础上轻松搞定,谬撒。

甚至遇到特殊行业客户,那也是有可能完成他们的订单的。

(完)

© 2012-2023 Conmajia

评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Conmajia

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值