如何在Bitmap上绘制包含内部线条的椭圆?
在Bitmap上绘制带内部线条的椭圆
嘿,我懂你现在的困扰——已经能画出适配任意Bitmap尺寸的椭圆,但内部线条的坐标总是不对,之前试的外接矩形对角线完全不是想要的效果对吧?别着急,我们一步步来解决这个问题。
核心思路:找准椭圆上的关键点
你用Bmp.Canvas.Ellipse(0, 0, Bmp.Width, Bmp.Height)绘制的椭圆,它的外接矩形是从(0,0)到(Bmp.Width,Bmp.Height),所以椭圆的中心坐标是:
cx := Bmp.Width / 2; cy := Bmp.Height / 2;
椭圆的长半轴a = Bmp.Width / 2,短半轴b = Bmp.Height / 2。内部线条的端点必须是椭圆上的点,这样线条才会和椭圆完美衔接。
常见内部线条的实现方案
根据常见的设计需求,这里给你两种最常用的内部线条实现:
方案1:椭圆的两条对称轴(水平+垂直)
这是最常见的内部线条,穿过椭圆中心,分别平行于Bitmap的宽和高:
// 水平对称轴:从椭圆最左端到最右端 Bmp.Canvas.MoveTo(0, cy); Bmp.Canvas.LineTo(Bmp.Width, cy); // 垂直对称轴:从椭圆最上端到最下端 Bmp.Canvas.MoveTo(cx, 0); Bmp.Canvas.LineTo(cx, Bmp.Height);
方案2:自定义角度的交叉斜线
如果你想要的是特定角度的交叉线条(比如45度),需要用椭圆方程计算两端点的坐标。椭圆上的点满足公式:(x - cx)²/a² + (y - cy)²/b² = 1,以此推导任意角度的端点:
// 以45度斜线为例 var theta := 45 * Pi / 180; // 转成弧度 var x1 := cx + a * Cos(theta); var y1 := cy - b * Sin(theta); var x2 := cx - a * Cos(theta); var y2 := cy + b * Sin(theta); Bmp.Canvas.MoveTo(x1, y1); Bmp.Canvas.LineTo(x2, y2);
替换theta的值,就能画出不同角度的内部线条。
完整示例代码
整合起来的完整绘制代码(以Delphi语法为例):
procedure DrawEllipseWithInnerLines(Bmp: TBitmap); var cx, cy, a, b: Single; theta: Double; x1, y1, x2, y2: Single; begin // 设置画笔和填充样式 Bmp.Canvas.Brush.Style := bsClear; // 透明填充,只画轮廓 Bmp.Canvas.Pen.Color := clBlack; // 绘制外层椭圆 Bmp.Canvas.Ellipse(0, 0, Bmp.Width, Bmp.Height); // 计算椭圆核心参数 cx := Bmp.Width / 2; cy := Bmp.Height / 2; a := cx; b := cy; // 绘制水平+垂直对称轴 Bmp.Canvas.MoveTo(0, cy); Bmp.Canvas.LineTo(Bmp.Width, cy); Bmp.Canvas.MoveTo(cx, 0); Bmp.Canvas.LineTo(cx, Bmp.Height); // 可选:绘制45度交叉斜线 theta := 45 * Pi / 180; x1 := cx + a * Cos(theta); y1 := cy - b * Sin(theta); x2 := cx - a * Cos(theta); y2 := cy + b * Sin(theta); Bmp.Canvas.MoveTo(x1, y1); Bmp.Canvas.LineTo(x2, y2); end;
为什么你之前的方法不对?
你之前用MoveTo(0,0); LineTo(Bmp.Width, Bmp.Height);画的是外接矩形的对角线,但(0,0)和(Bmp.Width,Bmp.Height)这两个点并不在椭圆上——椭圆只经过外接矩形的上下左右中点,所以这条线的两端会超出椭圆边缘,自然和你想要的效果不符。
只要找准椭圆上的端点坐标,就能轻松画出贴合椭圆的内部线条啦!
内容的提问来源于stack exchange,提问作者Ilyes
相关产品推荐
相关产品推荐

